How to know the "level" of shells I am in?
You have in fact hit upon the correct term¹. There is an environment variable SHLVL
which all major interactive shells (bash, tcsh, zsh) increment by 1 when they start. So if you start a shell inside a shell, SHLVL
increases by 1.
This doesn't directly answer your concern, however, because SHLVL
carries over things like terminal emulators. For example, in my typical configuration, $SHLVL
is 2 in an xterm, because level 1 corresponds to the shell that runs my X session (~/.xinitrc
or ~/.xsession
).
What I do is to display $SHLVL
in my prompt, but only if the parent process of the shell is another shell (with heuristics like “if its name ends in sh
plus optional punctuation and digits, it's a shell”). That way, I have an obvious visual indication in the uncommon case of a shell running under another shell.
Maybe you would prefer to detect shells that are running directly under a terminal emulator.
You can do this fairly accurately: these are the shells whose parent process has a different controlling terminal, so that ps -o tty= -p$$
and ps -o tty= -p$PPID
produce different output. You might manually reset SHLVL
to 1 in these shells, or set your own TERMSHLVL
to 1 in these shells (and incremented otherwise).
¹
Although one wouldn't think it looking at the manual pages: none of the three shells that support it include the word “level” in their documentation of SHLVL
.
One (admittedly not perfect) way is to add the result of ps --no-headers -o comm $PPID
to your shell prompt. This will tell you the name of the process that spawned your shell. If you're inside a nested zsh, it will say "zsh". If you're inside a top-level zsh, it will read "xterm" or "screen" or whatever your shell is running in.
To tell whether you're inside an ssh or su session, you can simply look at the hostname and username part of your prompt.
When you're running nested screens (which I don't imagine is a common situation), there's no way I can think of to tell whether you're in the top-level shell of a nested screen, or the top-level shell of the top-level screen. You could configure screen to always display a status line, which would cause multiple status lines to be displayed, if you're in nested screens.