[HN Gopher] Getting decent error reports in Bash when you're usi...
       ___________________________________________________________________
        
       Getting decent error reports in Bash when you're using 'set -e'
        
       Author : zdw
       Score  : 31 points
       Date   : 2025-07-24 04:40 UTC (2 days ago)
        
 (HTM) web link (utcc.utoronto.ca)
 (TXT) w3m dump (utcc.utoronto.ca)
        
       | newAccount2025 wrote:
       | Why don't all shells just do this?
        
         | inetknght wrote:
         | Perhaps you underestimate just how many scripts are poorly
         | written and part of your operating system.
         | 
         | For what it's worth, I think `set -euo pipefail` should be
         | default for every script, and thoroughly checked with
         | shellcheck.net.
        
           | scns wrote:
           | > For what it's worth, I think `set -euo pipefail` should be
           | default for every script, and thoroughly checked with
           | shellcheck.net.
           | 
           | This
        
           | mananaysiempre wrote:
           | Take care that set -o pipefail will not work on older dash
           | (including IIRC the current Ubuntu LTS), and neither will set
           | -o pipefail || true if set -e is in effect. (For some reason
           | that I'm too lazy to investigate, a failing set invocation
           | will crash the script immediately rather than proceed into
           | the second branch.) The best I could think of to
           | opportunistically enable it was to use a subshell:
           | if (set -o pipefail 2>/dev/null); then set -o pipefail; fi
           | 
           | Or you can just target bash, I guess.
           | 
           | (I rather dislike shellcheck because it combines genuine
           | smells with opinions, such as insisting on $(...) instead of
           | `...`. For the same reason, with Python I regularly use
           | pyflakes but can't stand flake8. But to each their own.)
        
           | imcritic wrote:
           | That's a pitfall 60
           | 
           | https://mywiki.wooledge.org/BashPitfalls#set_-euo_pipefail
        
           | eikenberry wrote:
           | What about for `/bin/sh`, i.e. posix compliant shells like
           | dash?
        
         | koolba wrote:
         | Automatically leaking the line number and command, even to
         | stderr is not a sane default.
        
       | Grimeton wrote:
       | You can just do                 trap 'caller 1' ERR
       | 
       | should do the same thing. Also you should set "errtrace" (-E) and
       | possibly "nounset" (-u) and "pipefail".
        
       | o11c wrote:
       | FWIW, I've grown the following which handles a few more cases.
       | For some reason I wasn't aware of `caller` ...
       | set -e              is-oil()         {             test -n
       | "$OIL_VERSION"         }              set -E || is-oil
       | trap 'echo "$BASH_SOURCE:$LINENO: error: failure during early
       | startup! Details unavailable."' ERR
       | magic_exitvalue=$(($(kill -l CONT)+128))              backtrace()
       | {             {                 local status=$?
       | if [ "$status" -eq "$magic_exitvalue" ]                 then
       | echo '(omit backtrace)'                     exit
       | "$magic_exitvalue"                 fi                 local max
       | file line func argc argvi i j                 echo
       | echo 'Panic! Something failed unexpectedly.' "(status $status)"
       | echo 'While executing' "$BASH_COMMAND"                 echo
       | echo Backtrace:                 echo
       | max=${#BASH_LINENO[@]}                 let max-- # The top-most
       | frame is "special".                 argvi=${BASH_ARGC[0]}
       | for ((i=1;i<max;++i))                 do
       | file=${BASH_SOURCE[i]}
       | line=${BASH_LINENO[i-1]}                     func=${FUNCNAME[i]}
       | argc=${BASH_ARGC[i]}                     printf '%s:%d: ... in
       | %q' "$file" "$line" "$func"                     # BASH_ARGV: ...
       | bar foo ...                     # argvi          ^
       | # argvi+argc             ^                     for ((j=argc-1;
       | j>=0; --j))                     do                         printf
       | ' %q' ${BASH_ARGV[argvi+j]}                     done
       | let argvi+=argc || true                     printf '\n'
       | done                      if true                 then
       | file=${BASH_SOURCE[i]}
       | line=${BASH_LINENO[i-1]}                     printf '%s:%d: ...
       | at top level\n' "$file" "$line"                 fi             }
       | >&2             exit "$magic_exitvalue"             unreachable
       | }         shopt -s extdebug         trap 'backtrace' ERR
        
         | edoceo wrote:
         | What the hell. This is cool and all but I'm looking at it as a
         | signal I should move up one tier in language (eg: to Perl, PHP,
         | Python or Ruby)
        
         | chubot wrote:
         | I think you should be able to get rid of the is-oil part - it
         | was implemented last year                   $ osh -c 'set -E;
         | set -o |grep errtrace'         set -o errtrace
         | 
         | I'd be interested in any bug reports if it doesn't behave the
         | same way
         | 
         | (The Oils runtime supports FUNCNAME BASH_SOURCE and all that,
         | but there is room for something much better. It actually has a
         | JSON crash report with a shell stack dump, but it probably
         | needs some polish.)
        
       | bjackman wrote:
       | But trap doesn't "stack" (like e.g. defer in Go) so if you do
       | this it's not available for other purposes like cleanup
        
       ___________________________________________________________________
       (page generated 2025-07-26 23:00 UTC)