Estou criando arquivos temporários de um script bash. Estou excluindo-os no final do processamento, mas como o script está em execução há um bom tempo, se eu encerrá-lo ou simplesmente CTRL-C durante a execução, os arquivos temporários não serão excluídos.
Existe uma maneira de capturar esses eventos e limpar os arquivos antes que a execução termine?
Além disso, existe algum tipo de prática recomendada para a nomenclatura e a localização desses arquivos temporários?
No momento, não tenho certeza entre usar:
TMP1=`mktemp -p /tmp`
TMP2=`mktemp -p /tmp`
...
e
TMP1=/tmp/`basename $0`1.$$
TMP2=/tmp/`basename $0`2.$$
...
Ou talvez existam soluções melhores?
bash
exit
temporary-files
skinp
fonte
fonte
Respostas:
Você pode definir uma " armadilha " para executar na saída ou em um control-c para limpar.
Como alternativa, um dos meus unix-isms favoritos é abrir um arquivo e excluí-lo enquanto ainda estiver aberto. O arquivo permanece no sistema de arquivos e você pode lê-lo e gravá-lo, mas assim que o programa termina, o arquivo desaparece. Não tenho certeza de como você faria isso no bash, no entanto.
BTW: Um argumento a favor do mktemp em vez de usar sua própria solução: se o usuário antecipar que seu programa criará arquivos temporários enormes, ele pode querer definir
TMPDIR
para algum lugar maior, como / var / tmp. mktemp reconhece isso, sua solução enrolada à mão (segunda opção) não. Eu uso freqüentementeTMPDIR=/var/tmp gvim -d foo bar
, por exemplo.fonte
exec 5<>$TMPFILE
descritor de arquivo laços 5 a US $ tmpfile como leitura e escrita, e você pode usar<&5
,>&5
e/proc/$$/fd/5
(Linux) depois disso. O único problema é que o Bash não temseek
função ...trap
: não há como interceptarSIGKILL
(por design, uma vez que termina imediatamente a execução). Portanto, se isso acontecer, tenha um plano alternativo (comotmpreaper
). Em segundo lugar, as armadilhas não são cumulativas - se você tiver mais de uma ação a realizar, todas elas devem estar notrap
comando. Uma maneira de lidar com várias ações de limpeza é definir uma função (e você pode redefini-la como seu programa procede, se necessário) e referência que:trap cleanup_function EXIT
.trap "rm -f $LOCKFILE" EXIT
ou receberia um erro inesperado de fim de arquivo.Normalmente crio um diretório no qual coloco todos os meus arquivos temporários e, imediatamente depois, crio um manipulador EXIT para limpar esse diretório quando o script for encerrado.
Se você colocar todos os seus arquivos temporários em
$MYTMPDIR
, todos eles serão excluídos quando o script for encerrado na maioria das circunstâncias. Eliminar um processo com SIGKILL (kill -9) elimina o processo imediatamente, portanto, seu manipulador EXIT não será executado nesse caso.fonte
Você deseja usar o comando trap para lidar com a saída do script ou sinais como CTRL-C. Consulte o Wiki de Greg para obter detalhes.
Para seus arquivos temporários,
basename $0
é uma boa ideia usar , além de fornecer um modelo que forneça espaço para arquivos temporários suficientes:fonte
$()
. Adicionadas as aspas duplas também.tempfile
comando, enquanto todos os sistemas modernos razoáveis que conheço têm ummktemp
comando.Basta ter em mente que a resposta escolhida é
bashism
, o que significa solução comofuncionaria apenas no bash (não irá capturar Ctrl + C se o shell for
dash
ou clássicosh
), mas se você quiser compatibilidade, então ainda precisa enumerar todos os sinais que deseja capturar.Também tenha em mente que, quando o script sai, a armadilha do sinal "0" (também conhecida como EXIT) é sempre executada, resultando em dupla execução do
trap
comando.Essa é a razão para não empilhar todos os sinais em uma linha se houver sinal EXIT.
Para melhor entendê-lo, observe o seguinte script que funcionará em diferentes sistemas sem alterações:
Esta solução lhe dará mais controle, pois você pode executar parte do seu código na ocorrência do sinal real antes da saída final (
preExit
função) e, se necessário, pode executar algum código no sinal EXIT real (estágio final de saída)fonte
A alternativa de usar um nome de arquivo previsível com $$ é uma brecha de segurança e você nunca, jamais, deve pensar em usá-lo. Mesmo que seja apenas um simples script pessoal em seu PC de usuário único. É um péssimo hábito que você não deve adquirir. BugTraq está cheio de incidentes de "arquivo temporário inseguro". Consulte aqui , aqui e aqui para obter mais informações sobre o aspecto de segurança de arquivos temporários.
Eu estava inicialmente pensando em citar as atribuições inseguras de TMP1 e TMP2, mas pensando bem, provavelmente não seria uma boa ideia .
fonte
Eu prefiro usar o
tempfile
que cria um arquivo em / tmp de maneira segura e você não precisa se preocupar com sua nomenclatura:fonte
Não posso acreditar que tantas pessoas presumam que um nome de arquivo não conterá um espaço. O mundo irá travar se $ TMPDIR for atribuído ao "diretório temporário".
Espaços e outros caracteres especiais como aspas simples e retornos de carro em nomes de arquivo devem ser considerados no código como um requisito para um hábito de programação decente.
fonte
trap 'rm -f "${zTemp}"' EXIT
corretamente de espaços e outros caracteres especiais, a solução desta resposta não adia a avaliação dezTemp
. Portanto, não há necessidade de se preocupar com o valor dezTemp
ser alterado posteriormente no script. Além disso,zTemp
pode ser declarado local para uma função; não precisa ser uma variável de script global.${parameter@operator}
expansões foram adicionadas no Bash 4.4 (lançado em setembro de 2016).Você não precisa se preocupar em remover os arquivos tmp criados com mktemp. Eles serão excluídos de qualquer maneira mais tarde.
Use mktemp se puder, pois ele gera mais arquivos exclusivos do que o prefixo '$$'. E parece uma forma mais multiplataforma de criar arquivos temporários e, em seguida, colocá-los explicitamente em / tmp.
fonte