Trap both INT and ERR, but callback got executed multiple times
Clash Royale CLAN TAG#URR8PPP
up vote
3
down vote
favorite
I'm trapping both INT and ERR with the following code
set -ex -o pipefail
dest=$(mktemp -d)
cd "$dest"
trap "echo; echo Clean up; rm -rf $dest" INT ERR
sleep 9999
When I press ^C
the clean up callback is executed multiple times
++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516
++ echo
++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516
Is that expected behavior? Is it possible to execute it only once?
bash trap
add a comment |Â
up vote
3
down vote
favorite
I'm trapping both INT and ERR with the following code
set -ex -o pipefail
dest=$(mktemp -d)
cd "$dest"
trap "echo; echo Clean up; rm -rf $dest" INT ERR
sleep 9999
When I press ^C
the clean up callback is executed multiple times
++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516
++ echo
++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516
Is that expected behavior? Is it possible to execute it only once?
bash trap
@sourcejedi I'm trying to clean up the temp folder either when error happens or user manually stops the script. Never know the EXIT, it does work better :-)
â daisy
May 3 at 23:44
add a comment |Â
up vote
3
down vote
favorite
up vote
3
down vote
favorite
I'm trapping both INT and ERR with the following code
set -ex -o pipefail
dest=$(mktemp -d)
cd "$dest"
trap "echo; echo Clean up; rm -rf $dest" INT ERR
sleep 9999
When I press ^C
the clean up callback is executed multiple times
++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516
++ echo
++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516
Is that expected behavior? Is it possible to execute it only once?
bash trap
I'm trapping both INT and ERR with the following code
set -ex -o pipefail
dest=$(mktemp -d)
cd "$dest"
trap "echo; echo Clean up; rm -rf $dest" INT ERR
sleep 9999
When I press ^C
the clean up callback is executed multiple times
++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516
++ echo
++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516
Is that expected behavior? Is it possible to execute it only once?
bash trap
edited May 3 at 15:47
Jeff Schaller
31.1k846105
31.1k846105
asked May 3 at 15:31
daisy
27.3k45157289
27.3k45157289
@sourcejedi I'm trying to clean up the temp folder either when error happens or user manually stops the script. Never know the EXIT, it does work better :-)
â daisy
May 3 at 23:44
add a comment |Â
@sourcejedi I'm trying to clean up the temp folder either when error happens or user manually stops the script. Never know the EXIT, it does work better :-)
â daisy
May 3 at 23:44
@sourcejedi I'm trying to clean up the temp folder either when error happens or user manually stops the script. Never know the EXIT, it does work better :-)
â daisy
May 3 at 23:44
@sourcejedi I'm trying to clean up the temp folder either when error happens or user manually stops the script. Never know the EXIT, it does work better :-)
â daisy
May 3 at 23:44
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
3
down vote
accepted
You're getting both the INT and ERR signals; SIGINT is handed to sleep
, who exits with a non-zero return code. The non-zero return code then triggers the trap for 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...
An example, to see the separate traps:
set -ex -o pipefail
trap "echo Clean up for INT" INT
trap "echo Clean up for ERR" ERR
sleep 9999
Executing, then 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
As for calling the trap only once, one option would be to reset the ERR
trap while inside the INT
trap:
...
trap "echo Clean up for INT; trap ERR" INT ERR
...
... which results in:
+ trap 'echo Clean up for INT; trap ERR' INT ERR
+ sleep 9999
^C++ echo Clean up for INT
Clean up for INT
++ trap ERR
add a comment |Â
up vote
1
down vote
In bash
, you can simply replace this with trap "my-cleanup-command" EXIT
. This trap will be run when the script exits, including if it is sent SIGINT. In my opinion this is usually the more elegant approach...
Except for the fact that it is bash-specific. EXIT traps are mentioned in POSIX, but the behaviour is not specified. In many other shells, the EXIT trap is not run if the shell exits because of a signal.
https://unix.stackexchange.com/a/57960/29483
Sometimes I really hate shell scripting :).
Looking at the linked answer, I think a less bash-specific way to ensure no code gets run after the first trap would be to exit immediately. It seems there's different ways you might want to do this, but here's the simplest one I would try.
cleanup()
echo "Clean up"
rm -rf "$dest"
trap cleanup EXIT
trap "exit 1" INT ERR
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
accepted
You're getting both the INT and ERR signals; SIGINT is handed to sleep
, who exits with a non-zero return code. The non-zero return code then triggers the trap for 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...
An example, to see the separate traps:
set -ex -o pipefail
trap "echo Clean up for INT" INT
trap "echo Clean up for ERR" ERR
sleep 9999
Executing, then 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
As for calling the trap only once, one option would be to reset the ERR
trap while inside the INT
trap:
...
trap "echo Clean up for INT; trap ERR" INT ERR
...
... which results in:
+ trap 'echo Clean up for INT; trap ERR' INT ERR
+ sleep 9999
^C++ echo Clean up for INT
Clean up for INT
++ trap ERR
add a comment |Â
up vote
3
down vote
accepted
You're getting both the INT and ERR signals; SIGINT is handed to sleep
, who exits with a non-zero return code. The non-zero return code then triggers the trap for 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...
An example, to see the separate traps:
set -ex -o pipefail
trap "echo Clean up for INT" INT
trap "echo Clean up for ERR" ERR
sleep 9999
Executing, then 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
As for calling the trap only once, one option would be to reset the ERR
trap while inside the INT
trap:
...
trap "echo Clean up for INT; trap ERR" INT ERR
...
... which results in:
+ trap 'echo Clean up for INT; trap ERR' INT ERR
+ sleep 9999
^C++ echo Clean up for INT
Clean up for INT
++ trap ERR
add a comment |Â
up vote
3
down vote
accepted
up vote
3
down vote
accepted
You're getting both the INT and ERR signals; SIGINT is handed to sleep
, who exits with a non-zero return code. The non-zero return code then triggers the trap for 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...
An example, to see the separate traps:
set -ex -o pipefail
trap "echo Clean up for INT" INT
trap "echo Clean up for ERR" ERR
sleep 9999
Executing, then 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
As for calling the trap only once, one option would be to reset the ERR
trap while inside the INT
trap:
...
trap "echo Clean up for INT; trap ERR" INT ERR
...
... which results in:
+ trap 'echo Clean up for INT; trap ERR' INT ERR
+ sleep 9999
^C++ echo Clean up for INT
Clean up for INT
++ trap ERR
You're getting both the INT and ERR signals; SIGINT is handed to sleep
, who exits with a non-zero return code. The non-zero return code then triggers the trap for 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...
An example, to see the separate traps:
set -ex -o pipefail
trap "echo Clean up for INT" INT
trap "echo Clean up for ERR" ERR
sleep 9999
Executing, then 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
As for calling the trap only once, one option would be to reset the ERR
trap while inside the INT
trap:
...
trap "echo Clean up for INT; trap ERR" INT ERR
...
... which results in:
+ trap 'echo Clean up for INT; trap ERR' INT ERR
+ sleep 9999
^C++ echo Clean up for INT
Clean up for INT
++ trap ERR
answered May 3 at 16:31
Jeff Schaller
31.1k846105
31.1k846105
add a comment |Â
add a comment |Â
up vote
1
down vote
In bash
, you can simply replace this with trap "my-cleanup-command" EXIT
. This trap will be run when the script exits, including if it is sent SIGINT. In my opinion this is usually the more elegant approach...
Except for the fact that it is bash-specific. EXIT traps are mentioned in POSIX, but the behaviour is not specified. In many other shells, the EXIT trap is not run if the shell exits because of a signal.
https://unix.stackexchange.com/a/57960/29483
Sometimes I really hate shell scripting :).
Looking at the linked answer, I think a less bash-specific way to ensure no code gets run after the first trap would be to exit immediately. It seems there's different ways you might want to do this, but here's the simplest one I would try.
cleanup()
echo "Clean up"
rm -rf "$dest"
trap cleanup EXIT
trap "exit 1" INT ERR
add a comment |Â
up vote
1
down vote
In bash
, you can simply replace this with trap "my-cleanup-command" EXIT
. This trap will be run when the script exits, including if it is sent SIGINT. In my opinion this is usually the more elegant approach...
Except for the fact that it is bash-specific. EXIT traps are mentioned in POSIX, but the behaviour is not specified. In many other shells, the EXIT trap is not run if the shell exits because of a signal.
https://unix.stackexchange.com/a/57960/29483
Sometimes I really hate shell scripting :).
Looking at the linked answer, I think a less bash-specific way to ensure no code gets run after the first trap would be to exit immediately. It seems there's different ways you might want to do this, but here's the simplest one I would try.
cleanup()
echo "Clean up"
rm -rf "$dest"
trap cleanup EXIT
trap "exit 1" INT ERR
add a comment |Â
up vote
1
down vote
up vote
1
down vote
In bash
, you can simply replace this with trap "my-cleanup-command" EXIT
. This trap will be run when the script exits, including if it is sent SIGINT. In my opinion this is usually the more elegant approach...
Except for the fact that it is bash-specific. EXIT traps are mentioned in POSIX, but the behaviour is not specified. In many other shells, the EXIT trap is not run if the shell exits because of a signal.
https://unix.stackexchange.com/a/57960/29483
Sometimes I really hate shell scripting :).
Looking at the linked answer, I think a less bash-specific way to ensure no code gets run after the first trap would be to exit immediately. It seems there's different ways you might want to do this, but here's the simplest one I would try.
cleanup()
echo "Clean up"
rm -rf "$dest"
trap cleanup EXIT
trap "exit 1" INT ERR
In bash
, you can simply replace this with trap "my-cleanup-command" EXIT
. This trap will be run when the script exits, including if it is sent SIGINT. In my opinion this is usually the more elegant approach...
Except for the fact that it is bash-specific. EXIT traps are mentioned in POSIX, but the behaviour is not specified. In many other shells, the EXIT trap is not run if the shell exits because of a signal.
https://unix.stackexchange.com/a/57960/29483
Sometimes I really hate shell scripting :).
Looking at the linked answer, I think a less bash-specific way to ensure no code gets run after the first trap would be to exit immediately. It seems there's different ways you might want to do this, but here's the simplest one I would try.
cleanup()
echo "Clean up"
rm -rf "$dest"
trap cleanup EXIT
trap "exit 1" INT ERR
edited May 4 at 7:51
answered May 4 at 7:40
sourcejedi
18.2k32475
18.2k32475
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f441580%2ftrap-both-int-and-err-but-callback-got-executed-multiple-times%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
@sourcejedi I'm trying to clean up the temp folder either when error happens or user manually stops the script. Never know the EXIT, it does work better :-)
â daisy
May 3 at 23:44