Puede usar el comando pstree
(que viene por defecto con Ubuntu). Aquí hay un ejemplo: actualmente solo tengo una ventana de terminal abierta en 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}
Dentro de un entorno real de Linux / Ubuntu, el árbol de procesos será más complicado. Podemos filtrar el árbol por la opción -s
que mostrará a los padres de un proceso seleccionado. Entonces, nuestro comando podría ser pstree -s $$
, donde $$
es una variable de entorno que contiene el PID actual:
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
Referencias
Agregue un indicador a la solicitud del shell: según la idea de @ waltinator , para tener un contador al frente de la solicitud para varios shells diferentes cuando el nivel es más profundo que uno, he agregado las líneas, que se muestran debajo de la demostración, en la parte inferior de los archivos de comandos de ejecución ( ~/.*rc
) relevantes .
He realizado pruebas en WSL, Ubuntu 16.04, Ubuntu 18.04 (servidor / escritorio), Ubuntu 19.04, dentro de la sesión gnome-terminal, tty y ssh. Así es como funciona:
La limitación es que: el contador funciona solo para 13-14 niveles de profundidad, dependiendo del sistema operativo. No tengo la intención de investigar las razones :)
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
eso está realmente dash
en Ubuntu: aquí las cosas son un poco complicadas y están cableadas (lea las referencias a continuación para obtener más información):
Edite el ~/.profile
archivo y agregue la siguiente línea en la parte inferior:
ENV=$HOME/.shrc; export ENV
Cree el archivo ~/.shrc
con el siguiente contenido, la nota ksh
también lee el $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
Referencias
Cree un comando que genere la profundidad: otra opción es crear un comando de shell que genere la profundidad. Para este propósito, cree el archivo ejecutable (por lo tanto, debe ser accesible en todo el sistema):/usr/local/bin/depth
sudo touch /usr/local/bin/depth
sudo chmod +x /usr/local/bin/depth
Edite el archivo con su editor favorito y agregue las siguientes líneas como su contenido:
#!/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
El script anterior tiene dos opciones -v
o --verbose
que generará una lista de los shells involucrados. Y la otra opción que verificará si la profundidad es mayor que una y, en función de esto, regresará exit 0
o exit 1
, para que pueda usarla de esta manera depth && exit
. Aquí hay algunos ejemplos de uso:
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
Comparación con las otras soluciones: pasé un tiempo adicional para descubrir algunas debilidades de los enfoques proporcionados aquí. Pude imaginar los siguientes dos casos (las mayúsculas son necesarias para un mejor resaltado de sintaxis):
Cuando su
o sudo -i
están involucrados:
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
Cuando se inicia un proceso en segundo plano:
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