Come può il mio script determinare se è gestito da bash o dash?


13

Sto eseguendo una nuova installazione di Oneiric (ovvero non un aggiornamento) su due sistemi diversi e sto eseguendo lo stesso set di problemi apparentemente correlati.

Il più frustrante del gruppo è che, quando uso i file .profile e .bashrc che ho portato con me da Mac OS X, accedendo a X tramite LightDM mi disconnette immediatamente. Credo che ciò sia causato dal fatto che, quando esegue "/ bin / sh", si comporta come / bin / dash, ma ha ancora la variabile $ SHELL impostata su / bin / bash.

Estrapolazione

Ho un enorme .bashrc. Puoi vederlo qui se vuoi, ma i suoi contenuti probabilmente non sono rilevanti, a parte il fatto che è pieno di bashismi e il fatto che funzioni senza errori all'interno di xterm o su una console virtuale.

Il mio .profileassomiglia a questo (abbreviato):

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

Se provo ad accedere a X tramite LightDM, mi disconnetterà immediatamente. Ricevo errori nel .xsession-errorsmio .bashrc che sembrano così (abbreviati):

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

Come ho detto, quando eseguo bash da una console virtuale, non ottengo questi errori. Inoltre, se rimuovo il mio .profile, posso accedere a X bene. (Posso anche accedere a una console virtuale e utilizzare startxper avviare una sessione X che funziona, ma questa ovviamente non è una soluzione a lungo termine.)

Tuttavia, ho scoperto che se corro /bin/sh -l, io non ricevo gli errori. Ecco una sessione di esempio (nota: il prompt di bash che ho semplificato bash>e il prompt di sh è giusto $):

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: Perché sta succedendo questo?

Capisco che / bin / sh ora punta a trattino piuttosto che bash , ma se questo è vero, allora perché sta $SHELLancora ritornando /bin/bash?

Q2: cosa posso fare per aggirare il problema?

C'è un modo per aggirare questo? Voglio mantenere il mio profilo caricando .bashrc in modo da ottenere lo stesso ambiente su entrambe le shell di login e non login, ma ovviamente voglio solo caricarlo per bash stesso, non / bin / sh mascherato da bash.

Potresti aver notato la differenza nel contenuto delle variabili $ BASH_VERSION sopra. Ho provato a racchiudere il mio .profile in qualcosa del genere:

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

Il -ntest dovrebbe restituire true solo se la lunghezza della stringa è diversa da zero, tuttavia, anche se nella sessione precedente, quando sono in esecuzione sotto di /bin/sh -lessa restituisce una stringa vuota per $ BASH_VERSION, quando è inclusa nel mio .profile in questo modo , supera il test! Procede per procurarsi il mio .bashrc e darmi gli stessi errori di prima.

Ora sono davvero confuso.


Si noti che dash -lmostra anche $SHELLavere il valore /bin/bash.
Scott Severance,

3
$SHELLè quello che dice l'ultimo campo in /etc/passwd(o getent passwd).
In pausa fino a ulteriore avviso.

@DennisWilliamson Grazie , è quello che dovevo sapere per trovare la risposta giusta.
Micah R Ledbetter il

Lo stai facendo male. Dovresti inserire un ambiente non specifico per ~/.profileBash, cose specifiche per Bash ~/.bashrce avere ~/.bash_profileentrambi i sorgenti.
nyuszika7h,

Risposte:


12

Puoi rendere il fatto che $BASH_VERSIONè vuoto nel dashlavoro per te:

if [ "$BASH_VERSION" = '' ]; then
    echo "This is dash."
else
    echo "This is bash."
fi

2
La tecnica "x" è arcaica e necessaria solo nelle antiche conchiglie. Usaif [ "$BASH_VERSION" = '' ]
pausa fino a nuovo avviso.

@DennisWilliamson: grazie. Pensavo che la tua tecnica fosse specifica per Bash, ma l'ho semplicemente riposata in Dash e ha funzionato. Ho modificato la mia risposta.
Scott Severance

O semplicemente usa-n , o niente . (+1, però. = ''Funziona perfettamente.)
Eliah Kagan

5

Devi solo usare le virgolette sulla variabile BASH_VERSIONda usare-n

if [ -n "$BASH_VERSION" ];then
 echo "this is bash"; 
else 
 echo "this is dash";
fi

1
poiché [ "$EMPTY_STRING" ]valuta falso, non è nemmeno necessario -n. Devi solo citare la variabile.
jeberle

2

Utilizzare /proc/[PID]/cmdlineper vedere con cosa viene eseguito lo script e testare ciò che contiene. La $$variabile ci darà il PID della shell in esecuzione. Quindi possiamo creare una sceneggiatura come questa,

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

Ecco un test dello stesso script:

$> bash test_script.sh                                                                                                
This is bash
$> dash test_script.sh                                                                                                
This is some other shell

Questo non funzionerà su Mac. Controlla $ BASH_VERSION.
Austin Burk,

2
@AustinBurk non ha bisogno di funzionare su Mac. Questo è Chiedi a Ubuntu.
TheWanderer,

@ Zacharee1 oh maledizione, non stavo prestando attenzione:,)
Austin Burk,

Non voglio modificarlo lontano da ciò che intendi, ma suggerisco di menzionare i limiti di questo metodo. Bash non ha bisogno di avere bashnel suo nome; non è raro che l' basheseguibile venga eseguito tramite un collegamento simbolico con un altro nome. Di solito si vorrebbe ancora considerare quel Bash. Inoltre, il modello è abbinato ovunque in/proc/$$/cmdline , che dovrebbe essere possibile fissare, ma di tenere presente che gli argomenti in cmdlinesono nulli caratteri delimitato. grep -qE '(^|/)bash$'sembra che dovrebbe funzionare, ma dà un falso positivo quando qualsiasi argomento lo è bash.
Eliah Kagan,

@EliahKagan Sentiti libero di modificare le mie risposte in qualsiasi momento: hai esperienza sufficiente, quindi so che le tue modifiche possono offrire solo miglioramenti. La risposta è stata scritta quando ero molto più verde con le conchiglie di quanto lo sia ora.
Sergiy Kolodyazhnyy,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.