Bạn có thể sử dụng lệnh pstree
(đi kèm theo mặc định với Ubuntu). Dưới đây là ví dụ - hiện tại tôi chỉ có một cửa sổ đầu cuối mở trên 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}
Trong môi trường Linux / Ubuntu thực tế, cây quy trình sẽ phức tạp hơn. Chúng ta có thể lọc cây theo tùy chọn -s
sẽ hiển thị cha mẹ của một quy trình được chọn. Vì vậy, lệnh của chúng ta có thể là pstree -s $$
, nơi $$
là một biến môi trường có chứa PID hiện tại:
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
Tài liệu tham khảo:
Thêm chỉ báo vào dấu nhắc của shell: Dựa trên ý tưởng của @ waltinator , để có một bộ đếm ở phía trước dấu nhắc cho một số shell khác nhau khi mức độ sâu hơn một, tôi đã thêm các dòng, được hiển thị bên dưới bản demo, ở dưới cùng của các tệp lệnh run ( ~/.*rc
) có liên quan .
Tôi đã thực hiện các thử nghiệm trên WSL, Ubuntu 16.04, Ubuntu 18.04 (máy chủ / máy tính để bàn), Ubuntu 19.04, trong phiên gnome-terminal, tty và ssh. Đây là cách nó hoạt động:

Hạn chế là: bộ đếm chỉ hoạt động ở độ sâu 13-14, tùy thuộc vào HĐH. Tôi không có ý định điều tra lý do :)
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
và 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
đó thực sự là dash
trên Ubuntu - ở đây mọi thứ hơi phức tạp và có dây (đọc các tài liệu tham khảo bên dưới để biết thêm thông tin):
Chỉnh sửa ~/.profile
tệp và thêm dòng sau ở dưới cùng:
ENV=$HOME/.shrc; export ENV
Tạo tập tin ~/.shrc
với nội dung sau, lưu ý ksh
cũng đọc $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
Tài liệu tham khảo:
Tạo một lệnh sẽ xuất độ sâu: Một tùy chọn khác là tạo lệnh shell sẽ xuất độ sâu. Với mục đích này, hãy tạo tệp thực thi (do đó nó có thể truy cập được trên toàn hệ thống):/usr/local/bin/depth
sudo touch /usr/local/bin/depth
sudo chmod +x /usr/local/bin/depth
Chỉnh sửa tệp với trình chỉnh sửa yêu thích của bạn và thêm các dòng sau vào nội dung của nó:
#!/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
Kịch bản trên có hai tùy chọn -v
hoặc --verbose
sẽ xuất ra một danh sách các shell liên quan. Và tùy chọn khác sẽ kiểm tra xem độ sâu có lớn hơn một hay không và dựa trên điều này sẽ trở lại exit 0
hoặc exit 1
, vì vậy bạn có thể sử dụng nó theo cách này depth && exit
. Dưới đây là một vài ví dụ về cách sử dụng:
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
So sánh bằng các giải pháp khác: Tôi đã dành thêm thời gian để tìm hiểu một số điểm yếu của các phương pháp được cung cấp ở đây. Tôi đã có thể tưởng tượng hai trường hợp sau (chữ in hoa là cần thiết để làm nổi bật cú pháp tốt hơn):
Khi su
hoặc sudo -i
có liên quan:
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
Khi có một quá trình nền được đưa ra:
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