bash trap em funções de segundo plano

1

Chamando uma função em um script em segundo plano - usando '&', a função é chamada em subshell . Quando a função termina, o subshell termina, com um status de saída. Eu gostaria de capturar o sinal de saída de subshell para cancelar automaticamente os arquivos de log. Meu script de teste é o seguinte:

$ cat mscript.sh 
#!/usr/bin/env sh

mout="log.out"
rm -f $mout

# My testing log files
tmps=(first.tmp second.tmp third.tmp)

# Traps exit signal to delete the logfile upon exiting.
mtrap_tmp() {
  local ftmp="$1"
  # I create the tep file here:
  echo "init $ftmp" &>> $ftmp
  echo -e "\n($BASHPID) trapping \"$ftmp\"..." &>> $mout
  ## Here I trap the signal, to delete the temporary file.
  trap "rm -f \"$ftmp\"" EXIT
  echo -e "  trapped tmp file \"$ftmp\" to rm" &>> $mout
  echo "  $(ls -l $ftmp)" &>> $mout
}

# I trap the first and second log files within the script's pid. 
# Then I trap the third file in a subshell:
mtrap_tmp ${tmps[0]}
mtrap_tmp ${tmps[1]}
mtrap_tmp ${tmps[2]} &
wait $!

# Here I want to check the temp files do exist. 
# I expect the third file to be trapped in a subshell, 
# and hence to be non-existent once the subshell ends, 
# which should have happened after the 'wait $!':

for i in ${tmps[@]}; do
  echo -e "\nfinal check $i:" &>> $mout
  ls -l ${i} &>> $mout
done

echo "done"
exit 0 

A saída é a seguinte:

$  cat log.out 

(10598) trapping "first.tmp"...
  trapped tmp file "first.tmp" to rm
  -rw-rw-r-- 1 anadin ctgb 15 Jul  4 15:54 first.tmp

(10598) trapping "second.tmp"...
  trapped tmp file "second.tmp" to rm
  -rw-rw-r-- 1 anadin ctgb 16 Jul  4  2017 second.tmp

(10602) trapping "third.tmp"...
  trapped tmp file "third.tmp" to rm
  -rw-rw-r-- 1 anadin ctgb 15 Jul  4  2017 third.tmp

final check first.tmp:
-rw-rw-r-- 1 anadin ctgb 15 Jul  4 15:54 first.tmp

final check second.tmp:
-rw-rw-r-- 1 anadin ctgb 16 Jul  4 15:54 second.tmp

final check third.tmp:
-rw-rw-r-- 1 anadin ctgb 15 Jul  4 15:54 third.tmp

Eu esperava que o arquivo third.tmp fosse excluído antes do final do script. O estranho é que apenas o segundo arquivo.tmp foi cancelado:

$ ls *.tmp
first.tmp  third.tmp

Espero que o terceiro arquivo seja removido apenas após a saída da função. Espero que os dois outros arquivos sejam removidos após a conclusão do script.

O que está errado aqui?

    
por kaligne 04.07.2017 / 15:58

1 resposta

0

Como a terceira armadilha é criada em um subshell, ela também é ativada / executada quando esse shell sai, tentando remover o terceiro arquivo antes que ele seja criado. Portanto, o terceiro arquivo existe depois que o script é feito.

Toda vez que você trap […] SIGNAL você sobrescreve a armadilha para aquele sinal, então somente a segunda armadilha sobrevive no topo. Portanto, o primeiro arquivo existe depois que o script é feito.

Um echo no trap ou possivelmente set -o xtrace mostraria melhor o que está acontecendo. Você também pode executar trap por conta própria para ver quais traps estão em vigor.

    
por 04.07.2017 / 16:12