Problema : Encuentra cuántas conchas de profundidad tengo.
Detalles : abro mucho el shell desde vim. Construye, corre y sal. A veces olvido y abro otro vim dentro y luego otro shell. :(
Quiero saber cuántos shells de profundidad tengo, tal vez incluso tenerlo en mi pantalla de shell en todo momento. (Puedo manejar esa parte).
Mi solución : analizar el árbol de procesos y buscar vim y bash / zsh y descubrir la profundidad del proceso actual dentro de él.
¿Ya existe algo así? No pude encontrar nada.

$SHLVLvariable (mantenida por varios shells) lo que estás buscando?fgvolver, que no tiene este problema.vimtrabajos detenidos en paralelo puede ser más confuso que tener una pila de procesos anidados. Por cierto, prefiero tener varias ventanas , por lo que puedo saltar rápidamente hacia adelante y hacia atrás rápidamente, pero no llamaría a esto un problema XY solo porque prefiero un flujo de trabajo diferente.Respuestas:
Cuando leí tu pregunta, mi primer pensamiento fue
$SHLVL. Entonces vi que querías contarvimniveles además de los niveles de shell. Una manera simple de hacer esto es definir una función de shell:Esto aumentará automática y silenciosamente
SHLVLcada vez que escriba unvimcomando. Deberá hacer esto para cada variante devi/vimque alguna vez use; p.ej,El conjunto externo de paréntesis crea una subshell, por lo que el cambio manual en el valor de
SHLVLno contamina el entorno de shell actual (principal). Por supuesto, lacommandpalabra clave está allí para evitar que las funciones se llamen a sí mismas (lo que daría como resultado un bucle de recursión infinito). Y, por supuesto, debe poner estas definiciones en su.bashrcu otro archivo de inicialización de shell.Hay una leve ineficiencia en lo anterior. En algunas conchas (bash siendo uno), si dices
donde es un programa externo ejecutable (es decir, no un comando incorporado), el shell mantiene un proceso adicional por ahí, solo para esperar a que termine. Esto (posiblemente) no es necesario; Las ventajas y desventajas son discutibles. Si no le importa atar un poco de memoria y una ranura de proceso (y ver un proceso de shell más de lo que necesita cuando hace una ), haga lo anterior y pase a la siguiente sección. Lo mismo si estás usando un shell que no mantiene el proceso extra por ahí. Pero, si desea evitar el proceso adicional, lo primero que debe intentar es
cmdncmdnpsEl
execcomando está allí para evitar que el proceso de shell adicional se demore.Pero, hay una trampa. El manejo del shell
SHLVLes algo intuitivo: cuando se inicia el shell, comprueba siSHLVLestá configurado. Si no está establecido (o establecido en algo que no sea un número), el shell lo establece en 1. Si está establecido (en un número), el shell agrega 1 a él.Pero, según esta lógica, si dices
exec sh,SHLVLdeberías subir. Pero eso no es deseable, porque su nivel real de shell no ha aumentado. El shell maneja esto restando uno deSHLVLcuando haces unexec:Entonces
es un lavado; se incrementa
SHLVLsolo para disminuirlo nuevamente. También podría decirvim, sin el beneficio de una función.Para arreglar esto, harías
Entonces vi que querías contar los
vimniveles independientemente de los niveles de shell. Bueno, exactamente el mismo truco funciona (bueno, con una pequeña modificación):(y así sucesivamente para
vi,viewetc.)exportEs necesario porqueVILVLno está definido como una variable de entorno de forma predeterminada. Pero no necesita ser parte de la función; se puede decir simplementeexport VILVLcon un comando aparte (en su.bashrc). Y, como se discutió anteriormente, si el proceso de shell adicional no es un problema para usted, puede hacerlo encommand vimlugar deexec vimdejarloSHLVLsolo:Si está utilizando un shell que no es compatible
SHLVL(por ejemplo, guión), puede implementarlo usted mismo siempre que el shell implemente un archivo de inicio. Solo haz algo comoen su
.profileo archivo aplicable. (Probablemente no debería usar el nombreSHLVL, ya que eso causará caos si alguna vez comienza a usar un shell que lo admitaSHLVL).Otras respuestas han abordado el problema de incrustar valores variables de entorno en su indicador de shell, por lo que no repetiré eso, especialmente si usted dice que ya sabe cómo hacerlo.
fuente
psopstree, cuando puede hacer esto con shell incorporado.dashtiene expansión aritmética.SHELL_LEVEL=$((SHELL_LEVEL + 1))debería ser suficiente incluso si $ SHELL_LEVEL estaba previamente desarmado o vacío. Es sólo si tiene que ser portátil para el shell Bourne que se necesitaría recurrir aexpr, pero entonces también tendría que reemplazar$(...)con`..`.SHELL_LEVEL=`expr "${SHELL_LEVEL:-0}" + 1`bashscript para leer ~ / .bashrc por haciendo stdin un socket por ejemplo), entonces eso puede convertirse en un problema. Eso es un montón de "si", pero algo para tener en cuenta (los datos no saneados en contexto aritmético son peligrosos)Puede contar la cantidad de tiempo que necesita para subir el árbol de procesos hasta que encuentre un líder de sesión. Al igual que
zshen Linux:O POSIXly (pero menos eficiente):
Eso daría 0 para el shell que inició su emulador de terminal o getty y uno más para cada descendiente.
Solo necesita hacer eso una vez al inicio. Por ejemplo con:
en su
~/.zshrco equivalente para tenerlo en su solicitud.tcshy varios otros proyectiles (zsh,ksh93,fishybashpor lo menos) mantienen una$SHLVLvariable que se incrementan en el inicio (y decremento antes de ejecutar otro comando conexec(a no ser queexecse encuentra en un subnivel si no están con errores (pero muchos son))). Sin embargo, eso solo rastrea la cantidad de anidamiento de shell , no el proceso de anidación. Tampoco se garantiza que el nivel 0 sea el líder de la sesión.fuente
Utilizar
echo $SHLVL. Utiliza el principio KISS . Dependiendo de la complejidad de su programa, esto puede ser suficiente.fuente
bash, pero no paradash.Una posible solución es mirar la salida de
pstree. Cuando se ejecuta dentro de una concha que se generó desde adentrovi, la parte del árbol del árbol que se enumerapstreedebe mostrarle qué tan profundo está. Por ejemplo:fuente
Primera variante: solo profundidad de caparazón.
Solución simple para
bash: agregar a las.bashrcsiguientes dos líneas (o cambiar suPS1valor actual ):Resultado:
El número al comienzo de la cadena de solicitud indicará el nivel de shell.
Segunda variante, con niveles anidados de vim y shell ambos.
agregue estas líneas a la
.bashrcResultado:
v: 1 - nivel de profundidad vim
s: 3 - nivel de profundidad de caparazón
fuente
En la pregunta que mencionaste el análisis
pstree. Aquí hay una forma relativamente simple:Las
pstreeopciones:-A- Salida ASCII para un filtrado más fácil (en nuestro caso, cada comando está precedido por`-)-a- muestre también los argumentos de los comandos, como efecto secundario cada comando se muestra en una línea separada y podemos filtrar fácilmente la salida usandogrep-l- no truncar líneas largas-s- mostrar a los padres del proceso seleccionado(desafortunadamente no es compatible con versiones anteriores de
pstree)$$- el proceso seleccionado - el PID del shell actualfuente
Esto no responde estrictamente la pregunta, pero en muchos casos puede hacer que sea innecesario hacerlo:
Cuando inicies tu shell por primera vez, corre
set -o ignoreeof. No lo pongas en tu~/.bashrc.Acostúmbrese a escribir Ctrl-D cuando piense que está en el nivel superior y quiera estar seguro.
Si estás no en la cáscara de alto nivel, Ctrl-D será la señal "fin de la entrada" en el shell actual y volverá a caer un nivel.
Si se encuentra en el nivel superior, recibirá un mensaje:
Lo uso todo el tiempo para sesiones SSH encadenadas, para que sea fácil volver a un nivel específico de la cadena SSH. Funciona para conchas anidadas también.
fuente