Difference between linux $ BASH_SUBSHELL vs $ SHLVL variables

I got confused between them.

While the internal variable $ BASH_SUBSHELL indicates the nesting level of the subshell, the $ SHLVL variable does not display changes inside the subshell.

What does it mean? If I open a shell in another shell, the value of $ SHLVL increases. Isn't that a subshell?

+5
source share
2 answers

No, manually starting a new shell (via /bin/sh or /bin/bash , etc.) is not a subshell in this context.

A subshell is when the shell spawns a new instance of the shell on its own to handle some work.

Usage Substitution substitution (i.e. $(command) ) is a subshell (like the previous call to backticks).

Using a pipeline (i.e. echo '5.1+5.3' | bc -l ) creates subshells for each pipeline component.

Use Process substitution (i.e., <(command) ) creates a subshell.

Grouping commands (i.e. (declare a=5; echo $a) ) create a subshell.

Running commands in the background (i.e. sleep 1 & ) creates a subshell.

There may be other things, but these are common cases.

Testing is easy:

 $ printf "Outside: $BASH_SUBSHELL , $SHLVL\nInside: $(echo $BASH_SUBSHELL , $SHLVL)\n" Outside: 0 , 1 Inside: 1 , 1 $ (printf "Outside: $BASH_SUBSHELL , $SHLVL\nInside: $(echo $BASH_SUBSHELL , $SHLVL)\n") Outside: 1 , 1 Inside: 2 , 1 $ bash -c 'printf "Outside: $BASH_SUBSHELL , $SHLVL\nInside: $(echo $BASH_SUBSHELL , $SHLVL)\n"' Outside: 0 , 2 Inside: 1 , 2 $ bash -c '(printf "Outside: $BASH_SUBSHELL , $SHLVL\nInside: $(echo $BASH_SUBSHELL , $SHLVL)\n")' Outside: 1 , 2 Inside: 2 , 2 

The source of your quote (usually bad, and often avoided by ABS ) even demonstrates this a little (and in a rather obscure way, just another example of the general lack of rigor and quality in this "Advanced" manual):

 echo " \$BASH_SUBSHELL outside subshell = $BASH_SUBSHELL" # 0 ( echo " \$BASH_SUBSHELL inside subshell = $BASH_SUBSHELL" ) # 1 ( ( echo " \$BASH_SUBSHELL inside nested subshell = $BASH_SUBSHELL" ) ) # 2 # ^ ^ *** nested *** ^ ^ echo echo " \$SHLVL outside subshell = $SHLVL" # 3 ( echo " \$SHLVL inside subshell = $SHLVL" ) # 3 (No change!) 
+7
source

$SHLVL:
Shell level, how deep the bash is nested. If the command line $ SHLVL is 1, then in the script it will increase to 2. This subshell is not affected by this variable.

$BASH_SUBSHELL:
A variable indicating the level of the subshell.

Here's how they will have different meanings:

 # In the login bash shell echo $BASH_SUBSHELL:$SHLVL 0:1 # 1st nested child bash echo $BASH_SUBSHELL:$SHLVL 0:2 # 2nd nested child bash echo $BASH_SUBSHELL:$SHLVL 0:3 # back to 1st nested child exit echo $BASH_SUBSHELL:$SHLVL 0:2 # back to parent shell exit echo $BASH_SUBSHELL:$SHLVL 0:1 # first level sub-shell (echo $BASH_SUBSHELL:$SHLVL) 1:1 # 2nd level sub-shell ( (echo $BASH_SUBSHELL:$SHLVL) ) 2:1 # 3rd level sub-shell ( ( (echo $BASH_SUBSHELL:$SHLVL) ) ) 3:1 
+5
source

Source: https://habr.com/ru/post/1240643/


All Articles