¿Cómo puede determinar mi script si se ejecuta mediante bash o dash?

13

Estoy ejecutando una nueva instalación de Oneiric (es decir, no una actualización) en dos sistemas diferentes y me encuentro con el mismo conjunto de problemas aparentemente relacionados.

Lo más frustrante del grupo es que, cuando uso el .profile y .bashrc que he llevado conmigo desde Mac OS X, iniciar sesión en X a través de LightDM me desconecta de inmediato. Creo que esto se debe al hecho de que, cuando se ejecuta "/ bin / sh", se comporta como / bin / dash, pero aún tiene la variable $ SHELL establecida en / bin / bash.

Extrapolación

Tengo una enorme .bashrc. Puede verlo aquí si lo desea, pero su contenido probablemente no sea relevante, aparte del hecho de que está lleno de bashismos y el hecho de que funciona sin errores dentro de xterm o en una consola virtual.

Mi .profileaspecto es el siguiente (abreviado):

case $SHELL in 
*bash*)
    if [ -f $HOME/.bashrc -a -r $HOME/.bashrc ]; then
        . $HOME/.bashrc
    fi
    ;;
esac

Si intento iniciar sesión en X a través de LightDM, me desconectará inmediatamente. Recibo errores .xsession-errorsrelacionados con mi .bashrc que se ven así (abreviados):

/home/mrled/.bashrc: 103: [[: not found
[: 103: Linux: unexpected operator
[: 274: -P :: unexpected operator
/home/mrled/.bashrc: 520: complete: not found

Como dije, cuando ejecuto bash desde una consola virtual, no obtengo estos errores. Además, si elimino mi .profile, puedo iniciar sesión en X muy bien. (También puedo iniciar sesión en una consola virtual y usarla startxpara iniciar una sesión X que funcione, pero esto, por supuesto, no es una solución a largo plazo).

Sin embargo, he descubierto que si me quedo /bin/sh -l, yo no consigo los errores. Aquí hay una sesión de ejemplo (nota: el indicador bash me he simplificado bash>, y el indicador sh es solo $):

bash> echo $SHELL
/bin/bash
bash> echo $BASH_VERSION
4.2.10(1)-release
bash> /bin/sh -l
/home/mrled/.bashrc: 103: [[: not found
[: 103: Linux: unexpected operator
[: 274: -P :: unexpected operator
/home/mrled/.bashrc: 520: complete: not found
$ echo $SHELL
/bin/bash
$ echo $BASH_VERSION

$

Q1: ¿Por qué está sucediendo esto?

Entiendo que / bin / sh ahora apunta a guión en lugar de bash , pero si eso es cierto, ¿por qué $SHELLsigue regresando /bin/bash?

P2: ¿Qué puedo hacer para solucionarlo?

¿Hay alguna manera de evitar esto? Quiero mantener mi perfil cargando .bashrc para obtener el mismo entorno tanto en los shells de inicio de sesión como de inicio de sesión, pero obviamente solo quiero que se cargue para bash en sí, no / bin / sh enmascarado como bash.

Es posible que haya notado la diferencia en el contenido de las variables $ BASH_VERSION anteriores. He intentado envolver mi .profile en algo como esto:

if [ -n $BASH_VERSION ]; then
    # the rest of my .profile as above
fi

La -nprueba debe devolver verdadero solo si la longitud de la cadena no es cero, sin embargo, aunque en la sesión anterior, cuando la estoy ejecutando /bin/sh -l, devuelve una cadena vacía para $ BASH_VERSION, cuando está incluida en mi perfil. , pasa la prueba! Se procede a la fuente de mi .bashrc y me da los mismos errores que antes.

Ahora estoy realmente confundido.

Micah R Ledbetter
fuente
Tenga en cuenta que dash -ltambién muestra $SHELLtener el valor /bin/bash.
Scott Severance
3
$SHELLes lo que dice el último campo en /etc/passwd(o getent passwd).
Pausado hasta nuevo aviso.
@DennisWilliamson Gracias , eso es lo que necesitaba saber para encontrar la respuesta correcta.
Micah R Ledbetter
Lo estás haciendo mal. Debe colocar un entorno no específico de bash, elementos específicos de ~/.profilebash ~/.bashrcy tener ~/.bash_profilefuente de ambos.
nyuszika7h

Respuestas:

12

Puede hacer que el hecho de que $BASH_VERSIONesté en blanco en el dashtrabajo para usted:

if [ "$BASH_VERSION" = '' ]; then
    echo "This is dash."
else
    echo "This is bash."
fi
Scott Cesantía
fuente
2
La técnica "x" es arcaica y solo se necesita en conchas antiguas . Usoif [ "$BASH_VERSION" = '' ]
pausa hasta nuevo aviso.
@DennisWilliamson: Gracias. Pensé que tu técnica era específica de Bash, pero la descansé en Dash y funcionó. He editado mi respuesta.
Scott Severance
O simplemente usar-n , o nada . (+1, sin embargo. = ''Funciona perfectamente bien.)
Eliah Kagan
5

Solo tiene que usar comillas en la variable BASH_VERSIONpara usar-n

if [ -n "$BASH_VERSION" ];then
 echo "this is bash"; 
else 
 echo "this is dash";
fi
GM-Script-Writer-62850
fuente
1
como [ "$EMPTY_STRING" ]evalúa falso, ni siquiera necesita el -n. Solo tienes que citar la variable.
jeberle
2

Use /proc/[PID]/cmdlinepara ver con qué se ejecuta el script y pruebe lo que contiene. La $$variable nos dará el PID del shell en ejecución. Así podemos hacer un guión como este,

#!/bin/bash
if grep -q 'bash' /proc/$$/cmdline ;
then
    echo "This is bash"
else
    echo "This is some other shell"
fi

Aquí hay una prueba del mismo script:

$> bash test_script.sh                                                                                                
This is bash
$> dash test_script.sh                                                                                                
This is some other shell
Sergiy Kolodyazhnyy
fuente
Esto no funcionará en Mac. Verifique $ BASH_VERSION.
Austin Burk
2
@AustinBurk no necesita trabajar en Mac. Esto es Ask Ubuntu.
TheWanderer
@ Zacharee1 oh maldita sea, no estaba prestando atención:)
Austin Burk
No quiero editar esto lejos de lo que pretendes, pero sugiero mencionar las limitaciones de este método. Bash no necesita tener bashsu nombre; No es raro que el bashejecutable se ejecute a través de un enlace simbólico con otro nombre. Por lo general, uno todavía querría considerar ese Bash. Además, el patrón coincide en cualquier lugar/proc/$$/cmdline , lo que debería ser posible corregir, pero tenga en cuenta que los argumentos cmdlineestán delimitados por caracteres nulos. grep -qE '(^|/)bash$'siente que debería funcionar, pero da un falso positivo cuando cualquier argumento lo es bash.
Eliah Kagan el
@EliahKagan Siéntase libre de editar mis respuestas en cualquier momento: tiene suficiente experiencia para que sepa que sus ediciones solo pueden ofrecer mejoras. La respuesta fue escrita cuando era mucho más verde con las conchas que ahora.
Sergiy Kolodyazhnyy