armadilha de saída no dash vs ksh e bash

armadilha de saída no dash vs ksh e bash

Aqui está um script simples que configura um diretório temporário no diretório atual e uma armadilha para excluí-lo na saída.

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

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

Responder1

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

Somente bash, ksh88, ksh93e mkshse comportam de outra forma.

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

Ele diz que EXITa ação trap deve ser avaliada quando exité invocada, mas AFAICT, nem mesmo diz, por exemplo, se deve ser avaliada quando o shell sai como resultado de set -eou set -ucondições de erro, como erros de sintaxe ou falhas internas especiais.

Para poder executar EXITo trap ao receber um sinal, o shell precisaria instalar um manipulador nesse sinal.

É isso que ksh, mkshe bashfaz, mas a lista de sinais que eles tratam é diferente entre as três implementações. Os únicos sinais comuns entre todos os 3 parecem ser INT,,, e .QUITTERMALRMHUP

Se você quiser que a EXITarmadilha seja executada com base em alguns sinais, a maneira portátil seria lidar com esses sinais você mesmo:

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

Essa abordagem, entretanto, não funciona com zsh, que não executa EXITtrap se exitfor chamado de um manipulador de trap.

Ele também não relata sua morte por sinal aos seus pais.

Então, em vez disso, 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, tenha cuidado, pois se mais sinais chegarem enquanto você estiver executando cleanup, cleanupele poderá ser executado novamente. Você pode querer ter certeza de que cleanupfunciona corretamente se invocado várias vezes e/ou ignorar sinais durante sua execução.

Responder2

Aviso: exitnão é garantido que funcione, você deve usarEXIT

Dado que o padrão POSIX não define se o EXITtrap também deve ser executado em caso de sinal e dado o fato do Bourne Shell não chamar o EXITtrap no caso que você mencionou, é óbvio que você está entrandonão especificadocomportamento.

informação relacionada