0
#!/bin/bash
set -e
set -o pipefail
shopt -s inherit_errexit

declare _x=`command-with-error`
echo "_x=${_x}"

Run the script shows:

bash xx.sh
xx.sh: line 6: command-with-error: command not found
_x=

Apparently line 6 did not exit the shell. What option should I use to make the script exit when the subshell command on declare line fails?

Wang
  • 7,250
  • 4
  • 35
  • 66
  • 1
    I assume you've already read [BashFAQ #105](https://mywiki.wooledge.org/BashFAQ/105)? `errexit` behavior is wildly different between individual shell releases, not to mention between different shells and even on different calling contexts (`set -e` changes behavior of code in a function based on whether the exit status of the function itself _or anything else upwards in the call stack_ is branched on); it's hard to audit code for correctness in its presence, much harder than it is to simply audit for explicit error handling (like a `|| exit` or `|| return` after each individual command). – Charles Duffy Sep 10 '21 at 21:18
  • In the specific case, `declare _x=$(anything)` is an antipattern. Make `declare _x` one command, and `_x=$(anything)` a second one. Same thing goes for `local` or `typeset`. – Charles Duffy Sep 10 '21 at 21:21
  • I recommend you check you script with https://shellcheck.net/ it would have pointed you at why you have this issue: [SC2155 Declare and assign separately to avoid masking return values.](https://github.com/koalaman/shellcheck/wiki/SC2155) – Léa Gris Sep 10 '21 at 21:41

1 Answers1

2

The successful exit status of declare is overriding the unsuccessful exit status of command-with-error.

Break it into two separate commands:

declare _x
_x=$(command-with-error)

...as you can see running correctly (which is to say, without writing anything to stdout) at https://ideone.com/TGyFCZ

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • Just to clarify, `set -e` is the reason this answer works, right? You can remove `shopt -s inherit_errexit` and the error will still be caught, right? – 425nesp Jan 06 '23 at 17:17
  • @425nesp, for purposes of how `$?` is set it works the same way whether or not `set -e` is in use; `set -e` just adds an implicit `|| exit` in some cases ([fewer than people often think](https://mywiki.wooledge.org/BashFAQ/105#Exercises), which is part of why relying on it is such a bad idea). The safer approach is to write `declare _x; _x=$(command-with-error) || exit` (or `|| return` if inside a function) – Charles Duffy Jan 12 '23 at 21:12