-1

i am writing a shell script which should exit in some cases, my current code is:

 set -e 

    Running A || (echo "failed to run A"; exit 1)
    Running B || (echo "failed to run B"; exit 1)
    if Condition C
    then 
       Running D || (echo "failed to run D"; exit 1)
    ....

and it worked as expected, it passes if A/B runs well, echo message for me if A or B failed, but i have not tested D failed yet. My understanding is if A or B failed, it will go to code after "||", echo error, then exit subshell and return false. So the whole line is "false||false" so it exited because i have "set -e" at the beginning. But then i read How to exit if a command failed? it mentioned "set -e" is dangerous because it won't be triggered inside if statement, so does it mean that it won't work if my "Running D" command fails?(meanning it won't exit and will continue executing next command). Also, i tried to use {} as the above post suggests, but it's weird. if i change it to:

#set -e
Running A || {exit 1}

it's correct, meaning if A successes, continue next command, if A fails, exit script. But if i change to

#set -e
Running A || {echo "running A failed";exit 1}

it always exited here no matter A successes or fails.

What is wrong? Also i am a bit confused now which is the best way to exit in my case? i should use "set -e" or "{}"? Thanks!

oguz ismail
  • 1
  • 16
  • 47
  • 69
code3
  • 81
  • 1
  • 8

1 Answers1

0

Using ( ) spawns a sub-shell, while using { } does not, the latter allowing the enclosed exit to directly terminate your script.

The group command syntax using { } is a little picky about syntax. You have to separate the brace characters from others with whitespace. You also need to use a trailing semicolon after the last command in the group.

Given the above constraints, try changing:

Running A || {echo "running A failed";exit 1}

... to:

Running A || { echo "running A failed";exit 1; }
rtx13
  • 2,580
  • 1
  • 6
  • 22
  • thanks! it worked. Also, is it good practice to use "{}" or to use "set -e"? Will "set -e" miss the failure in if condition? Thanks! – code3 May 20 '20 at 05:13
  • @code3 In your example with `set -e` active, _any_ failure when evaluating `Condition C` will not terminate the script, rather it will simply result in a `false` condition for the `if` statement (so it may move on to an `elif` or `else` clause). This may or may not be what you want. Failures in `Running D` (the _body_ of the `if` statement) will definitely be caught by `set -e` and will terminate the script. Generally it is less error-prone and there are fewer surprises when using `|| exit` rather than `set -e`. – rtx13 May 20 '20 at 12:14