A remoção de arquivos temporários criados em exit festa inesperada
-
22-08-2019 - |
Pergunta
Estou criando arquivos temporários de um script bash. Estou excluí-los no final do processamento, mas desde que o script está sendo executado por um longo tempo, se eu matá-lo ou simplesmente CTRL-C durante a corrida, os arquivos temporários não são excluídos.
Existe uma maneira que eu possa pegar esses eventos e limpeza dos arquivos antes de terminar a execução?
Além disso, existe algum tipo de boas práticas para a nomeação e localização desses arquivos temporários?
Atualmente estou não tenho certeza entre usando:
TMP1=`mktemp -p /tmp`
TMP2=`mktemp -p /tmp`
...
e
TMP1=/tmp/`basename $0`1.$$
TMP2=/tmp/`basename $0`2.$$
...
Ou talvez há algumas soluções melhores?
Solução
Você pode definir um " armadilha" para executar em saída ou em um controle-c para limpar.
trap "{ rm -f $LOCKFILE; }" EXIT
Como alternativa, um dos meus unix-ismos favoritos é para abrir um arquivo e, em seguida, excluí-lo enquanto você ainda tem que abrir. As estadias de arquivos no sistema de arquivos e você pode ler e escrever, mas assim que da saída do programa, o arquivo vai embora. Não tenho certeza como você faria isso em bash, no entanto.
BTW: Um argumento que eu vou dar em favor de mktemp em vez de usar sua própria solução: se o usuário antecipa o seu programa vai criar enormes arquivos temporários, ele pode querer TMPDIR
configurada para um local maior, como / var / tmp . mktemp reconhece que, a sua solução enrolado à mão (segunda opção) não. Eu freqüentemente usam TMPDIR=/var/tmp gvim -d foo bar
, por exemplo.
Outras dicas
Eu costumo criar um diretório no qual colocar todos os meus arquivos temporários e, em seguida, imediatamente depois, criar um manipulador EXIT para limpar este diretório quando sai do script.
MYTMPDIR=$(mktemp -d)
trap "rm -rf $MYTMPDIR" EXIT
Se você colocar todos os seus arquivos temporários sob $MYTMPDIR
, em seguida, todos eles serão excluídos quando suas saídas de script na maioria das circunstâncias. Matar um processo com SIGKILL (kill -9) mata o processo de imediato, porém, assim o manipulador de saída não será executado nesse caso.
Você quer usar o href="http://www.gnu.org/software/bash/manual/bashref.html#index-trap" rel="nofollow noreferrer"> comando de Greg para mais detalhes.
Para que sua tempfiles, usando basename $0
é uma boa idéia, bem como proporcionar um modelo que fornece espaço para arquivos temporários suficiente:
tempfile() {
tempprefix=$(basename "$0")
mktemp /tmp/${tempprefix}.XXXXXX
}
TMP1=$(tempfile)
TMP2=$(tempfile)
trap 'rm -f $TMP1 $TMP2' EXIT
Basta ter em mente que a resposta escolhida é bashism
, o que significa solução, como
trap "{ rm -f $LOCKFILE }" EXIT
iria funcionar apenas em bash (ele não vai pegar Ctrl + c se shell é dash
ou sh
clássico), mas se você quiser compatibilidade, em seguida, você ainda precisa para enumerar todos os sinais de que pretende armadilha.
Além disso, mantenha em mente que quando o script sai da armadilha para sinal "0" (aka EXIT) é sempre executado, resultando em execução dupla de comando trap
.
Que a razão para não empilhar todos os sinais em uma linha se não houver sinal EXIT.
Para melhor compreendê-lo olhar seguinte script que irá funcionar em vários sistemas diferentes sem alterações:
#!/bin/sh
on_exit() {
echo 'Cleaning up...(remove tmp files, etc)'
}
on_preExit() {
echo
echo 'Exiting...' # Runs just before actual exit,
# shell will execute EXIT(0) after finishing this function
# that we hook also in on_exit function
exit 2
}
trap on_exit EXIT # EXIT = 0
trap on_preExit HUP INT QUIT TERM STOP PWR # 1 2 3 15 30
sleep 3 # some actual code...
exit
Esta solução vai lhe dar mais controle, pois você pode executar alguns dos seu código em ocorrência de sinal real pouco antes (função preExit
) saída final e se necessário você pode executar um código no sinal de SAÍDA real (fase final de saída)
A alternativa de usar um nome de arquivo previsível com $$ é um furo de segurança e você deve nunca, nunca, nunca pensar em utilizá-lo. Mesmo que seja apenas um script pessoal simples em seu PC de usuário único. É um hábito muito ruim você não deve obter. BugTraq está cheio de incidentes "insegura de arquivo temporário". Consulte aqui , aqui e aqui para obter mais informações sobre o aspecto dos arquivos temporários de segurança.
Eu estava inicialmente pensando em citar as atribuições tmp1 e TMP 2 inseguras, mas pensando que seria, provavelmente, não ser uma boa ideia .
Eu prefiro usar tempfile
que cria um arquivo em / tmp na maneira segura e você não precisa se preocupar com a sua nomeação:
tmp=$(tempfile -s "your_sufix")
trap "rm -f '$tmp'" exit
Você não tem que se preocupar remover esses arquivos tmp criados com mktemp. Eles serão excluídos de qualquer maneira mais tarde.
Use mktemp, se puder, pois gera arquivos mais originais, em seguida, '$$' prefixo. E parece que maneira plataforma mais cruz para criar arquivos temporários, em seguida, explicitamente colocá-los em / tmp.