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

Vik*_*ari 9 linux bash shell

我在两者之间感到困惑.

虽然$ BASH_SUBSHELL内部变量指示子shell的嵌套级别,但$ SHLVL变量在子shell中没有显示任何更改.

它究竟意味着什么?如果我在另一个shell中打开一个shell,$ SHLVL的值会递增.不是那个子壳吗?

Eta*_*ner 13

不,在此上下文中,手动运行新shell(通过/bin/sh/bin/bash等)不是子shell.

子shell是当外壳产生一个新的shell实例自身来处理一些工作.

使用命令替换(ie $(command))是一个子shell(就像旧的反引号调用一样).

使用管道(即echo '5.1+5.3' | bc -l)为管道的每个组件创建子壳.

使用Process Substitution(ie <(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
Run Code Online (Sandbox Code Playgroud)

你的报价来源(通常很差,通常更好的避免,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!)
Run Code Online (Sandbox Code Playgroud)


anu*_*ava 7

$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
Run Code Online (Sandbox Code Playgroud)