27

At first this was a bit funny, like playing "Bash Roulette" ...but now it's getting old lol

Any command in my terminal that exits with non-zero code closes my terminal window

I was told that perhaps I have set -e set in some bash script somewhere that my terminal sources.

I have checked .bash_profile / .bashrc / .profile and it doesn't look like set -e is in there.

Would there be any other obvious culprits?

  • 8
    Execute a set +e, does it repair the problem? If so, which I assume, then you need to keep looking for that set -e. It could be in the global versions of these files under /etc, or in any other script sourced from them. Move your config files away, if the problem is fixed then add back the lines in smaller chunks to see where it breaks. – egmont Nov 27 '17 at 23:21
  • 4
    PS4=' ${BASH_SOURCE}:$LINENO: ' bash -lixc true |& grep -e set -e trap could be informative. – muru Nov 28 '17 at 03:23
  • 1
    You can inspect the set of currently enabled shell flags with the special variable - like so: echo $-. – David Foerster Nov 28 '17 at 12:57
  • What if set +e does not fix the problem? – jewbix.cube Oct 13 '23 at 02:30

3 Answers3

24

Alright, so indeed, it was a wayward set -e that caused my trouble.

The way I found the set -e was using bash -lx

The best thing to do would be to use:

bash -lx > lx.log 2>&1

then open that log file and do a search for set...

once you find that wayward set -e you can remove that line and your problem should be gone! (Machine restart might be a good idea tho).

In my case, the set -e was in a file that .bash_profile sources, but the line was not in .bash_profile itself.

  • 4
    Things that are safe to source in your shell is a much smaller set than just "random shell scripts". -e can be useful in actual scripts, for dumb error checking. (Or to make sure you didn't forget to error-check anything.) – Peter Cordes Nov 28 '17 at 10:17
  • Apparently that's case...i wish there was something like global set -e so that set -e only affects the containing script – Alexander Mills Nov 28 '17 at 15:33
  • @AlexanderMills, to do that, you could check $- to check for the flag in the inner script and restore its state at the end, or just reset it at the main script if you know you have sourced scripts that would set it – ilkkachu Nov 28 '17 at 15:39
  • So I guess local set -e could only be used in a bash function? – Alexander Mills Nov 28 '17 at 16:14
14

If you just want to solve the problem, include set +e in your .bashrc — at the end.

You can go digging—there are a lot of other places where a set -e might be—but that will take care of the lot.

If, however, the set -e is part of your $PROMPT_COMMAND then the above will not work. Try printf '%s\n' "$PROMPT_COMMAND" and see what's in it.

Wildcard
  • 36,499
  • 1
    on my machine, when I open a terminal, printf '%s\n' "$PROMPT_COMMAND" yields just whitespace, nothing there – Alexander Mills Nov 27 '17 at 23:33
  • @AlexanderMills, then that's not what your problem is. One common use for $PROMPT_COMMAND is to update the terminal tab name or window name; MacOS X and Ubuntu both do this. See https://apple.stackexchange.com/q/220641/151730 for data on this for Mac. – Wildcard Nov 28 '17 at 04:00
  • I found an answer to the problem and added my own answer, set +e didn't work, perhaps because it was before the set -e call in my sourced bash files. – Alexander Mills Nov 28 '17 at 05:28
  • 1
    @AlexanderMills, yes, I thought that was implicit. I meant to append set +e to your .bashrc, not put it in at the start. I've made that explicit in my answer now. Good that you found the source! – Wildcard Nov 28 '17 at 05:31
  • Yeah, set +e is just a band-aid obviously, but you stated that – Alexander Mills Nov 28 '17 at 05:43
  • Note that even if set +e is appended to .bashrc there might still be a command in between (after set -e is called) that causes an early exit from non zero return status. – John B Nov 28 '17 at 11:31
  • @JohnB yes, but that wouldn't give you "bash roulette" as described. – Wildcard Nov 28 '17 at 11:55
2

In my case, the set -e was not in any of my bash startups and appending set +e to my .bashrc was not fixing it.

It turns out the set -e was in a bash script that I frequently run for my project, and I was running that script using . ./my-dev-script.sh so that it would honor my bash aliases.

What I didn't realize is running it with that extra . in front was also causing the bash options in the script to carry over into all my regular terminal sessions.

I need a new solution for running a bash script that honors my personal bash aliases, but at least I found the source of the rogue set -e. Just running it normally with ./my-dev-script.sh prevents the frustrating "Bash Roulette" scenario.