How do I know if I'm running a nested shell?
When using a *nix shell (usually bash), I often spawn a sub-shell with which I can take care of a small task (usually in another directory), then exit out of to resume the session of the parent shell.
Once in a while, I'll lose track of whether I'm running a nested shell, or in my top-level shell, and I'll accidentally spawn an additional sub-shell or exit out of the top-level shell by mistake.
Is there a simple way to determine whether I'm running in a nested shell? Or am I going about my problem (by spawning sub-shells) in a completely wrong way?
Solution 1:
The $SHLVL
variable tracks your shell nesting level:
$ echo $SHLVL
1
$ bash
$ echo $SHLVL
2
$ exit
$ echo $SHLVL
1
As an alternative to spawning sub-shells you could push and pop directories from the stack and stay in the same shell:
[root@localhost /old/dir]# pushd /new/dir
/new/dir /old/dir
[root@localhost /new/dir]# popd
/old/dir
[root@localhost /old/dir]#
Solution 2:
Here is a simplified version of part of my prompt:
PS1='$(((SHLVL>1))&&echo $SHLVL)\$ '
If I'm not in a nested shell, it doesn't add anything extra, but it shows the depth if I'm in any level of nesting.
Solution 3:
Look at $0
: if it starts with a minus -
, you're in the login shell.
Solution 4:
pstree -s $$
is quite useful to see your depth.
Solution 5:
The environment variable $SHLVL
contains the shell "depth".
echo $SHLVL
The shell depth can also be determined using pstree
(version 23 and above):
pstree -s $$ | grep sh- -o | wc -l
I've found the second way to be more robust than the first whose value was reset when using sudo
or became unreliable with env -i
.
None of them can correctly deal with su
.
The information can be made available in your prompt:
PS1='\u@\h/${SHLVL} \w \$ '
PS1='\u@\h/$(pstree -s $$ | grep sh- -o | tail +2 | wc -l) \w \$ '
The | tail +2
is there to remove one line from the grep
output. Since we are using a pipeline inside a "$(...)
" command substitution, the shell needs to invoke a sub-shell, so pstree report it and grep detects one more sh-
level.
In debian-based distributions, pstree
is part of the package psmisc
. It might not be installed by default on non-desktop distributions.