exit trap em dash vs ksh e bash

4

Aqui está um script simples que configura um diretório temporário no diretório atual e um trap para deletá-lo ao sair.

#filename: script   
set -x  
trap 'rm -rf "$d"' exit
d='TMPDIR=$PWD mktemp -d'
"$@"

Se eu fizer ksh script sleep 100 ou bash script sleep 100 e interromper com C-C , a armadilha será executada e o diretório será excluído. Não funciona com dash . Por quê? Isso é um bug ou comportamento pretendido?

    
por PSkocik 04.11.2015 / 13:21

2 respostas

11

zsh , pdksh (embora versões não recentes de mksh sejam derivadas disso), yash , o shell Bourne se comporta como dash .

Somente bash , ksh88 , ksh93 e mksh se comportarão de outra forma.

A especificação POSIX não está clara sobre qual deve ser o comportamento correto, mas não há nada lá que diga que o shell está autorizado a sobrescrever o manipulador padrão para o sinal SIGINT (ou outro).

Ele diz que a ação EXIT trap deve ser avaliada quando exit é invocado, mas AFAICT, nem sequer diz por exemplo se deve ser avaliado quando o shell sai como resultado de set -e ou set -u ou condições de erro, como erros de sintaxe ou falhas de especialidade.

Para poder executar a interceptação EXIT na recepção de um sinal, o shell precisaria instalar um manipulador naquele sinal.

Isso é o que ksh , mksh e bash fazem, mas a lista de sinais que eles manipulam é diferente entre as três implementações. Os únicos sinais comuns entre todos os 3 parecem ser INT, QUIT, TERM, ALRM e HUP.

Se você quiser que o trap EXIT funcione com alguns sinais, o modo portátil seria lidar com esses sinais:

trap 'exit 1' INT HUP QUIT TERM ALRM USR1
trap 'cleanup' EXIT

Essa abordagem, no entanto, não funciona com zsh , que não executa a interceptação EXIT se exit for chamado de um manipulador de interceptações.

Ele também não informa sua morte por sinal para seus pais.

Então, você poderia fazer:

for sig in INT QUIT HUP TERM ALRM USR1; do
  trap "
    cleanup
    trap - $sig EXIT
    kill -s $sig "'"$$"' "$sig"
done
trap cleanup EXIT

Agora, cuidado, porém, se mais sinais chegarem enquanto você estiver executando cleanup , cleanup poderá ser executado novamente. Você pode querer garantir que seu cleanup funcione corretamente se invocado várias vezes e / ou ignorar sinais durante sua execução.

    
por 04.11.2015 / 14:21
1

Aviso: não é garantido que exit funcione, você deve usar EXIT

Dado que o padrão POSIX não define se o EXIT trap também deve ser executado no caso de um sinal e dado o fato de que o Bourne Shell não chama o EXIT trap no caso que você mencionou, é É óbvio que você está inserindo um comportamento não especificado .

    
por 04.11.2015 / 14:13

Tags