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 100
ou bash script sleep 100
interromper com, C-C
a 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 mksh
derivadas disso), yash
, o shell Bourne se comporta como dash
.
Somente bash
, ksh88
, ksh93
e mksh
se 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 EXIT
a 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 -e
ou set -u
condições de erro, como erros de sintaxe ou falhas internas especiais.
Para poder executar EXIT
o trap ao receber um sinal, o shell precisaria instalar um manipulador nesse sinal.
É isso que ksh
, mksh
e bash
faz, 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 .QUIT
TERM
ALRM
HUP
Se você quiser que a EXIT
armadilha 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 EXIT
trap se exit
for 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
, cleanup
ele poderá ser executado novamente. Você pode querer ter certeza de que cleanup
funciona corretamente se invocado várias vezes e/ou ignorar sinais durante sua execução.
Responder2
Aviso: exit
não é garantido que funcione, você deve usarEXIT
Dado que o padrão POSIX não define se o EXIT
trap também deve ser executado em caso de sinal e dado o fato do Bourne Shell não chamar o EXIT
trap no caso que você mencionou, é óbvio que você está entrandonão especificadocomportamento.