scripts script programacion pasar parametros español ejemplos comandos comando bash unix shell csh tcsh

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



scripts bash ejemplos (23)

En Mac OS X (y FreeBSD):

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

¿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?


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

Me doy cuenta de que la respuesta es un poco tarde en este buen 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 puedes usar $(getshell) --version.

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


Este funciona bien en RHEL, MacOS, BSD y algunos AIX.

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

alternativamente, el siguiente también debería funcionar si pstree está disponible,

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


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

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

Sé que aquí hay muchos que dicen que la salida de ls debería ser procesada más recientemente, pero ¿cuál es la probabilidad de que tenga un shell que esté usando con nombres de caracteres especiales o que se coloque en un directorio con caracteres especiales? Si este es el caso, aquí hay muchos otros ejemplos que lo hacen de manera diferente.


Grepping PID de la salida de "ps" no es necesario porque puede leer la línea de comando respectiva para cualquier PID desde la estructura de directorio / proc:

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

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

echo $0

Acerca de ejecutar un shell realmente diferente de lo que el nombre indica, una idea es solicitar una versión del shell con el nombre que recibió anteriormente:

<some_shell> --version

Parece que sh falla con el código de salida 2 mientras que otros dan algo útil (pero no puedo verificar todo porque no los tengo):

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


Haga lo siguiente para saber si su Shell está usando DASH / BASH.

1) ls –la / bin / sh , si el resultado es / bin / sh -> / bin / bash ==> Entonces su shell está utilizando BASH.

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

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

NOTA: Si el comando anterior produce un mensaje de error, / bin / sh ya existe, elimine / bin / sh e intente nuevamente.


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

Hacia adelante

  1. $> echo $ 0 (Te da el nombre del programa. En mi caso, la salida fue -bash )
  2. $> $ SHELL (Esto lo lleva al shell y en el indicador del sistema obtiene 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 le dará información completa sobre el software de shell con el tipo de licencia)

Enfoque de hackers

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


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 PID grepping. Con algo de limpieza, solo genera un nombre ejecutable (bajo Cygwin con ruta):

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

Puedes crear una función para no tener que memorizarla:

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

... y luego solo ejecuta shell .

Probado bajo Debian y Cygwin.


Mi solución:

ps -o command | grep -v -e "/<ps/>" -e grep -e tail | tail -1

Esto debería ser portátil a través de diferentes plataformas y shells. Utiliza ps como otras soluciones, pero no se basa en sed o awk y filtra la basura de las tuberías y ps sí, por lo que la shell debe ser siempre la última entrada. De esta manera, no necesitamos depender de variables PID no portátiles o seleccionar 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 fish, porque utiliza una variable PID diferente).


Mi variante en la impresión del proceso padre.

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

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


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

Esto me funciona (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 genera una cadena como bash . Estoy usando aquí solo ps , tail y sed (sin versiones GNU; intente agregar --posix para verificarlo). Todos ellos son comandos POSIX estándar. Estoy seguro de que se puede quitar la tail , pero mi sed fu no es lo suficientemente fuerte para hacer esto.

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


Puedes probar:

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

O:

echo $SHELL


Si solo desea 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 (solo lectura) no se puede establecer en el entorno, por lo que puede estar seguro de que viene (si es que lo hace) del shell actual. Sin embargo, dado que Bash tiene un comportamiento diferente cuando se invoca como sh , también debe verificar que la variable de entorno $BASH termina con /bash .

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

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

En el primer caso, podría omitir la comprobación funcional algo paranoica para las funciones, y suponer que las futuras versiones de bash serían compatibles.


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


Siempre que su /bin/sh compatible con el estándar POSIX y su sistema tenga instalado el comando lsof en este caso, una posible alternativa a lsof podría ser 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}''


Tengo un truco simple para encontrar el shell actual. Simplemente escriba una cadena aleatoria (que no es un comando). Fallará y devolverá un error "no encontrado", pero al comienzo de la línea dirá qué shell es:

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


Tratar

ps -p $$ -oargs=

o

ps -p $$ -ocomm=


Utilice amablemente el siguiente comando:

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


ps es el método más confiable. El envar SHELL no está garantizado para ser configurado e incluso si lo está, puede ser fácilmente falsificado


$SHELL no necesita mostrar siempre el shell actual. Solo refleja el shell por defecto a invocar.

Para probar lo anterior, Say bash es el shell predeterminado, intente 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 ejecutable del shell mediante readlink /proc/$$/exe


ps -p $$

Debería funcionar en cualquier lugar que las soluciones que involucran ps -ef y grep do (en cualquier variante de Unix que admita las opciones POSIX para ps ) y no sufran los falsos positivos introducidos por grepping para una secuencia de dígitos que pueden aparecer en otros lugares.



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

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

    Por lo tanto, la segunda pregunta sobre si la salida de ps será suficiente se responde con " no siempre ".

    1. echo $0 - imprimirá el nombre del programa ... que en el caso de shell es el shell real

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

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

    3. echo $SHELL : la ruta al shell actual se almacena como la variable SHELL para cualquier shell. La advertencia para este caso es que si inicia un shell explícitamente como un subproceso (por ejemplo, no es su shell de inicio de sesión), obtendrá el valor de su 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 shell real (por ejemplo, /bin/sh es en realidad bash o ksh), necesita heurísticas. Aquí hay algunas variables ambientales específicas para varias conchas:

    • $version está establecida en tcsh

    • $BASH se establece en bash

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

    • $ZSH_NAME se establece en zsh

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