Vous pouvez utiliser la commande pstree
(qui est fourni par défaut avec Ubuntu). Voici un exemple - actuellement, je n'ai qu'une seule fenêtre de terminal ouverte sur WSL :
User@Wsl:~$ pstree
initinitbashpstree
{init}
User@Wsl:~$ bash
User@Wsl:~$ sh
$ bash
User@Wsl:~$ pstree
initinitbashbashshbashpstree
{init}
Dans un environnement Linux/Ubuntu réel, l'arborescence des processus sera plus complexe. Nous pouvons filtrer l'arbre par l'option -s
qui affichera les parents d'un processus sélectionné. Notre commande pourrait donc être pstree -s $$
où $$
est une variable d'environnement qui contient le PID actuel :
User@Ubuntu:~$ pstree -s $$
systemdlightdmlightdmupstartgnome-terminal-bashpstree
User@Ubuntu:~$ bash
User@Ubuntu:~$ sh
$ bash
User@Ubuntu:~$ pstree -s $$
systemdlightdmlightdmupstartgnome-terminal-bashbashshbashpstree
Références :
Ajouter un indicateur à l'invite du Shell : Sur la base de l'article de @waltinator idée afin d'avoir un compteur à l'avant de l'invite pour plusieurs coquilles différentes lorsque le niveau est plus profond qu'un, j'ai ajouté les lignes, montrées sous la démo, au bas de l'invite concernée exécuter des commandes ( ~/.*rc
).
J'ai fait des tests sur WSL, Ubuntu 16.04, Ubuntu 18.04 (serveur/bureau), Ubuntu 19.04, en session gnome-terminal, tty et ssh. Voici comment cela fonctionne :
La limitation est la suivante : le compteur ne fonctionne que pour 13-14 niveaux de profondeur, selon le système d'exploitation. Je n'ai pas l'intention d'en rechercher les raisons :)
-
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
y 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
qui est en fait dash
sur Ubuntu - ici les choses sont un peu compliquées et câblées (lire les références ci-dessous pour plus d'informations) :
-
Modifier le ~/.profile
et ajoutez la ligne suivante à la fin du fichier :
ENV=$HOME/.shrc; export ENV
-
Créer le fichier ~/.shrc
avec le contenu suivant, note ksh
lit également le $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
Références :
Créez une commande qui affichera la profondeur : Une autre option consiste à créer une commande Shell qui affichera la profondeur. Pour ce faire, créez le fichier exécutable /usr/local/bin/**depth**
(il devrait donc être accessible à l'ensemble du système) :
sudo touch /usr/local/bin/depth
sudo chmod +x /usr/local/bin/depth
Modifiez le fichier avec votre éditeur préféré et ajoutez les lignes suivantes à son contenu :
#!/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
Le script ci-dessus a deux options -v
o --verbose
qui produira une liste des shells concernés. Et une autre option qui vérifiera si la profondeur est supérieure à un et qui, en fonction de cela, renverra exit 0
o exit 1
Vous pouvez donc l'utiliser de la manière suivante depth && exit
. Voici quelques exemples d'utilisation :
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
Comparaison avec les autres solutions : J'ai passé un peu plus de temps à découvrir les faiblesses des approches proposées ici. J'ai pu imaginer les deux cas suivants (les lettres majuscules sont nécessaires pour une meilleure mise en évidence de la syntaxe) :
-
Quand su
o sudo -i
sont concernés :
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
-
Un processus d'arrière-plan est alors lancé :
User@Ubuntu:~$ bash
User@Ubuntu:~$ ps | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh)\>'
2
User@Ubuntu:~$ echo $SHLVL
2
User@Ubuntu:~$ depth
DETH: 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