Reputation: 3819
I have a need to group commands using curly braces in my shell script so that I can direct their output to separate log files like so ...
😈 >cat how-to-exit-script-from-within-curly-braces.sh
{
printf "%d\n" 1
printf "%d\n" 2
} | tee a.log
{
printf "%d\n" 3
printf "%d\n" 4
} | tee b.log
😈 >./how-to-exit-script-from-within-curly-braces.sh
1
2
3
4
😈 >cat a.log
1
2
😈 >cat b.log
3
4
😈 >
Although I have added the curly braced to facilitate logging, I would still like the script to exit when the exit command is invoked inside the curly braces.
It does not do so of course. It only exits the curly braces and then continues on executing the remainder of the script like so ...
😈 >cat how-to-exit-script-from-within-curly-braces.sh
{
printf "%d\n" 1
exit
printf "%d\n" 2
} | tee a.log
{
printf "%d\n" 3
printf "%d\n" 4
} | tee b.log
😈 >./how-to-exit-script-from-within-curly-braces.sh
1
3
4
😈 >cat a.log
1
😈 >cat b.log
3
4
😈 >
making the exit code non-zero and adding "set -e" to the script does not appear to work ...
😈 >cat how-to-exit-script-from-within-curly-braces.sh
set -e
{
printf "%d\n" 1
exit 1
printf "%d\n" 2
} | tee a.log
{
printf "%d\n" 3
printf "%d\n" 4
} | tee b.log
😈 >./how-to-exit-script-from-within-curly-braces.sh
1
3
4
😈 >cat a.log
1
😈 >cat b.log
3
4
😈 >
Is there a way to force the exit of the script from within the curly braces?
Upvotes: 4
Views: 1379
Reputation: 123470
There is no problem with exit
and curly braces:
{
exit
}
echo "This will never run."
However, there is a problem with exit
and pipes, and that's what you're running into:
exit | exit
echo "Still alive"
In bash by default, each stage in a pipeline runs in a subshell, and exit
can only exit that subshell. In your case, you can use redirection and process substitution instead:
{
printf "%d\n" 1
exit 1
printf "%d\n" 2
} > >(tee a.log)
echo "This will not run"
Note that this is bash specific code, and will not work in sh
(such as when using #!/bin/sh
or sh myscript
). You have to use bash
instead.
Upvotes: 6