Why is SHLVL initially 2 in Ubuntu 16.10 (but not earlier versions)?

I just upgraded to Ubuntu 16.10. Why does $SHLVL now start with a value of 2 when I open the Gnome terminal? This was not the case in 16.04.

1

4 Answers

This unfortunate bug was introduced in Ubuntu 16.10.

For a bash work-around, see

If you run an application that does not start a shell, but can give you access to the environment variables, you'll see that the environment already contains SHLVL with a value of 1. For instance, I installed and ran IDLE3, ran import os and checked the value of os.environ['SHLVL'], which turned out to be 1.

Now, SHLVL is also set and incremented in scripts, so, if I ran a bash script containing echo $SHLVL in a terminal, I'd get 3.

However, the consoles/TTYs still have a SHLVL of 1, so the culprit must be somewhere in the GUI start process. I don't know what exactly it would be, but my guess is Unity. In GNOME Shell, for example, this does not happen. Somewhere in that startup of Unity, a bash script is probably present.

Following up from my comment in the original question (and, this is not an answer per se, since I can't answer "why", but I can verify the new behavior exists):

This change breaks backward compatibility. Now, no matter how you open a terminal/bash in ubuntu, they all start at SHLVL=2 Though, I'm not sure if this is a Ubuntu-specific issue, or due to using Unity. If one happens to have logic that does something specific when the parent shell exits (eg saving state), that will now never execute.

(Also, I'm not sure if ~/.bash_logout is being called at the same time as before, either. Not sure, can't remember. The unpredictability of depending on this behavior is why we use custom logic depending on shell-depth. The only way I can trigger ~/.bash_logout it is by explicitly exiting a shell started with bash -l; all other Ubuntu bash shells aren't login shells. It could have always been this way.)

In experimenting with ways to try to deduce the true SHLVL, trying to see if there is another way to tell a "parent" vs subshell, this might work (checking for ubuntu is optional, if this is in fact a Unity-specific bug feature.)

$ echo $SHLVL 2
$ my_shlvl() { lsb_release -i | grep -qi ubuntu && pstree -s $$ | grep -o bash | wc -l }
$ export -f my_shlvl
$ my_shlvl 1
$ bash
$ echo $SHLVL 3
$ my_shlvl 2
$ exit
$ my_shlvl 1

This hack work-around is very gnu/linux specific (e.g. assumes pstree, lsb_release exist), but afaik this problem exists only on a subset of linux distros (so far, just ubuntu; but probably others, too, e.g., mint, etc).

It doesn't really, man bash explains, SHLVL Incremented by one each time an instance of bash is started. By the time you look at $SHLVL in Gnome terminal, you are two levels deep. If you look at $SHLVL in a text (Ctrl-Alt-F1) terminal it will start as 1.

One can track the progress of SHLVL, by adding these lines to one's .bashrc:

# keep track of the SHLVL values I see.
export SHLVLs="${SHLVLs:='init'}"
SHLVLs="${SHLVLs}:${SHLVL}"
4

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like