为什么在 Ubuntu 16.10 中 SHLVL 最初为 2(但在早期版本中不是)?

为什么在 Ubuntu 16.10 中 SHLVL 最初为 2(但在早期版本中不是)?

我刚刚升级到 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 仍然有SHLVL1,因此罪魁祸首一定是在 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}"

相关内容