Como remover de forma confiável todos os arquivos temporários criados em um script?

0

É possível capturar a saída / retorno de uma função? Para um programa que eu poderia fazer

trap -- "clean_this" EXIT

Isso executaria a função clean_this quando o programa sair. Eu gostaria de fazer algo desse tipo quando sair de uma função.

function myfunc() {
  echo "I'm a function"
}

myfunc &
wait $!

Eu executo a função em um subshell, e gostaria de capturar a saída / retorno. Isso é possível?

EDIT1

Aqui está o meu objetivo

Eu tenho um script para gerenciar arquivos temporários:

cat tempfiles.sh

## List of temp files
tmp_tmp_files=()

## Adds a file to the list of temp files
function tmp_add_file() {
  tmp_tmp_files+=("$1")
}

## Resets the list of temp files
function tmp_reset_files() {
  tmp_tmp_files=()
}

## Removes the list of temp files 
function tmp_rm_all() {
  rm -f "${tmp_tmp_files[@]}"
}

## Removes all temp files on exit and sigint
trap "tmp_rm_all" EXIT SIGINT

Aqui está o meu script principal:

cat mscript.sh

source tempfiles.sh

## ## Creates a temp file and writes in it
mfunc() {
  local tempfile=$(mktemp)
  tmp_add_file $tempfile
  echo "something" >> $tempfile
  echo "($BASHPID) - tempfiles: ${tmp_tmp_files[@]}"
}

## Creates a temp file in main shell
mfunc

## Creates a temp file in a subshell
(mfunc)

Eu chamo o script principal:

$ bash mscript.sh 
(92250) - tempfiles: /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj
(92254) - tempfiles: /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.s1iIvtpq

Eu verifico os arquivos temporários:

$ cat /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj
cat: /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj: No such file or directory

$ cat /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.s1iIvtpq 
something

Os arquivos temporários declarados no subshell são perdidos da lista ao sair do programa. Eu gostaria de tê-los removido idealmente no final da função. Ou eu tenho que removê-los especificamente antes de deixar a função, é fácil e me custa mais uma linha:

mfunc() {
  local tempfile=$(mktemp)
  tmp_add_file $tempfile1
  echo "something" >> $tempfile
  echo "tempfiles: ${tmp_tmp_files[@]}"
  ## Process things...
  rm $tempfile1
}

Mas gostaria de saber se existe uma maneira elegante de removê-los automaticamente (os arquivos temporários criados no subshells ), como acontece com trap s ao sair do programa.

Então, minha pergunta é: é possível fazer isso? Quais poderiam ser algumas alternativas?

    
por kaligne 05.07.2017 / 20:12

1 resposta

1

Subshells herdam o ambiente ou parte dele. Parece que quando você executa uma função em um subshell, você não precisa que suas variáveis sejam exportadas (compare: Não é necessário para exportação ao executar funções em subshell ). Pode haver alguns casos em que você precisa de export , mas vamos nos concentrar em seu exemplo.

Sua abordagem é falha e difícil de manter porque a herança é unidirecional. Todo (mfunc) herda tmp_tmp_files e trabalha com sua própria cópia da matriz. Não há como modificar o tmp_tmp_files original usado no script principal. Portanto, o script principal não pode limpar tudo, apenas não possui informações suficientes.

Se você optar por limpar a função subshelled, precisará prestar atenção e separar os arquivos temporários da função dos arquivos temporários do script principal. A remoção prematura do último pode causar falha no script.

Abordagem alternativa: um diretório temporário

  1. Em vez de criar uma matriz, crie um diretório e lembre-se do caminho. Faça isso uma vez no começo e export se precisar:

    tempdir=$(mktemp -d mscript.XXXXXXXXXX)
    
  2. Crie todos os arquivos temporários dentro do diretório temporário, assim:

    tempfile=$(mktemp -p "$tempdir")
    
  3. No final, remova o diretório inteiro, não importando se os arquivos foram criados pelo script principal ou por um subshell, ou até mesmo por algum programa de terceiros. Você pode usar uma armadilha para realizar essa etapa. Simplesmente:

    rm -r "$tempdir"
    
por 06.07.2017 / 06:53