![为什么在 Ubuntu 16.10 中 SHLVL 最初为 2(但在早期版本中不是)?](https://linux22.com/image/1143110/%E4%B8%BA%E4%BB%80%E4%B9%88%E5%9C%A8%20Ubuntu%2016.10%20%E4%B8%AD%20SHLVL%20%E6%9C%80%E5%88%9D%E4%B8%BA%202%EF%BC%88%E4%BD%86%E5%9C%A8%E6%97%A9%E6%9C%9F%E7%89%88%E6%9C%AC%E4%B8%AD%E4%B8%8D%E6%98%AF%EF%BC%89%EF%BC%9F.png)
我刚刚升级到 Ubuntu 16.10。为什么$SHLVL
现在当我打开 Gnome 终端时,它是否以值 2 开始?在 16.04 中不是这种情况。
答案1
这个不幸的错误是在 Ubuntu 16.10 中引入的。
有关 bash 解决方法,请参阅https://bugs.launchpad.net/ubuntu/+source/unity/+bug/1707977/comments/3
答案2
如果您运行一个不启动 shell 但可以让您访问环境变量的应用程序,您将看到环境已经包含SHLVL
值 1。例如,我安装并运行了 IDLE3,运行import os
并检查了的值os.environ['SHLVL']
,结果为 1。
现在,也在脚本中设置和增加,所以,如果我在终端中SHLVL
运行包含的 bash 脚本,我会得到 3。echo $SHLVL
但是,控制台/TTY 仍然有SHLVL
1,因此罪魁祸首一定是在 GUI 启动过程中的某个地方。我不知道具体是什么,但我猜是 Unity。例如,在 GNOME Shell 中,这种情况不会发生。在 Unity 启动的某个地方,可能存在一个 bash 脚本。
答案3
继续我在原始问题中的评论(并且,这本身不是一个答案,因为我无法回答“为什么”,但我可以验证新的行为是否存在):
此更改破坏了向后兼容性。现在,无论您如何在 ubuntu 中打开终端/bash,它们都从开始,SHLVL=2
虽然我不确定这是 Ubuntu 特有的问题,还是由于使用 Unity。如果碰巧有逻辑在父 shell 退出时执行某些特定操作(例如保存状态),那么现在将永远不会执行。
(此外,我也不确定是否~/.bash_logout
与之前同时被调用。不确定,记不清了。依赖这种行为的不可预测性就是我们根据 shell 深度使用自定义逻辑的原因。我触发 ~/.bash_logout
它的唯一方法是明确退出以 开头的 shell bash -l
;所有其他 Ubuntu bash shell 都不是登录 shell。它可能一直都是这样。)
在尝试推断真正的 SHLVL 的方法时,尝试看看是否有另一种方法来区分“父级”与子 shell,这可能会起作用(如果这实际上是 Unity 特有的错误功能,则检查 ubuntu 是可选的。)
$ echo $SHLVL
2
$ my_shlvl() {
lsb_release -i | grep -qi ubuntu && pstree -s $$ | grep -o bash | wc -l
}
$ export -f my_shlvl
$ my_shlvl
1
$ bash
$ echo $SHLVL
3
$ my_shlvl
2
$ exit
$ my_shlvl
1
这种hack解决方法非常特定于 gnu/linux(例如pstree
,假设lsb_release
存在),但据我所知,该问题仅存在于一部分 linux 发行版中(到目前为止,只是 ubuntu;但也可能存在于其他发行版中,例如 mint 等)。
答案4
事实上并非如此,man bash
解释道,SHLVL Incremented by one each time an instance of bash is started.
当您$SHLVL
在 Gnome 终端中查看时,您已经深入了两个层次。如果您$SHLVL
在文本 ( Ctrl-Alt-F1) 终端中查看,它将以 开始1
。
SHLVL
可以通过在 中添加以下几行来跟踪 的进度.bashrc
:
# keep track of the SHLVL values I see.
export SHLVLs="${SHLVLs:='init'}"
SHLVLs="${SHLVLs}:${SHLVL}"