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.
$SHLVL
variable (mantenida por varios shells) lo que estás buscando?fg
volver, que no tiene este problema.vim
trabajos 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 contarvim
niveles 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
SHLVL
cada vez que escriba unvim
comando. Deberá hacer esto para cada variante devi
/vim
que alguna vez use; p.ej,El conjunto externo de paréntesis crea una subshell, por lo que el cambio manual en el valor de
SHLVL
no contamina el entorno de shell actual (principal). Por supuesto, lacommand
palabra 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.bashrc
u 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
cmdn
cmdn
ps
El
exec
comando está allí para evitar que el proceso de shell adicional se demore.Pero, hay una trampa. El manejo del shell
SHLVL
es algo intuitivo: cuando se inicia el shell, comprueba siSHLVL
está 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
,SHLVL
deberías subir. Pero eso no es deseable, porque su nivel real de shell no ha aumentado. El shell maneja esto restando uno deSHLVL
cuando haces unexec
:Entonces
es un lavado; se incrementa
SHLVL
solo 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
vim
niveles independientemente de los niveles de shell. Bueno, exactamente el mismo truco funciona (bueno, con una pequeña modificación):(y así sucesivamente para
vi
,view
etc.)export
Es necesario porqueVILVL
no está definido como una variable de entorno de forma predeterminada. Pero no necesita ser parte de la función; se puede decir simplementeexport VILVL
con 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 vim
lugar deexec vim
dejarloSHLVL
solo: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
.profile
o 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
ps
opstree
, cuando puede hacer esto con shell incorporado.dash
tiene 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`
bash
script 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
zsh
en 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
~/.zshrc
o equivalente para tenerlo en su solicitud.tcsh
y varios otros proyectiles (zsh
,ksh93
,fish
ybash
por lo menos) mantienen una$SHLVL
variable que se incrementan en el inicio (y decremento antes de ejecutar otro comando conexec
(a no ser queexec
se 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 enumerapstree
debe mostrarle qué tan profundo está. Por ejemplo:fuente
Primera variante: solo profundidad de caparazón.
Solución simple para
bash
: agregar a las.bashrc
siguientes dos líneas (o cambiar suPS1
valor 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
.bashrc
Resultado:
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
pstree
opciones:-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