¿Cómo determinar el shell actual en el que estoy trabajando?

¿Cómo puedo determinar el shell actual en el que estoy trabajando?

¿Sería suficiente la salida del comando ps solo?

¿Cómo se puede hacer esto en diferentes sabores de UNIX?

  • Hay 3 enfoques para encontrar el nombre del ejecutable del shell actual:

    Tenga en cuenta que los 3 enfoques pueden engañarse si el ejecutable del shell es /bin/sh pero en realidad se trata de un bash renombrado, por ejemplo (lo que ocurre con frecuencia).

    Por lo tanto, su segunda pregunta de si la salida ps se hará se responde con ” no siempre “.

    1. echo $0 – imprimirá el nombre del progtwig … que en el caso del shell es el shell real

    2. ps -ef | grep $$ | grep -v grep ps -ef | grep $$ | grep -v grep : buscará la identificación del proceso actual en la lista de procesos en ejecución. Como el proceso actual es shell, se incluirá.

      Esto no es 100% confiable, ya que puede tener OTROS procesos cuya lista de ps incluye el mismo número que el ID de proceso del shell, especialmente si ese ID es un número pequeño (por ejemplo, si el PID de shell es “5”, puede encontrar procesos llamados “java5”). “o” perl5 “en la misma salida grep !). Este es el segundo problema con el enfoque “ps”, además de no poder confiar en el nombre del shell.

    3. echo $SHELL – La ruta al shell actual se almacena como la variable SHELL para cualquier shell. La advertencia de esto es que si ejecuta un shell explícitamente como un subproceso (por ejemplo, no es su shell de inicio de sesión), obtendrá el valor del shell de inicio de sesión. Si eso es una posibilidad, use el enfoque ps o $0 .


  • Sin embargo, si el ejecutable no coincide con su caparazón real (por ejemplo, /bin/sh es en realidad bash o ksh), necesita heurística. Aquí hay algunas variables ambientales específicas para varias conchas:

    • $version está configurada en tcsh

    • $BASH está configurado en bash

    • $shell (minúscula) se establece en el nombre del shell real en csh o tcsh

    • $ZSH_NAME está configurado en zsh

    • ksh tiene $PS3 y $PS4 establecidos, mientras que el shell Bourne normal ( sh ) solo tiene $PS1 y $PS2 establecidos. Esto generalmente parece ser el más difícil de distinguir: la ÚNICA diferencia en todo el conjunto de variables ambientales entre sh y ksh que hemos instalado en el $ERRNO Solaris es $ERRNO , $FCEDIT , $LINENO , $PPID , $PS3 , $PS4 , $RANDOM , $SECONDS , $TMOUT .

ps -p $$

debería funcionar en cualquier lugar que las soluciones que involucran ps -ef y grep hacen (en cualquier variante de Unix que soporte opciones POSIX para ps ) y no sufrirá de los falsos positivos introducidos por grepping para una secuencia de dígitos que pueden aparecer en otra parte.

Tratar

 ps -p $$ -oargs= 

o

 ps -p $$ -ocomm= 

Puedes probar:

 ps | grep `echo $$` | awk '{ print $4 }' 

O:

 echo $SHELL 

Si solo quiere asegurarse de que el usuario está invocando el script con bash:

 if [ ! -n "$BASH" ] ;then echo Please run this script $0 with bash; exit 1; fi 

$SHELL no siempre debe mostrar el shell actual. Solo refleja el shell predeterminado que se invocará.

Para probar lo anterior, Say bash es el shell predeterminado, pruebe echo $SHELL , luego en el mismo terminal, ingrese en otro shell (ksh por ejemplo) y pruebe $SHELL , verá el resultado como bash en ambos casos.

Para obtener el nombre del shell actual, use cat /proc/$$/cmdline Y la ruta al shell ejecutable mediante readlink /proc/$$/exe

ps es el método más confiable. El ENVELL SHELL no está garantizado y, aunque lo sea, puede ser fácilmente falsificado

Tengo un truco simple para encontrar el caparazón actual. Simplemente escriba una cadena aleatoria (que no es un comando). Fallará y devolverá un error “no encontrado”, pero al inicio de la línea indicará qué shell es:

 ksh: aaaaa: not found [No such file or directory] bash: aaaaa: command not found 

Esto dará siempre el shell real utilizado – obtiene el nombre del ejecutable real y no del nombre del shell (es decir, ksh93 lugar de ksh etc.) Para /bin/sh mostrará el shell real utilizado: es decir, el dash

 ls -l /proc/$$/exe | sed 's%.*/%%' 

Sé que aquí hay muchos que dicen que la salida de ls debe procesarse más recientemente, pero ¿cuál es la probabilidad de que tenga un shell que esté utilizando con nombres con caracteres especiales o colocado en un directorio nombrado con caracteres especiales? Si aún así es el caso, aquí hay muchos otros ejemplos que lo hacen de manera diferente.

Mi variante al imprimir el proceso principal.

 ps -p $$ | awk '$1 == PP {print $4}' PP=$$ 

¿Por qué ejecutar aplicaciones innecesarias, cuando ‘awk’ puede hacerlo por usted?

Siempre que su /bin/sh admita el estándar POSIX y su sistema tenga instalado el comando lsof , una posible alternativa a lsof podría ser, en este caso, pid2path , también puede usar (o adaptar) el siguiente script que imprime rutas completas:

 #!/bin/sh # cat /usr/local/bin/cursh set -eu pid="$$" set -- sh bash zsh ksh ash dash csh tcsh pdksh mksh fish psh rc scsh bournesh wish Wish login unset echo env sed ps lsof awk getconf # getconf _POSIX_VERSION # reliable test for availability of POSIX system? PATH="`PATH=/usr/bin:/bin:/usr/sbin:/sbin getconf PATH`" [ $? -ne 0 ] && { echo "'getconf PATH' failed"; exit 1; } export PATH cmd="lsof" env -i PATH="${PATH}" type "$cmd" 1>/dev/null 2>&1 || { echo "$cmd not found"; exit 1; } awkstr="`echo "$@" | sed 's/\([^ ]\{1,\}\)/|\/\1/g; s/ /$/g' | sed 's/^|//; s/$/$/'`" ppid="`env -i PATH="${PATH}" ps -p $pid -o ppid=`" [ "${ppid}"X = ""X ] && { echo "no ppid found"; exit 1; } lsofstr="`lsof -p $ppid`" || { printf "%s\n" "lsof failed" "try: sudo lsof -p \`ps -p \$\$ -o ppid=\`"; exit 1; } printf "%s\n" "${lsofstr}" | LC_ALL=C awk -v var="${awkstr}" '$NF ~ var {print $NF}' 

He intentado muchos enfoques diferentes y el mejor para mí es:

ps -p $$

También funciona bajo Cygwin y no puede producir falsos positivos como desintegración PID. Con un poco de limpieza, solo genera un nombre ejecutable (en Cygwin con ruta):

 ps -p $$ | tail -1 | awk '{print $NF}' 

Puede crear una función para que no tenga que memorizarla:

 # print currently active shell shell () { ps -p $$ | tail -1 | awk '{print $NF}' } 

… y luego simplemente ejecuta shell .

Probado bajo Debian y Cygwin.

 echo $$ # Gives the Parent Process ID ps -ef | grep $$ | awk '{print $8}' #use the PID to see what the process is. 

de http://www.unix.com/unix-dummies-questions-answers/10390-how-do-you-know-what-your-current-shell.html

En Mac OS X (y FreeBSD):

 ps -p $$ -axco command | sed -n '$p' 

Si solo quiere comprobar que está ejecutando (una versión particular de) Bash, la mejor manera de hacerlo es usar la variable de matriz $BASH_VERSINFO . Como una variable de matriz (de solo lectura), no se puede establecer en el entorno, por lo que puede estar seguro de que está llegando (si es que lo hace) desde el shell actual. Sin embargo, dado que Bash tiene un comportamiento diferente cuando se invoca como sh , también es necesario verificar que la variable de entorno $BASH termine con /bash .

En un script que escribí que usa nombres de funciones con - (no subrayado) y depende de matrices asociativas (agregado en Bash 4), tengo la siguiente verificación de cordura (con un útil mensaje de error del usuario):

 case `eval 'echo $BASH@${BASH_VERSINFO[0]}' 2>/dev/null` in */bash@[456789]) # Claims bash version 4+, check for func-names and associative arrays if ! eval "declare -A _ARRAY && func-name() { :; }" 2>/dev/null; then echo >&2 "bash $BASH_VERSION is not supported (not really bash?)" exit 1 fi ;; */bash@[123]) echo >&2 "bash $BASH_VERSION is not supported (version 4+ required)" exit 1 ;; *) echo >&2 "This script requires BASH (version 4+) - not regular sh" echo >&2 "Re-run as \"bash $CMD\" for proper operation" exit 1 ;; esac 

Podría omitir la comprobación funcional algo paranoica de las características en el primer caso, y simplemente asumir que las futuras versiones de bash serían compatibles.

No es necesario expandir PID desde la salida de “ps” porque puede leer la línea de comando respectiva para cualquier PID de la estructura de directorio / proc:

 echo $(cat /proc/$$/cmdline) 

Sin embargo, eso podría no ser mejor que simplemente:

 echo $0 

Acerca de ejecutar en realidad un shell diferente de lo que indica el nombre, una idea es solicitar la versión de shell utilizando el nombre que obtuvo anteriormente:

  --version 

sh parece fallar con el código de salida 2, mientras que otros dan algo útil (pero no puedo verificarlo todo porque no los tengo):

 $ sh --version sh: 0: Illegal option -- echo $? 2 

Ninguna de las respuestas funcionó con fish shell (no tiene variables $$ o $0 ).

Esto funciona para mí (probado en sh , bash , fish , ksh , csh , true , tcsh y zsh ; openSUSE 13.2):

 ps | tail -n 4 | sed -E '2,$d;s/.* (.*)/\1/' 

Este comando emite una cadena como bash . Estoy usando aquí solo ps , tail y sed (sin extesions de GNU; intente agregar --posix para verificarlo). Todos ellos son comandos POSIX estándar. Estoy seguro de que se puede eliminar la tail , pero mi sed fu no es lo suficientemente fuerte como para hacer esto.

Me parece que esta solución no es muy portátil, ya que no funciona en OS X.(

Esta no es una solución muy limpia, pero hace lo que quiere.

Me doy cuenta de que la respuesta es un poco tarde en este buen viejo 2015, pero …

 #MUST BE SOURCED.. getshell() { local shell="`ps -p $$ | tail -1 | awk '{print $4}'`" shells_array=( # It is important that the shells are listed by the decrease of their length name. pdksh bash dash mksh zsh ksh sh ) local suited=false for i in ${shells_array[*]}; do if ! [ -z `printf $shell | grep $i` ] && ! $suited; then shell=$i suited=true fi done echo $shell } getshell 

Ahora puede usar $(getshell) --version.

Esto funciona, sin embargo, solo en conchas tipo ksh.

Mi solución:

 ps -o command | grep -v -e "\" -e grep -e tail | tail -1 

Esto debería ser portátil a través de diferentes plataformas y proyectiles. Utiliza ps como otras soluciones, pero no se basa en sed o awk y filtra la basura de las tuberías y ps para que el shell siempre sea la última entrada. De esta forma, no necesitamos depender de variables PID no portátiles ni elegir las líneas y columnas correctas.

He probado en Debian y MacOS con bash, zsh y fish (que no funciona con la mayoría de estas soluciones sin cambiar la expresión específicamente para peces, porque usa una variable PID diferente).

Hay muchas formas de descubrir el shell y su versión correspondiente. Aquí hay algunos que funcionaron para mí.

Adelante

  1. $> echo $ 0 (le da el nombre del progtwig. En mi caso, la salida fue -bash )
  2. $> $ SHELL (Esto te lleva al intérprete de órdenes y en el mensaje de solicitud obtienes el nombre y la versión del shell. En mi caso, bash3.2 $ )
  3. $> echo $ SHELL (Esto le dará una ruta ejecutable. En mi caso / bin / bash )
  4. $> $ SHELL –version (Esto dará información completa sobre el software de shell con tipo de licencia)

Enfoque hackish

$> ******* (Escriba un conjunto de caracteres aleatorios y en el resultado obtendrá el nombre del shell. En mi caso -bash: chapter2-a-sample-isomorphic-app: comando no encontrado )

Utilice amablemente el siguiente comando:

  # ps -p $$ | tail -1 | awk '{print $4}' 

Haz lo siguiente para saber si tu Shell está usando DASH / BASH.

1) ls -la / bin / sh , si el resultado es / bin / sh -> / bin / bash ==> Entonces tu caparazón está usando BASH.

si el resultado es / bin / sh -> / bin / dash ==> Entonces tu shell está usando DASH.

Si quiere cambiar de BASH a DASH o viceversa, use el siguiente código ln -s / bin / bash / bin / sh (cambie la shell a BASH)

NOTA: Si el comando anterior genera un error que indica que / bin / sh ya existe, elimine / bin / sh y vuelva a intentarlo.

Este funciona bien en RHEL, MacOS, BSD y algunos AIXes

 ps -T $$ | awk 'NR==2{print $NF}' 

alternativamente, seguir uno también debería funcionar si pstree está disponible,

 pstree | egrep $$ | awk 'NR==2{print $NF}'