BASH_SUBSHELL 变量不生效的情况
BASH_SUBSHELL 实现于 Bash 3.0,我一直想不到它在实际编码中有什么用,后来在 Bash 的 Change Log 里找到一句话,才知道它是作调试用的:
New variables to support the bash debugger: BASH_ARGC, BASH_ARGV,
BASH_SOURCE, BASH_LINENO, BASH_SUBSHELL, BASH_EXECUTION_STRING,
BASH_COMMAND
BASH_SUBSHELL 是 subshell 嵌套层次的累加器,那么按理说,所有的 subshell 里这个变量都应该加 1。那 Bash 的哪些语法是在 subshell 里执行的呢?下面列举一下:
- 小括号分组 (...)
- 命令替换 `...` 和 $(...)
- 进程替换 <() 和 >()
- 管道 ... | ...
- 后台命令 ... &
那么当 BASH_SUBSHELL 出现在这些语法中时,它的值就应该加 1,对不对?然而实际情况却不是这样的,在我写这篇文章时,Bash 的最新稳定版是 4.3.30,在该版本中,BASH_SUBSHELL 只会在上面列出的 1 和 2 两种语法里生效:
(echo $BASH_SUBSHELL) 1 echo `echo $BASH_SUBSHELL` 1 echo $(echo $BASH_SUBSHELL) 1 |
在后三种语法里不生效:
cat <(echo $BASH_SUBSHELL) 0 echo $BASH_SUBSHELL | cat 0 echo $BASH_SUBSHELL & [1] 91155 0 |
搜索了一翻,在 help-bash 上发现已经有人提了个 bug,不过他仅仅提到了进程替换和命令替换中 BASH_SUBSHELL 表现不一致的事,Bash 作者也回复说会在 Bash 下个版本也就是是 4.4 里修复。然后我下了 4.4 alpha 版编译之后发现,进程替换中 BASH_SUBSHELL 是生效了,但在管道和后台命令中仍没效果,于是我又顶起了这个邮件,询问 Bash 作者是否能一起修复,他的回复是,后台命令那个他会修的,但管道命令那个不准备修复。然后我就没再追问为什么了,应该是实现上有困难,毕竟这是 Bash 私有的东西,作者有权决定该不该修。总之,我想说的是,在未来 Bash 4.4 发布的时候,BASH_SUBSHELL 在除了管道之外的其他子 Shell 里,都应该能生效了。
此外,当我问这个问题的时候,有人回复说,之所以 BASH_SUBSHELL 为 0,是因为它是在父 Shell 里展开之后才传入子 Shell 的,也就是说,echo $BASH_SUBSHELL | cat 在传入子 Shell 的时候就已经成了 echo 0 | cat,但这是不对的,我们可以举一个反例,如果真是那样的话,echo $BASHPID | cat 应该和 echo $BASHPID 的输出一样,但实际却是不一样的。所以可以总结一下就是,从来都不存在“在父 Shell 中展开变量,在子 Shell 里执行展开后的命令” 这一回事,所有的变量都是在子 Shell 中展开然后执行的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2012-09-21 [译]JavaScript:typeof的用途