Sie können den Befehl verwenden pstree
(der standardmäßig in Ubuntu enthalten ist). Hier ist ein Beispiel - zur Zeit habe ich nur ein offenes Terminalfenster in der 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}
In einer tatsächlichen Linux / Ubuntu-Umgebung wird der Prozessbaum komplizierter. Wir können den Baum nach der Option filtern, die -s
die Eltern eines ausgewählten Prozesses anzeigt. Unser Befehl könnte also lauten pstree -s $$
: Wo $$
ist eine Umgebungsvariable, die die aktuelle PID enthält?
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
Verweise:
Hinzufügen eines Indikators zur Shell-Eingabeaufforderung: Basierend auf der Idee des @ Waltinators habe ich die unter der Demo gezeigten Zeilen hinzugefügt, um einen Zähler für mehrere verschiedene Shells vor der Eingabeaufforderung zu haben, wenn das Level tiefer als eins ist. am unteren Rand der entsprechenden run-Anweisungen ( ~/.*rc
) -Dateien.
Ich habe Tests auf WSL, Ubuntu 16.04, Ubuntu 18.04 (Server / Desktop), Ubuntu 19.04 innerhalb von Gnome-Terminal, Tty und SSH-Sitzung gemacht. So funktioniert das:
Die Einschränkung besteht darin, dass der Zähler je nach Betriebssystem nur für 13-14 Tiefenstufen funktioniert. Ich habe nicht vor, die Gründe zu untersuchen :)
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
und 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
das ist eigentlich dash
auf Ubuntu - hier sind die Dinge etwas kompliziert und verkabelt (lesen Sie die Referenzen unten für weitere Informationen):
Bearbeiten Sie die ~/.profile
Datei und fügen Sie die folgende Zeile unten hinzu:
ENV=$HOME/.shrc; export ENV
Erstellen Sie die Datei ~/.shrc
mit dem folgenden Inhalt, Hinweis ksh
liest auch die $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
Verweise:
Erstellen Sie einen Befehl, der die Tiefe ausgibt: Eine andere Option besteht darin, einen Shell-Befehl zu erstellen, der die Tiefe ausgibt. Zu diesem Zweck erstellen Sie die ausführbare Datei (daher sollte sie systemweit zugänglich sein):/usr/local/bin/depth
sudo touch /usr/local/bin/depth
sudo chmod +x /usr/local/bin/depth
Bearbeiten Sie die Datei mit Ihrem bevorzugten Editor und fügen Sie die folgenden Zeilen als Inhalt hinzu:
#!/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
Das obige Skript hat zwei Optionen -v
oder --verbose
es wird eine Liste der beteiligten Shells ausgegeben. Und die andere Option, die prüft, ob die Tiefe größer als eins ist und darauf basiert, gibt exit 0
oder zurück exit 1
, sodass Sie sie auf diese Weise verwenden können depth && exit
. Hier einige Anwendungsbeispiele:
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
Vergleich mit den anderen Lösungen: Ich habe zusätzliche Zeit aufgewendet, um einige Schwächen der hier vorgestellten Ansätze herauszufinden. Ich konnte mir die folgenden zwei Fälle vorstellen (die Großbuchstaben werden für eine bessere Hervorhebung der Syntax benötigt):
Wann su
oder sudo -i
sind beteiligt:
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
Wenn dort ein Hintergrundprozess gestartet wird:
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