Como excluir um diretório automaticamente quando um executável é morto

9

Frequentemente, executamos um executável que precisa gravar / ler alguns arquivos temporários. Geralmente criamos um diretório temporário, executamos o executável lá e excluímos o diretório quando o script é concluído.

Eu quero excluir o diretório mesmo que o executável seja morto. Eu tentei envolvê-lo em:

#!/bin/bash
dir=$(mktemp -d /tmp/foo.XXXXXXX) && cd $dir && rm -rf $dir
/usr/local/bin/my_binary

Quando my_binarymorrer, o último processo em que o kernel excluirá o diretório, pois o script é o último processo que o mantém inode; mas não consigo criar nenhum arquivo no diretório excluído.

#!/bin/bash
dir=$(mktemp -d /tmp/foo.XXXXXXX) && cd $dir && rm -rf $dir
touch file.txt

saídas touch: file.txt: No such file or directory

O melhor que pude descobrir é excluir o diretório temp quando o processo morrer, captando os sinais mais comuns e executar um processo de limpeza com o cron:

#!/bin/bash
dir=$(mktemp -d /tmp/d.XXXXXX) && cd "$dir" || exit 99
trap 'rm -rf "$dir"' EXIT
/usr/local/bin/my_binary

Existe alguma maneira simples de criar um diretório realmente temporário que é excluído automaticamente quando o binário atual morre, não importa o quê?

Joaquin Cuenca Abela
fonte
1
tenha cuidado que você tem uma pequena janela onde cleanuppode ser executada antes que o mktemp esteja pronto. Você pode querer unset dirantes de montar a armadilha.
Stéphane Chazelas
boa captura, atualizei o script para lidar com isso e com uma falha no mktemp.
Joaquin Cuenca Abela
Eu pensei que a saída era obrigatória. Fixo.
Joaquin Cuenca Abela
Seu último exemplo menciona o cron, mas não tem nada a ver com o cron. Esse último exemplo também é o mais seguro contra falhas. A única coisa que ele não aguenta é a SIGKILL.
194 Patrick Patrick
Não incluí o script cron que estou executando para mantê-lo sucinto. É um achado nesse padrão para corresponder dirs com mais de 1 hora e rm-los. Quero saber se existe alguma solução que também cubra o caso sigkill, ou mesmo um encerramento brutal no meio do script.
Joaquin Cuenca Abela

Respostas:

3

Seu último exemplo é o mais seguro contra falhas.

trap 'rm -rf "$dir"' EXIT

Isso será executado enquanto o próprio shell ainda estiver funcional. Basicamente, o SIGKILL é a única coisa com a qual não vai lidar, já que o shell é terminado à força.
(talvez o SIGSEGV também não tenha tentado, mas pode ser pego)

Se você não deixar o shell limpar sozinho, a única outra alternativa possível é fazer com que o kernel faça isso. Normalmente, isso não é um recurso do kernel, mas há um truque que você pode fazer, mas ele tem seus próprios problemas:

#!/bin/bash
mkdir /tmp/$$
mount -t tmpfs none /tmp/$$
cd /tmp/$$
umount -l /tmp/$$
rmdir /tmp/$$

do_stuff

Basicamente, você cria uma montagem tmpfs e desmonta-a lentamente. Depois que o script estiver pronto, ele será removido.
A desvantagem, além de ser excessivamente complexa, é que, se o script morrer por qualquer motivo antes da desmontagem, você não terá uma montaria por aí.
Isso também usa tmpfs, que consumirá memória. Mas você pode tornar o processo mais complexo e usar um sistema de arquivos em loop e remover o arquivo que o suporta depois de montado.


Em última análise, o trapmelhor é no que diz respeito à simplicidade e segurança, e, a menos que seu script seja regularmente SIGKILLed, eu continuaria com ele.

Patrick
fonte
Importa se a armadilha é colocada antes mktempou depois dela? Eu acho que se a armadilha for colocada logo antes da mktemp, mesmo que o sinal de saída seja recebido após a armadilha e antes da mktemp, tudo o que aconteceria é que um rm -rfcomando seria executado com um argumento vazio, sem realizar nada. Mas se a armadilha estivesse atrás da mktemp, poderia haver uma pequena janela de chance de que o diretório temporário fosse deixado. Ou estou completamente fora da base?
Curinga
1

Você pode usar a espera incorporada para aguardar a conclusão de um trabalho em segundo plano:

blah &
wait
rm -rf $DIR
Matthew Cline
fonte
Mas isso será equivalente a blah; rm -rf $DIR, certo? Ele tem o problema de vazar $ DIR se o script for morto.
Joaquin Cuenca Abela
Se o script filho for morto, o script pai ainda estará disponível para limpeza após ele. Se o script pai também for morto, então sim, o diretório será deixado para trás.
Matthew Cline