4

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?

1
  • 1
    Good Q except for the smileys (I'm feeling grumpy;->) but wasn't sure if S.O. was now converting some mistaken shell syntax of yours to a smiley. Good luck to all! Commented Jan 12, 2017 at 4:31

1 Answer 1

6

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.

Sign up to request clarification or add additional context in comments.

2 Comments

that worked beautifully. very informative. thank you
FYI ... "set -o pipefail" seems to work as well. "used to propagate errors so that the return value of the pipeline command is non-zero if one of the preceding commands exited with a non-zero status" stackoverflow.com/a/19622300/2341218

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.