Live data from Hacker News

Why doesn't Bash’s ‘set -e’ do what I expected? (2021)

mywiki.wooledge.org

91–100 of 114 posts

Re: Why doesn't Bash’s ‘set -e’ do what I expected? (2021)

#91

In the 2000s, I was running extensive sets of simulations and data reduction scripts for a scientific experiment, and I was heavy relying on scripts to run the programs, collect the results, and distribute them over several servers. At first I developed those scripts using bash, but I needed to do math and complex iterations over file names and different parameter files, and I continuously stumbled upon weird behavio…

Have you seen python's sh module?

Re: Why doesn't Bash’s ‘set -e’ do what I expected? (2021)

#92

A lot of commenters suggesting "pipefail" aren't realising the full extent of the problem. Here's an example that might be clearer, from https://david.rothlis.net/shell-set-e This prints “a”, as you’d expect: set -e myfun() { printf a; false; printf b; } myfun printf c ...because the “set -e” terminates the whole script immediately after running the “false” command. But this script prints “a-b-True”, where some peopl…

I call this the "disabled errexit quirk" which leads to the "if myfunc" pitfall:

https://www.oilshell.org/release/latest/doc/error-handling.h...

Here's a demo of how Oil fixes it, which I mentioned in this thread:

    $ osh hn.sh
    a-b-True
You can add shopt --set strict_errexit at the top of your script:

    $ osh -o strict_errexit hn.sh
      if myfun; then
      ^~
    hn.sh:3: errexit was disabled for this construct

    if myfun; then
       ^~~~~
    hn.sh:3: fatal: Can't run a proc while errexit is disabled. Use 'try' or wrap it in a process with $0 myproc
Or just use Oil:

    $ oil hn.sh
    
So Oil is acting like a ShellCheck at runtime, to unconditionally flag this error. It cannot be caught using syntax (which ShellCheck is limited to), because function vs. external executable is a runtime decision.

Re: Why doesn't Bash’s ‘set -e’ do what I expected? (2021)

#93
post #90

A lot of commenters suggesting "pipefail" aren't realising the full extent of the problem. Here's an example that might be clearer, from https://david.rothlis.net/shell-set-e This prints “a”, as you’d expect: set -e myfun() { printf a; false; printf b; } myfun printf c ...because the “set -e” terminates the whole script immediately after running the “false” command. But this script prints “a-b-True”, where some peopl…

It's always been odd that Bash has hundreds of options for controlling its behaviour in non-standard ways, via "set", "shopt" and environment variables, but it's never had an option to make "-e" do the obviously natural behaviour,, I encountered the "you can't enable -e" problem years ago in a complex build system that used Bash to build embedded sysem components. The scripts were all designed on the assumption that…

it's never had an option to make "-e" do the obviously natural behaviour,,

This is harder than it sounds! :) There's arguably not a natural behavior for shell, because $? is overloaded in Unix. It can mean success/failure or it can mean true/false/error.

https://www.oilshell.org/release/latest/doc/error-handling.h...

Oil introduces some new idioms that led you distinguish between the two paradigms, so it's best to change the way you write scripts. It's not something bash can magically fix.

https://www.oilshell.org/release/latest/doc/idioms.html#erro...

That said, just running your scripts with Oil will flag problems, acting like a ShellCheck at runtime, catching things that ShellCheck can't.

See the sibling reply for a demo, and this comment:

https://news.ycombinator.com/item?id=33117337

Re: Why doesn't Bash’s ‘set -e’ do what I expected? (2021)

#94
post #56

I can highly recommend using Shellcheck [0] when writing Bash, it also has extensions for VS Code and other IDE's. It makes writing Bash much easier. [0] https://github.com/koalaman/shellcheck

Agree, this is the way.

ShellCheck is great, but since it works on syntax, it can't catch problems that can only be determined at runtime, like "if myfunc" with set -e on.

Example here: https://news.ycombinator.com/item?id=33122256

Re: Why doesn't Bash’s ‘set -e’ do what I expected? (2021)

#95
post #33

All of these problems are fixed in OSH. It runs your bash scripts but you can also opt into correct error handling. The simple invariant is that it doesn't lose an exit code, and non-zero is fatal by default. See https://www.oilshell.org/release/latest/doc/error-handling.h... Oil 0.10.0 - Can Unix Shell Error Handling Be Fixed Once and For All? https://www.oilshell.org/blog/2022/05/release-0.10.0.html This took quite…

Addendum: You need shopt --set oil:upgrade strict:all to catch this, or just use Oil. Demo here:

https://news.ycombinator.com/item?id=33122256

They're separate things because introducing MORE error handling can make your script incompatible with bash, for people who want to write code that's portable to 2 shells :-/

Re: Why doesn't Bash’s ‘set -e’ do what I expected? (2021)

#96
post #56

I can highly recommend using Shellcheck [0] when writing Bash, it also has extensions for VS Code and other IDE's. It makes writing Bash much easier. [0] https://github.com/koalaman/shellcheck

I moved over to shellharden a while ago. It can actually apply the suggestions it makes. Aside from that, my employer is somewhat disapproving for GPLv3 tools, but MPL that shellharden uses is essentially auto-approved. https://github.com/anordal/shellharden

How is GPLv3 any different from MPL when it comes to use (as opposed to modification or distribution)?

Re: Why doesn't Bash’s ‘set -e’ do what I expected? (2021)

#97

In the 2000s, I was running extensive sets of simulations and data reduction scripts for a scientific experiment, and I was heavy relying on scripts to run the programs, collect the results, and distribute them over several servers. At first I developed those scripts using bash, but I needed to do math and complex iterations over file names and different parameter files, and I continuously stumbled upon weird behavio…

I was very surprised to see scsh mentioned in this thread. I'm glad to read that it was of some use for you.

Re: Why doesn't Bash’s ‘set -e’ do what I expected? (2021)

#98
This is really interesting. The case pointed out in Ex.3 is pretty hilarious:

(from the bash manual)

              The ERR trap [same rules as set -e] is not executed if the
              failed command is part of the command list immediately following
              a  while  or until keyword, part of the test in an if statement,
              part of a command executed in a && or || list except the command
              following the final && or || [...]

Re: Why doesn't Bash’s ‘set -e’ do what I expected? (2021)

#99
post #37
post #33

All of these problems are fixed in OSH. It runs your bash scripts but you can also opt into correct error handling. The simple invariant is that it doesn't lose an exit code, and non-zero is fatal by default. See https://www.oilshell.org/release/latest/doc/error-handling.h... Oil 0.10.0 - Can Unix Shell Error Handling Be Fixed Once and For All? https://www.oilshell.org/blog/2022/05/release-0.10.0.html This took quite…

Never used OilShell (OSH) before, but this opening line on their home page struck me: > … and it's a new language for Python and JavaScript users who avoid shell! Why not work towards using python/JavaScript as shell languages? There was a HN thread a few days ago on Xonsh, the main python attempt at this which looks nice to me, which naturally got a lot of anti-anti-bash energy. But if we want better shell ergonomic…

> Why not work towards using python/JavaScript as shell languages?

I always refer to this awesome answer to that question:

https://stackoverflow.com/a/3640403/512904

Re: Why doesn't Bash’s ‘set -e’ do what I expected? (2021)

#100

A lot of commenters suggesting "pipefail" aren't realising the full extent of the problem. Here's an example that might be clearer, from https://david.rothlis.net/shell-set-e This prints “a”, as you’d expect: set -e myfun() { printf a; false; printf b; } myfun printf c ...because the “set -e” terminates the whole script immediately after running the “false” command. But this script prints “a-b-True”, where some peopl…

This is a separate problem from the pipe one. Anyway, if you're looking that behavior, you need to use `&&` instead of the semicolon.
Post reply on HN