【问题标题】:How do I know if I'm running a nested shell?我如何知道我是否在运行嵌套 shell?
【发布时间】:2010-12-22 16:39:55
【问题描述】:

当使用 *nix shell(通常是 bash)时,我经常生成一个子 shell,我可以用它来处理一个小任务(通常在另一个目录中),然后退出以恢复父 shell 的会话.

有时,我会忘记我是在运行嵌套 shell 还是在顶级 shell 中,并且我会不小心生成一个额外的子 shell 或退出顶级 shell错误的shell。

有没有一种简单的方法来确定我是否在嵌套的 shell 中运行?还是我以完全错误的方式解决我的问题(通过生成子 shell)?

【问题讨论】:

  • 我可以知道我何时在登录 shell 中,因为我不导出 PS1,我只在 .profile 中设置它。因此,如果我在子 shell 中,我会得到一个 '$' 提示符(或一些 '$' 提示符的变体)而不是我的正常提示符。
  • 我也不懂接近投票,该死,我 95% 的代表都是通过 shell 问题完成的

标签: linux bash shell unix


【解决方案1】:

$SHLVL 变量跟踪您的 shell 嵌套级别:

$ echo $SHLVL
1
$ bash
$ echo $SHLVL
2
$ exit
$ echo $SHLVL
1

作为生成子 shell 的替代方法,您可以从堆栈中推送和弹出目录并保持在同一个 shell 中:

[root@localhost /old/dir]# pushd /new/dir
/new/dir /old/dir
[root@localhost /new/dir]# popd
/old/dir
[root@localhost /old/dir]#

【讨论】:

  • 选择推送/弹出:[root@/old/dir]# cd /new/dir 然后[root@/new/dir]# cd - 会让你回到[root@/old/dir]#
  • 通过将此变量的打印输出添加到您的PS1 命令提示变量中,使其始终 打印到您的提示,如下所示:stackoverflow.com/questions/4511407/…
【解决方案2】:

这是我的提示部分的简化版本:

PS1='$(((SHLVL>1))&&echo $SHLVL)\$ '

如果我不在嵌套 shell 中,它不会添加任何额外内容,但如果我处于任何嵌套级别,它会显示深度。

【讨论】:

  • 非常有用。希望看到更多你的 .bashrc fu!
  • @Scalistro:好的,herehereherehere
  • @RobinA.Meade:该链接是否旨在成为误导性信息的示例?请指出以什么方式。无论如何,我已经更新了我的答案以使用更精确的措辞。
  • 好答案!我喜欢它总是在提示符上方打印$SHLVL 值,所以这是我的想法:stackoverflow.com/questions/4511407/…
【解决方案3】:

查看$0:如果它以减号- 开头,则说明您在登录shell 中。

【讨论】:

  • +1,因为它不使用 bashisms,但可以正常工作。
  • 嗯,如果我在另一个虚拟控制台上登录,这有效,但如果我打开一个新的gnome-terminal,则无效; $SHLVL 是 1,但 $0 没有 -。另外,在 tmux 中,当我有 $SHLVL==2 时,我会得到 $0,前面有 -。我很困惑。
【解决方案4】:

pstree -s $$ 对了解您的深度非常有用。

【讨论】:

  • 不过,如果您只想查看当前的 shell 处于哪个级别,那就是信息过载了。
【解决方案5】:

环境变量$SHLVL 包含shell“深度”。

echo $SHLVL

外壳深度也可以使用pstree(23及以上版本)来确定:

pstree -s $$ | grep sh- -o | wc -l

我发现第二种方法比使用sudo 重置值或使用env -i 变得不可靠的第一种方法更强大。

没有一个能正确处理su


信息可以在您的提示中提供:

PS1='\u@\h/${SHLVL} \w \$ '
PS1='\u@\h/$(pstree -s $$ | grep sh- -o | tail +2 | wc -l) \w \$ '

| tail +2 用于从grep 输出中删除一行。由于我们在“$(...)”命令替换中使用了管道,因此 shell 需要调用一个子 shell,因此 pstree 报告它并且 grep 检测到另一个sh- 级别。


在基于 debian 的发行版中,pstree 是包 psmisc 的一部分。它可能不会默认安装在非桌面发行版上。

【讨论】:

    【解决方案6】:

    ptree $$ 还会显示你的深度有多少级

    【讨论】:

      【解决方案7】:

      @John Kugelman saysecho $SHLVL 会告诉你 bash shell 的深度。
      作为@Dennis Williamson shows,您可以通过PS1 变量编辑您的提示,让它打印这个值。

      我更喜欢它总是打印外壳深度值,所以这就是我所做的:编辑您的“~/.bashrc”文件:

      gedit ~/.bashrc
      

      并在末尾添加以下行:

      export PS1='\$SHLVL'":$SHLVL\n$PS1"
      

      现在您将始终在提示上方看到当前 bash 级别的打印输出。例如:在这里您可以看到我的 bash 级别(深度)为 2,如 $SHLVL:2 所示:

      $SHLVL:2
      7510-gabriels ~ $

      现在,当我通过 bash 命令进入一些 bash 级别时,请注意提示,然后通过 exit 回来。在这里你可以看到我的命令和提示(响应),从第 2 级开始到第 5 级,然后又回到第 2 级:

      $SHLVL:2 
      7510-gabriels ~ $ bash
      $SHLVL:3 
      7510-gabriels ~ $ bash
      $SHLVL:4 
      7510-gabriels ~ $ bash
      $SHLVL:5 
      7510-gabriels ~ $ exit
      exit
      $SHLVL:4 
      7510-gabriels ~ $ exit
      exit
      $SHLVL:3 
      7510-gabriels ~ $ exit
      exit
      $SHLVL:2 
      7510-gabriels ~ $ 
      

      奖励:始终在您的终端中显示您当前的git branch,您也在使用!

      通过在“~/.bashrc”文件中使用以下内容,让您的提示也向您显示您正在处理的 git 分支

      git_show_branch() {
          __gsb_BRANCH=$(git symbolic-ref -q --short HEAD 2>/dev/null)
          if [ -n "$__gsb_BRANCH" ]; then
              echo "$__gsb_BRANCH"
          fi
      }
      export PS1="\e[7m\$(git_show_branch)\e[m\n\h \w $ "
      export PS1='\$SHLVL'":$SHLVL $PS1"
      

      来源:我不知道 git_show_branch() 最初来自哪里,但我是在 2018 年 4 月 5 日从 Jason McMullan 那里得到的。然后我添加了上面显示的 $SHLVL 部分,就在上周。

      样本输出:

      $SHLVL:2 主
      7510-gabriels ~/GS/dev/temp $

      这是一张截图,展示了它的所有荣耀。注意 git 分支名称,master以白色突出显示

      奖励部分更新

      我再次改进了它,put my ~/.bashrc file on github here。这是新终端提示的示例输出。请注意,当我在本地 git 存储库中时,它如何将 shell 级别显示为 1,并且它显示当前签出分支的分支名称(在本例中为 master):

      交叉引用:

      【讨论】:

        【解决方案8】:

        如果你在子 shell 中运行,下面的代码将产生 2:

        ps | fgrep bash | wc -l
        

        否则,它将产生 1。

        编辑好的,它不像 cmets 中指出的那样健壮:)
        另一件要尝试的是

        ps -ef | awk '{print $2, " ", $8;}' | fgrep $PPID 
        

        如果您在子 shell 中,将产生 'bash'。

        【讨论】:

        • 这取决于你的深度——如果你在子shell中创建了一个子shell,它将是3。
        • 您可能想在wc 之前添加| grep -v grep -- 并希望您的 id 下没有打开任何其他 shell。
        • @Seidr 只是不要下 4 个子 shell,那里是纯代码片段,如果你的程序在你这么深的时候崩溃,你可能永远不会回来。
        • @tvan 使用grep [b]ash 或更好,但只需使用pgrep 并完全删除对ps 的调用
        猜你喜欢
        • 1970-01-01
        • 2013-03-05
        • 2014-04-29
        • 2014-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多