Você está recebendo os sinais INT e ERR; SIGINT é entregue para sleep
, que sai com um código de retorno diferente de zero. O código de retorno diferente de zero dispara a armadilha para o SIGERR.
If a sigspec is ERR, the command arg is executed whenever a pipeline (which may consist of a single simple command), a list, or a compound command returns a non-zero exit status...
Um exemplo, para ver as armadilhas separadas:
set -ex -o pipefail
trap "echo Clean up for INT" INT
trap "echo Clean up for ERR" ERR
sleep 9999
Executando, depois Control-C:
+ trap 'echo Clean up for INT' INT
+ trap 'echo Clean up for ERR' ERR
+ sleep 9999
^C++ echo Clean up for INT
Clean up for INT
++ echo Clean up for ERR
Clean up for ERR
Como para chamar a interceptação somente uma vez, uma opção seria redefinir a interceptação ERR
enquanto dentro da interceptação INT
:
...
trap "echo Clean up for INT; trap ERR" INT ERR
...
... o que resulta em:
+ trap 'echo Clean up for INT; trap ERR' INT ERR
+ sleep 9999
^C++ echo Clean up for INT
Clean up for INT
++ trap ERR