Linux变量$BASH_SUBSHELL与$SHLVL之间的区别

11
我对这两个变量有点困惑。
尽管$BASH_SUBSHELL内部变量表示子shell的嵌套级别,$SHLVL变量在子shell中不发生变化。
这到底是什么意思?如果我在另一个shell中打开一个shell,$SHLVL的值会增加。那不就是一个子shell吗?
2个回答

18
不,手动运行新的shell(通过/bin/sh/bin/bash等)在此上下文中不是子shell。
当shell自己生成一个新的shell实例来处理一些工作时,就会出现子shell。
使用命令替换(即$(command))是子shell(旧版反引号调用也是如此)。
使用管道(即echo '5.1+5.3' | bc -l)为管道的每个组件创建子shell。
使用进程替换(即<(command))会创建一个子shell。

分组命令(例如(declare a=5; echo $a))会创建一个子shell。

在后台运行命令(例如sleep 1 &)会创建一个子shell。

可能还有其他情况,但这些是常见的情况。

测试很容易:

$ 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

你的引用来源(通常较差且应尽量避免的ABS)甚至在某种程度上证明了这一点(以及那个“高级”指南中普遍缺乏严谨和质量的另一个例子,表述也相当不清楚):

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!)

非常感谢,帮助很大。 - Vikas Tiwari
@Etan Reisner ABS来自TLDP,不是一个好的来源吗?我原本计划阅读它的。我应该跳过去找更好的来源吗?你能推荐一下吗? - Porcupine

10

$SHLVL:
Shell级别,Bash嵌套的深度。如果在命令行中$SHLVL为1,则在脚本中它将增加到2。此变量不受子shell的影响。

$BASH_SUBSHELL:
指示子shell级别的变量。

以下是它们具有不同值的方式:

# 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接