!Probablemente, probar las capacidades particulares (por ejemplo, ¿hace sustitución?) Es más portátil que encontrar el nombre del shell. La costumbre local puede hacer que ejecute algo llamado /bin/shque podría ser ash, dash, bash, etc.
msw
1
@msw: Parece un buen comentario, excepto que me deja preguntándome "¿cómo?".
nobar
Parece que no hay una respuesta simple a esta pregunta. Si no podemos consultar el shell, quizás el mejor enfoque sea especificar siempre el shell. No estoy seguro de que esto siempre sea posible, pero tal vez se logra más fácilmente de lo que la gente generalmente asume.
@Aniket, no hay tanta ayuda como podría pensar, solo le interesan los procesos de shell interactivos .
Toby Speight
Respuestas:
794
Hay tres enfoques para encontrar el nombre del ejecutable del shell actual:
Tenga en cuenta que los tres enfoques pueden ser engañados si el ejecutable del shell es /bin/sh, pero en realidad es un cambio de nombre bash, por ejemplo (lo que sucede con frecuencia).
Por lo tanto, su segunda pregunta sobre si la pssalida funcionará se responde con " no siempre ".
echo $0 - imprimirá el nombre del programa ... que en el caso del shell es el shell real.
ps -ef | grep $$ | grep -v grep- esto buscará el ID del proceso actual en la lista de procesos en ejecución. Dado que el proceso actual es el shell, se incluirá.
Esto no es 100% confiable, ya que es posible que tenga otros procesos cuya pslista incluya 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 del shell es "5", puede encontrar procesos llamados "java5" o "perl5" en la misma grepsalida!). Este es el segundo problema con el enfoque "ps", además de no poder confiar en el nombre del shell.
echo $SHELL- La ruta al shell actual se almacena como la SHELLvariable para cualquier shell. La advertencia para esto 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 es una posibilidad, use el enfoque pso $0.
Sin embargo, si el ejecutable no coincide con su shell real (por ejemplo, en /bin/shrealidad es bash o ksh), necesita heurística. Aquí hay algunas variables ambientales específicas para varios shells:
$version está configurado en tcsh
$BASH se establece en bash
$shell (minúscula) se establece en el nombre real del shell en csh o tcsh
$ZSH_NAME está configurado en zsh
ksh tiene $PS3y $PS4establece, mientras que el shell Bourne normal ( sh) solo tiene $PS1y $PS2establece. Esto parece generalmente como el más difícil de distinguir - la única diferencia en todo el conjunto de variables de entorno entre shy kshhemos instalado en Solaris es Boxen $ERRNO, $FCEDIT, $LINENO, $PPID, $PS3, $PS4, $RANDOM, $SECONDS, y $TMOUT.
ps -p $$como señala Matthew Slattery . Para ksh: echo $KSH_VERSIONo echo ${.sh.version}.
Pausado hasta nuevo aviso.
@Dennish: mi ksh en este momento no tiene configurado KSH_VERSION. y echo ${.sh.version}devuelve "Mala sustitución". Vea mi solución arriba
DVK
3
“ ps -ef | grep …... Esto no es 100% fiable como ...” Usando una expresión regular simple a través de egrepo grep -efácilmente puede traer la fiabilidad hasta para-todo-intenciones-y-fines 100%: ps -ef | egrep "^\s*\d+\s+$$\s+". Se ^asegura de que estamos comenzando desde el principio de la línea, se \d+come el UID, $$coincide con el PID y el \s*y \s+representa y garantiza el espacio en blanco entre las otras partes.
Slipp D. Thompson
2
@ SlippD.Thompson no funcionaba en GNU / Linux. Pero esto parece funcionar:ps -ef | awk '$2==pid' pid=$$
jarno
98
ps -p $$
debería funcionar en cualquier lugar donde las soluciones involucren ps -efy lo grephagan (en cualquier variante de Unix que admita las opciones POSIXps ) y no sufrirá los falsos positivos introducidos por grepping para una secuencia de dígitos que puede aparecer en otros lugares.
Algunos proyectiles tienen su propia versión incorporada de la pscual puede que no se entienda, -ppor lo que es posible que deba usarla /bin/ps -p $$.
Pausado hasta nuevo aviso.
13
Todos los proyectiles con los que estoy familiarizado entienden, $$excepto los fishque tendrías que usar ps -p %self.
Pausado hasta nuevo aviso.
3
En realidad, no debes confiar en caminos difíciles como /bin/ps. pspodría instalarse fácilmente (en realidad es bastante normal hoy en día) /usr/bin. $(which ps) -p $$Es una mejor manera. Por supuesto, esto no funcionará en peces, y posiblemente en otras conchas. Creo que está (which ps) -p %selfen el pescado.
Aron Cederholm
1
En algunos sistemas mínimos, como un contenedor docker debian-slim, ps podría no estar allí. En ese caso, este enfoque todavía funciona:readlink /proc/$$/exe
mxmlnkn
si tu shes emulado por bash, ps -p te da /usr/bin/bashincluso lo ejecutas comosh
Este es un buen corto. Me estaba usando a mí mismo ps -o fname --no-headers $$.
Anne van Rossum
Gracias. Encontré esta la mejor opción para usar en un script para proteger comandos específicos de bash test `ps -p $$ -ocomm=` == "bash" && do_something_that_only_works_in_bash. (La siguiente línea en mi script tiene el equivalente para csh.)
craq
1
Descubrí que si hace esto desde una subshell, puede generar líneas adicionales espurias al hacer coincidir el PID del padre y el proceso de shell real. Para esto, uso en -qlugar de -p:SHELL=$(ps -ocomm= -q $$)
Steve
35
Si solo quiere asegurarse de que el usuario invoque un script con Bash:
if[!-n "$BASH"];then echo Please run this script $0 with bash;exit1;fi
Este debería ser el más cercano a la cima. Muchas gracias.
Alex Skrypnyk
44
No debería estar más cerca de la cima, porque no responde a la pregunta en absoluto. Si la pregunta sería "Cómo verificar si el script se ejecuta en bash", lo voto.
David Ferenczy Rogožan
2
@DawidFerenczy: sin embargo, esta pregunta es el mejor resultado cuando buscas esa frase. A la larga, creo que es mucho más importante que las respuestas respondan a lo que la gente está buscando en lugar de responder a la pregunta original.
ArtOfWarfare
3
Además, la variable $ BASH se define bajo tcsh si se invoca el tcsh desde bash
18446744073709551615
Esto es muy útil, gracias. Sólo adaptado un poco, poner esto como la segunda línea después #!/bin/bash: if [ ! -n "$BASH" ] ;then exec bash $0; fi. Con esta línea, el script se ejecuta usando bash incluso si se comenzó a usar ksh o sh. Mi caso de uso no necesita argumentos de línea de comando, pero podrían agregarse después $0si es necesario.
¿Cuál es el punto de grep seguido de awk, cuándo /pattern/ { action }lo hará?
Jens
# in zshell alias shell = 'echo $ {SHELL: t}'
SergioAraujo
44
$SHELLLa variable de entorno contiene un shell, que está configurado como predeterminado para un usuario actual. No refleja un shell, que se está ejecutando actualmente. También es mejor usar ps -p $$que grepping $$ debido a falsos positivos.
David Ferenczy Rogožan
El env $ SHELL. La variable apunta al shell 'padre', como se especifica en la especificación POSIX: SHELL Esta variable representará un nombre de ruta del intérprete de lenguaje de comando preferido del usuario. Por lo tanto, el valor de $ SHELL puede no ser el shell actual.
Theo
todo dentro awk,ps | awk '$1=='$$' { n=split($4,a,"/"); print a[n] }'
go2null
16
$SHELLNo siempre es necesario mostrar el shell actual. Solo refleja el shell predeterminado que se invocará.
Para probar lo anterior, digamos que bashes el shell predeterminado, intente echo $SHELL, y luego en el mismo terminal, ingrese a otro shell ( KornShell (ksh) por ejemplo) e intente $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 por readlink /proc/$$/exe.
+1 $ SHELL es el shell predeterminado para los programas que necesitan generar uno. No necesariamente refleja el shell que se está ejecutando actualmente.
Jim Lewis
8
Tengo un simple truco 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á de qué shell se trata:
ksh: aaaaa: not found [No such file or directory]
bash: aaaaa: command not found
No es bueno en un guión. echo 'aaaa' > script; chmod +x script; ./scriptda./script.sh: 1: aaaa: not found
delgado
6
Lo siguiente siempre dará el shell real utilizado: obtiene el nombre del ejecutable real y no el nombre del shell (es decir, en ksh93lugar de ksh, etc.). Para /bin/sh, mostrará el shell real utilizado, es decir dash.
ls -l /proc/$$/exe | sed 's%.*/%%'
Sé que hay muchos que dicen que la lssalida nunca debe procesarse, pero ¿cuál es la probabilidad de que tenga un shell que está usando que se nombra con caracteres especiales o se coloca en un directorio con caracteres especiales? Si este sigue siendo el caso, hay muchos otros ejemplos de hacerlo de manera diferente.
Como señaló Toby Speight , esta sería una forma más adecuada y limpia de lograr lo mismo:
Esto solo errores en todos los Unices que no proporcionan /proc. No todo el mundo es una caja de Linux.
Jens
55
Y si usted está en Linux, que prefiere basename $(readlink /proc/$$/exe)a ls+ sed+ echo.
Toby Speight
1
Esto le dará el nombre del ejecutable real , no el shell real . Cuando el shell real está vinculado como un applet busybox, digamos ash -> /bin/busybox, esto dará / bin / busybox.
stepse
6
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 grepping PID. Con un poco de limpieza, genera solo un nombre ejecutable (en Cygwin con ruta):
ps -p $$ | tail -1| awk '{print $NF}'
Puede crear una función para no tener que memorizarla:
# Print currently active shell
shell (){
ps -p $$ | tail -1| awk '{print $NF}'}
A partir de mi configuración (Cygwin | Windows 7) su respuesta es la mejor, y ps -p $$ | cola -1 | gawk '{print $ NF}' funciona incluso desde cmd sin $ bash. Tenga en cuenta gawk en lugar de awk, ya que awk solo funciona desde bash.
WebComer
@WebComer Lo siento, no estoy seguro de lo que quieres decir con " funciona incluso desde cmd sin $ bash ". Incluso si tuviera puertos Windows de ps, taily gawk, cmd no se define $$como su PID, por lo que definitivamente no puede funcionar bajo el cmd simple.
David Ferenczy Rogožan
¿Por qué no simplemente ps -p$$ -o comm=? POSIX dice que especificar todos los encabezados vacíos suprime el encabezado por completo. Todavía estamos fallando (como todas las psrespuestas) cuando nos obtiene un script ejecutado directamente (por ejemplo #!/bin/sh).
Toby Speight
5
Mi variante para imprimir el proceso padre:
ps -p $$ | awk '$1 == PP {print $4}' PP=$$
No ejecute aplicaciones innecesarias cuando AWK pueda hacerlo por usted.
¿Por qué ejecutar un innecesario awk, cuando ps -p "$$" -o 'comm='puede hacerlo por usted?
Toby Speight
5
Hay muchas formas de averiguar el shell y su versión correspondiente. Aquí hay algunos que me funcionaron.
Sencillo
$> echo $ 0 (Le da el nombre del programa. En mi caso, el resultado fue -bash ).
$> $ SHELL (Esto lo lleva al intérprete de comandos y en el indicador aparece el nombre y la versión del intérprete de comandos. En mi caso bash3.2 $ .)
$> echo $ SHELL (Esto le dará una ruta ejecutable. En mi caso / bin / bash .)
$> $ SHELL --version (Esto proporcionará información completa sobre el software de shell con el tipo de licencia)
Enfoque hackish
$> ******* (Escriba un conjunto de caracteres aleatorios y en la salida obtendrá el nombre del shell. En mi caso -bash: chapter2-a-sample-isomorphic-app: comando no encontrado )
Siempre que /bin/shadmita el estándar POSIX y su sistema tenga lsofinstalado el comando, una posible alternativa a lo que lsofpodría ser en este caso pid2path, también puede usar (o adaptar) el siguiente script que imprime las rutas completas:
#!/bin/sh# cat /usr/local/bin/curshset-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";exit1;}export PATH
cmd="lsof"
env -i PATH="${PATH}" type "$cmd"1>/dev/null2>&1||{ echo "$cmd not found";exit1;}
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";exit1;}
lsofstr="`lsof -p $ppid`"||{ printf "%s\n""lsof failed""try: sudo lsof -p \`ps -p \$\$ -o ppid=\`";exit1;}
printf "%s\n""${lsofstr}"|
LC_ALL=C awk -v var="${awkstr}"'$NF ~ var {print $NF}'
esto funciona en peces! pero para mí, falla en bash, debido a la -iopción (-> ignorar entorno) enven la línea donde verifica si lsofestá disponible. falla con: env -i PATH="${PATH}" type lsof->env: ‘type’: No such file or directory
hoijui
2
Si solo desea verificar que está ejecutando (una versión particular de) Bash, la mejor manera de hacerlo es usar la $BASH_VERSINFOvariable de matriz. Como una variable de matriz (solo lectura) no se puede establecer en el entorno, por lo que puede estar seguro de que proviene (si es que lo hace) del shell actual.
Sin embargo, dado que Bash tiene un comportamiento diferente cuando se invoca como sh, también es necesario verificar que la $BASHvariable de entorno termina con /bash.
En un script que escribí que usa nombres de funciones con -(no subrayado), y depende de matrices asociativas (agregadas en Bash 4), tengo la siguiente comprobació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 arraysif!eval"declare -A _ARRAY && func-name() { :; }"2>/dev/null;then
echo >&2"bash $BASH_VERSION is not supported (not really bash?)"exit1fi;;*/bash@[123])
echo >&2"bash $BASH_VERSION is not supported (version 4+ required)"exit1;;*)
echo >&2"This script requires BASH (version 4+) - not regular sh"
echo >&2"Re-run as \"bash $CMD\" for proper operation"exit1;;esac
Podría omitir la comprobación funcional paranoica de las funciones en el primer caso, y simplemente asumir que las futuras versiones de Bash serían compatibles.
Ninguna de las respuestas funcionó con fishshell (no tiene las 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 genera una cadena como bash. Aquí solo estoy usando ps, taily sed(sin extensiones GNU; intente agregar --posixpara verificarlo). Todos son comandos POSIX estándar. Estoy seguro de que tailse puede eliminar, pero mi sedfu 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. :(
Esto debería ser portátil en diferentes plataformas y shells. Se utiliza pscomo otras soluciones, pero no se basa en sedo awkfiltra la basura de las tuberías y de pssí misma para que el shell siempre sea la última entrada. De esta manera, no necesitamos confiar en variables PID no portátiles o elegir las líneas y columnas correctas.
He probado en Debian y macOS con Bash, Z shell ( zsh) y fish (que no funciona con la mayoría de estas soluciones sin cambiar la expresión específicamente para fish, porque usa una variable PID diferente).
Intenté esto mientras lo usaba zsh, y me dio -bash.
user137369
En mi sistema (ahora), probado con bash y dash, este regreso mutt...: -b
F. Hauri
1
No es necesario agrupar el PID de la salida de "ps", ya que puede leer la línea de comando correspondiente para cualquier PID desde la estructura del 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 al que indica el nombre, una idea es solicitar la versión del shell utilizando el nombre que obtuvo anteriormente:
<some_shell> --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):
Esta no es una solución muy limpia, pero hace lo que quieres.
# MUST BE SOURCED..
getshell(){local shell="`ps -p $$ | tail -1 | awk '{print $4}'`"
shells_array=(# It is important that the shells are listed in descending order of their name length.
pdksh
bash dash mksh
zsh ksh
sh
)local suited=falsefor i in ${shells_array[*]};doif![-z `printf $shell | grep $i`]&&! $suited;then
shell=$i
suited=truefidone
echo $shell
}
getshell
Ahora puedes usar $(getshell) --version.
Sin embargo, esto funciona solo en shells similares a KornShell (ksh).
"Sin embargo, esto funciona solo en proyectiles tipo ksh". ¿Estás diciendo que tengo que verificar el shell antes de ejecutar esto? Hmm ...
jpaugh
@jpaugh, las listas deben ser apoyados por la cáscara abastecimiento de este código, que no es el caso para dash, yashetc. Normalmente, si está utilizando bash, zsh, ksh, lo que sea - no debe preocuparse por esas cosas.
theoden8
¿Entonces estás contando bash como "ksh-like"? Entendido. Eso tiene más sentido
jpaugh
@jpaugh, bueno, eso es lo que quise decir porque kshel conjunto de características es principalmente un subconjunto de bashcaracterísticas (aunque no lo he comprobado a fondo).
theoden8
1
Haga lo siguiente para saber si su shell está usando Dash / Bash.
ls –la /bin/sh:
si el resultado es /bin/sh -> /bin/bash==> Entonces su shell está usando 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 (cambiar shell a Bash)
Nota : Si el comando anterior da como resultado un error que dice, / bin / sh ya existe, elimine / bin / sh e intente nuevamente.
La primera es una tontería, echo $SHELLhace lo que estás tratando de hacer y hazlo bien. El segundo tampoco es bueno, porque $SHELLla variable de entorno contiene un shell predeterminado para un usuario actual, no un shell actualmente en ejecución. Si, por ejemplo, lo bashconfiguro como shell predeterminado, ejecutar zshy echo $SHELL, se imprimirá bash.
David Ferenczy Rogožan
Tienes razón Dawid Ferenczy, podemos usar el comando ps para determinar el shell actual. [# ps -p $$ | cola -1 | awk '{print $ 4}'].
!
Probablemente, probar las capacidades particulares (por ejemplo, ¿hace sustitución?) Es más portátil que encontrar el nombre del shell. La costumbre local puede hacer que ejecute algo llamado/bin/sh
que podría ser ash, dash, bash, etc.Respuestas:
Hay tres enfoques para encontrar el nombre del ejecutable del shell actual:
Tenga en cuenta que los tres enfoques pueden ser engañados si el ejecutable del shell es
/bin/sh
, pero en realidad es un cambio de nombrebash
, por ejemplo (lo que sucede con frecuencia).Por lo tanto, su segunda pregunta sobre si la
ps
salida funcionará se responde con " no siempre ".echo $0
- imprimirá el nombre del programa ... que en el caso del shell es el shell real.ps -ef | grep $$ | grep -v grep
- esto buscará el ID del proceso actual en la lista de procesos en ejecución. Dado que el proceso actual es el shell, se incluirá.Esto no es 100% confiable, ya que es posible que tenga otros procesos cuya
ps
lista incluya 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 del shell es "5", puede encontrar procesos llamados "java5" o "perl5" en la mismagrep
salida!). Este es el segundo problema con el enfoque "ps", además de no poder confiar en el nombre del shell.echo $SHELL
- La ruta al shell actual se almacena como laSHELL
variable para cualquier shell. La advertencia para esto 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 es una posibilidad, use el enfoqueps
o$0
.Sin embargo, si el ejecutable no coincide con su shell real (por ejemplo, en
/bin/sh
realidad es bash o ksh), necesita heurística. Aquí hay algunas variables ambientales específicas para varios shells:$version
está configurado en tcsh$BASH
se establece en bash$shell
(minúscula) se establece en el nombre real del shell en csh o tcsh$ZSH_NAME
está configurado en zshksh tiene
$PS3
y$PS4
establece, mientras que el shell Bourne normal (sh
) solo tiene$PS1
y$PS2
establece. Esto parece generalmente como el más difícil de distinguir - la única diferencia en todo el conjunto de variables de entorno entresh
yksh
hemos instalado en Solaris es Boxen$ERRNO
,$FCEDIT
,$LINENO
,$PPID
,$PS3
,$PS4
,$RANDOM
,$SECONDS
, y$TMOUT
.fuente
ps -p $$
como señala Matthew Slattery . Paraksh
:echo $KSH_VERSION
oecho ${.sh.version}
.echo ${.sh.version}
devuelve "Mala sustitución". Vea mi solución arribaps -ef | grep …
... Esto no es 100% fiable como ...” Usando una expresión regular simple a través deegrep
ogrep -e
fácilmente puede traer la fiabilidad hasta para-todo-intenciones-y-fines 100%:ps -ef | egrep "^\s*\d+\s+$$\s+"
. Se^
asegura de que estamos comenzando desde el principio de la línea, se\d+
come el UID,$$
coincide con el PID y el\s*
y\s+
representa y garantiza el espacio en blanco entre las otras partes.ps -ef | awk '$2==pid' pid=$$
ps -p $$
debería funcionar en cualquier lugar donde las soluciones involucren
ps -ef
y logrep
hagan (en cualquier variante de Unix que admita las opciones POSIXps
) y no sufrirá los falsos positivos introducidos por grepping para una secuencia de dígitos que puede aparecer en otros lugares.fuente
ps
cual puede que no se entienda,-p
por lo que es posible que deba usarla/bin/ps -p $$
.$$
excepto losfish
que tendrías que usarps -p %self
./bin/ps
.ps
podría instalarse fácilmente (en realidad es bastante normal hoy en día)/usr/bin
.$(which ps) -p $$
Es una mejor manera. Por supuesto, esto no funcionará en peces, y posiblemente en otras conchas. Creo que está(which ps) -p %self
en el pescado.readlink /proc/$$/exe
sh
es emulado porbash
, ps -p te da/usr/bin/bash
incluso lo ejecutas comosh
Tratar
o
fuente
ps -o fname --no-headers $$
.test `ps -p $$ -ocomm=` == "bash" && do_something_that_only_works_in_bash
. (La siguiente línea en mi script tiene el equivalente para csh.)-q
lugar de-p
:SHELL=$(ps -ocomm= -q $$)
Si solo quiere asegurarse de que el usuario invoque un script con Bash:
fuente
#!/bin/bash
:if [ ! -n "$BASH" ] ;then exec bash $0; fi
. Con esta línea, el script se ejecuta usando bash incluso si se comenzó a usar ksh o sh. Mi caso de uso no necesita argumentos de línea de comando, pero podrían agregarse después$0
si es necesario.Puedes probar:
O:
fuente
/pattern/ { action }
lo hará?$SHELL
La variable de entorno contiene un shell, que está configurado como predeterminado para un usuario actual. No refleja un shell, que se está ejecutando actualmente. También es mejor usarps -p $$
que grepping $$ debido a falsos positivos.awk
,ps | awk '$1=='$$' { n=split($4,a,"/"); print a[n] }'
$SHELL
No siempre es necesario mostrar el shell actual. Solo refleja el shell predeterminado que se invocará.Para probar lo anterior, digamos que
bash
es el shell predeterminado, intenteecho $SHELL
, y luego en el mismo terminal, ingrese a otro shell ( KornShell (ksh) por ejemplo) e intente$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 porreadlink /proc/$$/exe
.fuente
/proc
.ps es el método más confiable. No se garantiza que se establezca la variable de entorno SHELL e incluso si lo es, se puede suplantar fácilmente.
fuente
Tengo un simple truco 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á de qué shell se trata:
fuente
echo 'aaaa' > script; chmod +x script; ./script
da./script.sh: 1: aaaa: not found
Lo siguiente siempre dará el shell real utilizado: obtiene el nombre del ejecutable real y no el nombre del shell (es decir, en
ksh93
lugar deksh
, etc.). Para/bin/sh
, mostrará el shell real utilizado, es decirdash
.Sé que hay muchos que dicen que la
ls
salida nunca debe procesarse, pero ¿cuál es la probabilidad de que tenga un shell que está usando que se nombra con caracteres especiales o se coloca en un directorio con caracteres especiales? Si este sigue siendo el caso, hay muchos otros ejemplos de hacerlo de manera diferente.Como señaló Toby Speight , esta sería una forma más adecuada y limpia de lograr lo mismo:
fuente
/proc
. No todo el mundo es una caja de Linux.basename $(readlink /proc/$$/exe)
als
+sed
+echo
.ash -> /bin/busybox
, esto dará / bin / busybox.He intentado muchos enfoques diferentes y el mejor para mí es:
También funciona bajo Cygwin y no puede producir falsos positivos como grepping PID. Con un poco de limpieza, genera solo un nombre ejecutable (en Cygwin con ruta):
Puede crear una función para no tener que memorizarla:
... y luego simplemente ejecuta
shell
.Fue probado bajo Debian y Cygwin.
fuente
ps
,tail
ygawk
, cmd no se define$$
como su PID, por lo que definitivamente no puede funcionar bajo el cmd simple.ps -p$$ -o comm=
? POSIX dice que especificar todos los encabezados vacíos suprime el encabezado por completo. Todavía estamos fallando (como todas lasps
respuestas) cuando nos obtiene un script ejecutado directamente (por ejemplo#!/bin/sh
).Mi variante para imprimir el proceso padre:
No ejecute aplicaciones innecesarias cuando AWK pueda hacerlo por usted.
fuente
awk
, cuandops -p "$$" -o 'comm='
puede hacerlo por usted?Hay muchas formas de averiguar el shell y su versión correspondiente. Aquí hay algunos que me funcionaron.
Sencillo
Enfoque hackish
$> ******* (Escriba un conjunto de caracteres aleatorios y en la salida obtendrá el nombre del shell. En mi caso -bash: chapter2-a-sample-isomorphic-app: comando no encontrado )
fuente
Siempre que
/bin/sh
admita el estándar POSIX y su sistema tengalsof
instalado el comando, una posible alternativa a lo quelsof
podría ser en este casopid2path
, también puede usar (o adaptar) el siguiente script que imprime las rutas completas:fuente
-i
opción (-> ignorar entorno)env
en la línea donde verifica silsof
está disponible. falla con:env -i PATH="${PATH}" type lsof
->env: ‘type’: No such file or directory
Si solo desea verificar que está ejecutando (una versión particular de) Bash, la mejor manera de hacerlo es usar la
$BASH_VERSINFO
variable de matriz. Como una variable de matriz (solo lectura) no se puede establecer en el entorno, por lo que puede estar seguro de que proviene (si es que lo hace) del shell actual.Sin embargo, dado que Bash tiene un comportamiento diferente cuando se invoca como
sh
, también es necesario verificar que la$BASH
variable de entorno termina con/bash
.En un script que escribí que usa nombres de funciones con
-
(no subrayado), y depende de matrices asociativas (agregadas en Bash 4), tengo la siguiente comprobación de cordura (con un útil mensaje de error del usuario):Podría omitir la comprobación funcional paranoica de las funciones en el primer caso, y simplemente asumir que las futuras versiones de Bash serían compatibles.
fuente
Ninguna de las respuestas funcionó con
fish
shell (no tiene las variables$$
o$0
).Esto funciona para mí (probado en
sh
,bash
,fish
,ksh
,csh
,true
,tcsh
, yzsh
; openSUSE 13.2):Este comando genera una cadena como
bash
. Aquí solo estoy usandops
,tail
ysed
(sin extensiones GNU; intente agregar--posix
para verificarlo). Todos son comandos POSIX estándar. Estoy seguro de quetail
se puede eliminar, pero mised
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. :(
fuente
sed: invalid option -- 'E'
en bash 3.2.51 y tcsh 6.15.00Mi solución:
Esto debería ser portátil en diferentes plataformas y shells. Se utiliza
ps
como otras soluciones, pero no se basa ensed
oawk
filtra la basura de las tuberías y deps
sí misma para que el shell siempre sea la última entrada. De esta manera, no necesitamos confiar en variables PID no portátiles o elegir las líneas y columnas correctas.He probado en Debian y macOS con Bash, Z shell (
zsh
) y fish (que no funciona con la mayoría de estas soluciones sin cambiar la expresión específicamente para fish, porque usa una variable PID diferente).fuente
De ¿Cómo saber cuál es su shell actual es? .
fuente
grep $$
no es confiable.ps -ef | awk -v pid=$$ '$2==pid { print $8 }'
es mejor, pero ¿por qué no solo usarps -p $$
?En Mac OS X (y FreeBSD):
fuente
zsh
, y me dio-bash
.mutt
...: -bNo es necesario agrupar el PID de la salida de "ps", ya que puede leer la línea de comando correspondiente para cualquier PID desde la estructura del directorio / proc
Sin embargo, eso podría no ser mejor que simplemente:
Acerca de ejecutar un shell realmente diferente al que indica el nombre, una idea es solicitar la versión del shell utilizando el nombre que obtuvo anteriormente:
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):fuente
Esta no es una solución muy limpia, pero hace lo que quieres.
Ahora puedes usar
$(getshell) --version
.Sin embargo, esto funciona solo en shells similares a KornShell (ksh).
fuente
dash
,yash
etc. Normalmente, si está utilizandobash
,zsh
,ksh
, lo que sea - no debe preocuparse por esas cosas.ksh
el conjunto de características es principalmente un subconjunto debash
características (aunque no lo he comprobado a fondo).Haga lo siguiente para saber si su shell está usando Dash / Bash.
ls –la /bin/sh
:si el resultado es
/bin/sh -> /bin/bash
==> Entonces su shell está usando 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
(cambiar shell a Bash)Nota : Si el comando anterior da como resultado un error que dice, / bin / sh ya existe, elimine / bin / sh e intente nuevamente.
fuente
Y se me ocurrió esto
fuente
Utilice amablemente el siguiente comando:
fuente
echo $SHELL
hace lo que estás tratando de hacer y hazlo bien. El segundo tampoco es bueno, porque$SHELL
la variable de entorno contiene un shell predeterminado para un usuario actual, no un shell actualmente en ejecución. Si, por ejemplo, lobash
configuro como shell predeterminado, ejecutarzsh
yecho $SHELL
, se imprimirábash
.echo $SHELL
puede ser basura:~ $ echo $SHELL /bin/zsh ~ $ bash bash-4.3$ echo $SHELL /bin/zsh bash-4.3$
Este funciona bien en Red Hat Linux (RHEL), macOS, BSD y algunos AIX :
alternativamente, el siguiente también debería funcionar si pstree está disponible,
fuente