Answers:
您可以使用命令pstree
(Ubuntu默认随附)。这是示例-当前我在WSL上只有一个打开的终端窗口:
User@Wsl:~$ pstree
init─┬─init───bash───pstree
└─{init}
User@Wsl:~$ bash
User@Wsl:~$ sh
$ bash
User@Wsl:~$ pstree
init─┬─init───bash───bash───sh───bash───pstree
└─{init}
在实际的Linux / Ubuntu环境中,过程树将更加复杂。我们可以通过-s
显示所选过程的父项的选项来过滤树。因此我们的命令可能是pstree -s $$
,其中$$
是包含当前PID的环境变量:
User@Ubuntu:~$ pstree -s $$
systemd──lightdm──lightdm──upstart──gnome-terminal-──bash──pstree
User@Ubuntu:~$ bash
User@Ubuntu:~$ sh
$ bash
User@Ubuntu:~$ pstree -s $$
systemd──lightdm──lightdm──upstart──gnome-terminal-──bash──bash──sh──bash──pstree
参考文献:
在shell的提示符中添加指示器:基于@waltinator的想法,为了在级别超过1时在提示符前面有一个计数器,用于存放多个不同的shell,我添加了以下示例中的行,在相关运行命令(~/.*rc
)文件的底部。
我已经在gnome-terminal,tty和ssh会话中对WSL,Ubuntu 16.04,Ubuntu 18.04(服务器/桌面),Ubuntu 19.04进行了测试。这是这样的:
限制是:计数器仅适用于13至14级深度,具体取决于操作系统。我无意调查原因:)
bash
> .bashrc
:
DEPTH=$(($(pstree -s $$ | sed -r 's/-+/\n/g' | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh)\>') - 1))
if (( DEPTH > 1 )); then PS1=$DEPTH:$PS1; fi
csh
和tcsh
> .cshrc
:
@ DEPTH = `pstree -s $$ | sed -r 's/-+/\n/g' | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh)\>'` - 0
if ( $DEPTH > 1 ) then; set prompt="$DEPTH":"$prompt"; endif
zsh
> .zshrc
:
DEPTH=$(($(pstree -s $$ | sed -r 's/-+/\n/g' | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh)\>') - 1))
if (( DEPTH > 1 )); then PROMPT=$DEPTH:$PROMPT; fi
ksh
> .kshrc
:
DEPTH=$(($(pstree -s $$ | sed -r 's/\-+/\n/g' | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh)\>') - 0))
if (( DEPTH > 1 )); then PS1="$DEPTH":"$PS1"'$ '; fi
sh
实际上是dash
在Ubuntu上-这里的事情有点复杂和连线(请阅读下面的参考资料以获得更多信息):
编辑~/.profile
文件,并在底部添加以下行:
ENV=$HOME/.shrc; export ENV
创建~/.shrc
具有以下内容的文件,注意ksh
也将读取$ENV
:
#!/bin/dash
DEPTH=$(pstree -s $$ | sed -r 's/-+/\n/g' | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh)\>')
if [ "$0" != 'ksh' ]; then DEPTH=$((DEPTH - 1)); fi
if [ "$DEPTH" -gt 1 ]; then export PS1='$DEPTH:\$ '; fi
参考文献:
.profile
和.kshrc
创建一个将输出深度的命令:另一个选项是创建将输出深度的shell命令。为此,请创建可执行文件(因此应在系统范围内进行访问):/usr/local/bin/depth
sudo touch /usr/local/bin/depth
sudo chmod +x /usr/local/bin/depth
使用您喜欢的编辑器编辑文件,并添加以下几行作为内容:
#!/bin/bash
SHELLS='(bash|zsh|sh|dash|ksh|csh|tcsh)'
DEPTH=$(pstree -s $$ | sed -r 's/-+/\n/g' | grep -Ec "\<$SHELLS\>")
if [[ $@ =~ -v ]]
then
pstree -s $$ | sed -r 's/-+/\n/g' | grep -E "\<$SHELLS\>" | cat -n
fi
echo "DEPTH: $DEPTH"
[[ $DEPTH -gt 1 ]] && exit 0 || exit 1
上面的脚本有两个选项,-v
或者--verbose
将输出涉及的shell的列表。而另一个将检查深度是否大于一个并基于此返回的选项将返回exit 0
or exit 1
,因此您可以以这种方式使用它depth && exit
。以下是一些用法示例:
User@Ubuntu:~$ depth # we are at the 1st level - bash
DEPTH: 1
User@Ubuntu:~$ sh
$ csh # we are at the 2nd level - dash
Ubuntu:~% depth # we are at the 3rd level - csh
DEPTH: 3
Ubuntu:~% ksh
$ depth -v # we are at the 4th level - ksh
1 bash
2 sh
3 csh
4 ksh
DEPTH: 4
$ depth && exit # exit to the 3rd level - csh
DEPTH: 4
Ubuntu:~% depth && exit # exit to the 2nd level - dash
DEPTH: 3
exit
$ depth && exit # exit to the 1st level - bash
DEPTH: 2
User@Ubuntu:~$ depth && exit # stay at the 1st level - bash
DEPTH: 1
User@Ubuntu:~$ depth && exit # stay at the 1st level - bash
DEPTH: 1
与其他解决方案的比较:我花了一些额外的时间来找出此处提供的方法的一些缺点。我能够想象以下两种情况(为了更好地突出显示语法,需要使用大写字母):
何时su
或sudo -i
涉及:
User@Ubuntu:~$ ps | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh|su|sudo)\>'
1
User@Ubuntu:~$ echo $SHLVL
1
User@Ubuntu:~$ depth
DEPTH: 1
User@Ubuntu:~$ su spas
Password:
Spas@Ubuntu:~$ ps | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh|su|sudo)\>'
1
Spas@Ubuntu:~$ echo $SHLVL
2
Spas@Ubuntu:~$ depth
DEPTH: 2
Spas@Ubuntu:~$ sudo -i
[sudo] password for spas:
Root@Ubuntu:~# ps | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh|su|sudo)\>'
3
Root@Ubuntu:~# echo $SHLVL
1
Root@Ubuntu:~# depth
DEPTH: 3
启动后台进程后:
User@Ubuntu:~$ bash
User@Ubuntu:~$ ps | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh)\>'
2
User@Ubuntu:~$ echo $SHLVL
2
User@Ubuntu:~$ depth
DEPTH: 2
User@Ubuntu:~$ while true; do sleep 10; done &
[1] 10886
User@Ubuntu:~$ ps | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh)\>'
3
User@Ubuntu:~$ echo $SHLVL
2
User@Ubuntu:~$ depth
DEPTH: 2
# Note: $SHLVL is not supported only by sh/dash.
# It works with all other tested shells: bash, zsh, csh, tcsh, ksh
User@Ubuntu:~$ sh
$ ps | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh)\>'
4
$ echo $SHLVL
2
$ depth
DEPTH: 3
systemd───xfce4-terminal───bash───pstree
。为什么这样呢?
xfce4-terminal
,它启动了一个bash
外壳程序,您在其中运行了该外壳程序,该外壳程序pstree
报告了其自身及其父级。如果您的意思是systemd和xfce4-terminal之间没有步骤,则可能是因为启动的xfce4-terminal死亡或被放弃,在这种情况下,它将被init继承。
SHLVL
吗?整个流程和系统的兼容性问题,我想,但后来pstree可能没有安装..
$SHLVL
不被一些炮弹支持。更具体地说,根据上面演示中的环境,它不仅仅受sh
(dash
)的支持-此变量根本不计入此shell。另一方面pstree
是psmisc软件包的一部分,该软件包还提供psmiscfuser
,killall
而其他软件包很少-它是Ubuntu的主要组件-我尚未在此答案中提到的系统上安装它。
检查SHLVL
shell变量的值:
echo $SHLVL
从bash
的手册页引用:
SHLVL Incremented by one each time an instance of bash is started.
也受到的支持zsh
。
:sh
默认为我认为的用户登录外壳程序(它实际上是缩写形式,:shell
而不是特定外壳程序二进制文件的名称)
:sh
从vim
发布这个答案之前,它确实增加了外壳的水平我。我的登录shell是bash。
在我的代码中.bashrc
,我常通过在变量中添加“ ”符号来$SHLVL
进行调整: $PS1
+
$SUBSHELL
...
# set a variable to reflect SHLVL > 1 (Ubuntu 12.04)
if [[ $SHLVL -gt 1 ]] ; then
export SUBSHELL="${SUBSHELL:+$SUBSHELL}+"
else
export SUBSHELL=""
fi
...
if [[ "$color_prompt" = yes ]]; then
# chroot? Depth green user@host nocolor : green $PWD red (status) off $ or # space
PS1='${debian_chroot:+($debian_chroot)}${SUBSHELL}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[1;31m\]($?)\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}${SUBSHELL}\u@\h:\w\$ '
fi
...
然后,我可以看到我有多深:
walt@bat:~(1)$ ed foo
263
!bash
+walt@bat:~(0)$ bash
++walt@bat:~(0)$ bash
+++walt@bat:~(0)$ exit
exit
++walt@bat:~(0)$ exit
exit
+walt@bat:~(0)$ exit
exit
!
q
walt@bat:~(0)$
awk:
# Count the occurrence of (sh)ells.
DEPTH_REGEX='^(ash|bash|busybox|csh|dash|fish|mksh|sh|tcsh|zsh)$'
DEPTH=$(/bin/ps -s $(/bin/ps -p $$ -osid --no-headers) -ocomm --no-headers | \
awk -v R=$DEPTH_REGEX '{for (A=1; A<=(NR-2); A++) {if ($A ~ R) {B++}}} END {print B}')
pgrep:
DEPTH=$(/usr/bin/pgrep -c -s $(/bin/ps -p $$ -osid --no-headers) '^(ash|bash|busybox|csh|dash|fish|mksh|sh|tcsh|zsh)$')
您可以将两个版本之一放在文件中,并使用源使$ DEPTH可用。
# Set 256 colors in terminal.
if [ -x /usr/bin/tput ] && [ "$(SHELL=/bin/sh tput colors)" -ge 8 ]; then
export TERM="xterm-256color"
fi
# change these if you don't dig my colors!
NM="\[\033[0;1;37m\]" #means no background and white lines
HI="\[\033[0;37m\]" #change this for letter colors
SI="\[\033[38;5;202m\]" #this is for the current directory
NI="\[\033[0;1;30m\]" #for @ symbol
IN="\[\033[0m\]"
# Count the occurrence of (sh)ells.
source /usr/share/shell-depth/depth
PS1="${NM}[${HI}\u${NI}@${HI}\h ${SI}\w${NM} \A](${HI}${DEPTH}${NM}): ${IN}"
您可以简单地使用ps
而无需任何其他参数来查看整个shell堆栈(包括当前的堆栈)。它还将显示您已开始的所有后台作业及其ps
本身,但可以粗略估计您的工作深度。
{ echo hello world; ps; } &
证明上述ps
答案。