如何知道我是否在运行嵌套shell?

时间:2022-03-22 16:23:06

When using a *nix shell (usually bash), I often spawn a sub-shell with which I can take care of a small task (usually in another directory), then exit out of to resume the session of the parent shell.

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

Once in a while, I'll lose track of whether I'm running a nested shell, or in my top-level shell, and I'll accidentally spawn an additional sub-shell or exit out of the top-level shell by mistake.

偶尔,我将会忘记我是在运行一个嵌套的shell,还是在我的*shell中,我将会错误地产生一个额外的子shell或者从顶层shell中退出。

Is there a simple way to determine whether I'm running in a nested shell? Or am I going about my problem (by spawning sub-shells) in a completely wrong way?

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

7 个解决方案

#1


62  

The $SHLVL variable tracks your shell nesting level:

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

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

As an alternative to spawning sub-shells you could push and pop directories from the stack and stay in the same shell:

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

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

#2


21  

Here is a simplified version of part of my prompt:

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

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

If I'm not in a subshell, it doesn't add anything extra, but it shows the depth if I'm in any level of subshell.

如果我不在子层中,它不会添加任何额外的东西,但是它显示了在任何子层中的深度。

#3


11  

Look at $0: if it starts with a minus -, you're in the login shell.

看看$0:如果它以-开头,你就在登录shell中。

#4


6  

pstree -s $$ is quite useful to see your depth.

pstree -s $$ $对你的深度非常有用。

#5


0  

ptree $$ will also show you how many levels deep you are

ptree $$ $也会显示你的深度

#6


0  

The environment variable $SHLVL contains the shell "depth".

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

echo $SHLVL

The shell depth can also be determined using pstree (version 23 and above):

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

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

I've found the second way to be more robust than the first whose value was reset when using sudo or became unreliable with env -i.

我发现第二种方法比第一个更健壮,当使用sudo时,它的值被重置,或者使用env -i变得不可靠。

None of them can correctly deal with su.

他们中没有一个人能正确地处理su。


The information can be made available in your prompt:

有关资料可于下列网址查阅:

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

The | tail +2 is there to remove one line from the grep output. Since we are using a pipeline inside a "$(...)" command substitution, the shell needs to invoke a sub-shell, so pstree report it and grep detects one more sh- level.

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


In debian-based distributions, pstree is part of the package psmisc. It might not be installed by default on non-desktop distributions.

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

#7


-1  

If you running inside sub-shell following code will yield 2:

如果您在子shell中运行以下代码,将产生2:

ps | fgrep bash | wc -l

Otherwise, it will yield 1.

否则,它会产生1。

EDIT Ok, it's not so robust approach as was pointed out in comments :)
Another thing to try is

编辑Ok,它不像注释中指出的那样健壮

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

will yield 'bash' if you in sub-shell.

如果在子shell中,将产生“bash”。

#1


62  

The $SHLVL variable tracks your shell nesting level:

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

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

As an alternative to spawning sub-shells you could push and pop directories from the stack and stay in the same shell:

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

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

#2


21  

Here is a simplified version of part of my prompt:

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

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

If I'm not in a subshell, it doesn't add anything extra, but it shows the depth if I'm in any level of subshell.

如果我不在子层中,它不会添加任何额外的东西,但是它显示了在任何子层中的深度。

#3


11  

Look at $0: if it starts with a minus -, you're in the login shell.

看看$0:如果它以-开头,你就在登录shell中。

#4


6  

pstree -s $$ is quite useful to see your depth.

pstree -s $$ $对你的深度非常有用。

#5


0  

ptree $$ will also show you how many levels deep you are

ptree $$ $也会显示你的深度

#6


0  

The environment variable $SHLVL contains the shell "depth".

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

echo $SHLVL

The shell depth can also be determined using pstree (version 23 and above):

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

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

I've found the second way to be more robust than the first whose value was reset when using sudo or became unreliable with env -i.

我发现第二种方法比第一个更健壮,当使用sudo时,它的值被重置,或者使用env -i变得不可靠。

None of them can correctly deal with su.

他们中没有一个人能正确地处理su。


The information can be made available in your prompt:

有关资料可于下列网址查阅:

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

The | tail +2 is there to remove one line from the grep output. Since we are using a pipeline inside a "$(...)" command substitution, the shell needs to invoke a sub-shell, so pstree report it and grep detects one more sh- level.

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


In debian-based distributions, pstree is part of the package psmisc. It might not be installed by default on non-desktop distributions.

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

#7


-1  

If you running inside sub-shell following code will yield 2:

如果您在子shell中运行以下代码,将产生2:

ps | fgrep bash | wc -l

Otherwise, it will yield 1.

否则,它会产生1。

EDIT Ok, it's not so robust approach as was pointed out in comments :)
Another thing to try is

编辑Ok,它不像注释中指出的那样健壮

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

will yield 'bash' if you in sub-shell.

如果在子shell中,将产生“bash”。