Korzystam z nowej instalacji Oneiric (tj. Bez aktualizacji) na dwóch różnych systemach i napotykam ten sam zestaw pozornie powiązanych problemów.
Najbardziej frustrujące jest to, że kiedy używam .profile i .bashrc, które zabrałem ze sobą z Mac OS X, zalogowanie się do X przez LightDM natychmiast mnie wylogowuje. Sądzę, że jest to spowodowane faktem, że po uruchomieniu „/ bin / sh” zachowuje się jak / bin / dash, ale nadal ma zmienną $ SHELL ustawioną na / bin / bash.
Ekstrapolacja
Mam ogromny .bashrc
. Możesz go zobaczyć tutaj, jeśli chcesz, ale jego zawartość prawdopodobnie nie jest istotna, poza tym, że jest pełen bashism i faktu, że działa bez błędów w xterm lub na wirtualnej konsoli.
Kim .profile
wygląda następująco (w skrócie):
case $SHELL in
*bash*)
if [ -f $HOME/.bashrc -a -r $HOME/.bashrc ]; then
. $HOME/.bashrc
fi
;;
esac
Jeśli spróbuję zalogować się do X przez LightDM, natychmiast mnie wyloguje. Występują błędy .xsession-errors
związane z moim .bashrc, które wyglądają tak (w skrócie):
/home/mrled/.bashrc: 103: [[: not found
[: 103: Linux: unexpected operator
[: 274: -P :: unexpected operator
/home/mrled/.bashrc: 520: complete: not found
Jak powiedziałem, kiedy uruchamiam bash z wirtualnej konsoli, nie otrzymuję tych błędów. Ponadto, jeśli usunę mój .profile, mogę zalogować się do X w porządku. (Mogę również zalogować się do wirtualnej konsoli i użyć startx
do zainicjowania sesji X, która działa, ale nie jest to oczywiście rozwiązanie długoterminowe).
Jednak odkryłem, że jeśli biegnę /bin/sh -l
, ja nie dostać błędy. Oto przykładowa sesja (uwaga: podpowiedź bash, którą uprościłem bash>
, a podpowiedź sh jest tylko $
):
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
$
P1: Dlaczego tak się dzieje?
Rozumiem, że / bin / sh wskazuje teraz na myślnik zamiast na bash , ale jeśli to prawda, to dlaczego $SHELL
wciąż powraca /bin/bash
?
Q2: Co mogę zrobić, aby obejść ten problem?
Czy istnieje sposób na obejście tego? Chcę, aby mój profil ładował plik .bashrc, aby uzyskać to samo środowisko zarówno dla powłok logowania, jak i bez logowania, ale oczywiście chcę, aby ładowało się tylko dla samego basha, a nie / bin / sh podszywającego się pod bash.
Być może zauważyłeś różnicę w treści zmiennych $ BASH_VERSION powyżej. Próbowałem zawinąć mój .profile w coś takiego:
if [ -n $BASH_VERSION ]; then
# the rest of my .profile as above
fi
-n
Test powinien wrócić prawdziwe tylko wtedy, gdy długość łańcucha jest różna od zera, jednak, choć w sesji powyżej, kiedy biegnę pod /bin/sh -l
zwraca pusty ciąg dla $ BASH_VERSION, gdy jest zawarte w moim .profile jak ta , przechodzi test! Następnie przechodzą do źródła .bashrc i dają te same błędy, co poprzednio.
Teraz jestem naprawdę zdezorientowany.
źródło
dash -l
pokazuje również$SHELL
posiadanie wartości/bin/bash
.$SHELL
jest tym, co mówi ostatnie pole w/etc/passwd
(lubgetent passwd
).~/.profile
bash, rzeczy specyficzne dla bash~/.bashrc
i mieć~/.bash_profile
oba źródła.Odpowiedzi:
Możesz sprawić, że fakt, który
$BASH_VERSION
jest pusty,dash
działa dla Ciebie:źródło
if [ "$BASH_VERSION" = '' ]
-n
lub nic . (+1, chociaż.= ''
Działa doskonale.)Wystarczy użyć cudzysłowu na zmiennej,
BASH_VERSION
aby użyć-n
źródło
[ "$EMPTY_STRING" ]
ocenia fałsz, nawet nie potrzebujesz-n
. Musisz tylko podać zmienną.Użyj,
/proc/[PID]/cmdline
aby zobaczyć, z czym skrypt jest uruchamiany i przetestować, co zawiera.$$
Zmienna da nam PID uruchomionego powłoki. W ten sposób możemy stworzyć taki skrypt,Oto test tego samego skryptu:
źródło
bash
w swoim imieniu; zdarza się, żebash
plik wykonywalny jest uruchamiany przez dowiązanie symboliczne o innej nazwie. Zwykle nadal chciałoby się rozważyć Bash. Ponadto wzorzec jest dopasowywany w dowolnym miejscu/proc/$$/cmdline
, co powinno być możliwe do naprawienia, ale należy pamiętać, że argumentycmdline
są rozdzielane znakami zerowymi.grep -qE '(^|/)bash$'
wydaje się, że powinno działać, ale daje fałszywy wynik pozytywny, gdy jest jakiś argumentbash
.