Вы получаете сигналы INT и ERR; SIGINT передается sleep
, который завершает работу с кодом возврата, отличным от -нулевым. Ненулевой код возврата, отличный от -, запускает ловушку для 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...
Пример, чтобы увидеть отдельные ловушки:
set -ex -o pipefail
trap "echo Clean up for INT" INT
trap "echo Clean up for ERR" ERR
sleep 9999
Выполнение, затем управление -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
Что касается вызова ловушки только один раз, одним из вариантов будет сбросить ERR
ловушку, находясь внутри ловушки INT
:
...
trap "echo Clean up for INT; trap ERR" INT ERR
...
... что приводит к:
+ trap 'echo Clean up for INT; trap ERR' INT ERR
+ sleep 9999
^C++ echo Clean up for INT
Clean up for INT
++ trap ERR