unix 我如何知道我是否在运行一个嵌套的shell?

w8f9ii69  于 2023-10-18  发布在  Unix
关注(0)|答案(8)|浏览(167)

当使用 *nix shell(通常是bash)时,我经常会生成一个子shell,我可以用它来处理一个小任务(通常在另一个目录中),然后退出以恢复父shell的会话。
有时候,我会忘记我是在运行一个嵌套的shell,还是在我的顶层shell中运行,我会意外地生成一个额外的子shell,或者错误地退出顶层shell。
有没有一种简单的方法来确定我是否在嵌套的shell中运行?或者我是在以一种完全错误的方式处理我的问题(通过生成子shell)?

yws3nbqq

yws3nbqq1#

$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]#
5cnsuln7

5cnsuln72#

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

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

如果我不在嵌套的shell中,它不会添加任何额外的东西,但是如果我在任何嵌套级别中,它会显示深度。

rt4zxlrg

rt4zxlrg3#

看看$0:如果它以--开头,则您处于登录shell中。

kpbwa7wx

kpbwa7wx4#

pstree -s $$是非常有用的,可以看到你的深度。

dhxwm5r4

dhxwm5r45#

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

echo $SHLVL

shell 深度也可以使用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的发行版中,pstreepsmisc包的一部分。默认情况下,它可能不会安装在非桌面发行版上。

zysjyyx4

zysjyyx46#

正如@John Kugelman所说,echo $SHLVL会告诉你bash shell的深度。
正如@Dennis威廉姆森所示,您可以通过PS1变量编辑提示符,让它打印这个值。
我更喜欢它 * 总是 * 打印shell深度值,所以下面是我所做的:编辑您的~/.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()最初来自哪里,但我在4月5日从Jason McMullan那里得到了它。2018.然后我添加了上周显示的$SHLVL部分。
样品输出:

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

这里有一个屏幕截图显示它在所有的荣耀。注意git分支名称master * 以白色高亮显示 *!

我最新的PS1提示

我再次改进了PS1提示符,并将其放入eRCaGuy_dotfiles存储库中。它位于我的~/.bash_aliases文件中,该文件来源于我的~/.bashrc文件。在我的~/.bash_aliases文件中搜索我的PS1条目和它们使用的gs_git_show_branch_and_hash函数。
下面是新终端提示符的示例输出。注意它是如何将shell级别显示为1的,并且它显示了当前 checkout 的分支的分支名称(在本例中为master),以及它的短git哈希值(在本例中为bac27c7),每当我在本地git repo中时!:

这真的很有帮助,帮助我确保我总是在正确的分支上执行我的git操作,并自动查看我何时将cd放入Git存储库。

对照:

  • 以类似树的方式输出git分支
x8diyxa7

x8diyxa77#

ptree $$也会显示你有多少层

yvfmudvl

yvfmudvl8#

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

ps | fgrep bash | wc -l

否则,它将产生1。

编辑好吧,这不是那么强大的方法,因为在评论中指出:)

另一个可以尝试的是

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

将产生'bash',如果你在子壳。

相关问题