Jaki cel robi [ -n "$PS1" ]
się [ -n "$PS1" ] && source ~/.bash_profile;
służyć? Ta linia jest zawarta w repozytorium.bashrc
dotfiles .
10
Jaki cel robi [ -n "$PS1" ]
się [ -n "$PS1" ] && source ~/.bash_profile;
służyć? Ta linia jest zawarta w repozytorium.bashrc
dotfiles .
Sprawdza to, czy powłoka jest interaktywna, czy nie. W takim przypadku pozyskiwanie ~/.bash_profile
pliku jest możliwe tylko wtedy, gdy powłoka jest interaktywna.
Zobacz „Czy to Shell Interactive?” w podręczniku bash, który cytuje ten konkretny idiom. (Zaleca się również sprawdzenie, czy powłoka jest interaktywna, poprzez sprawdzenie, czy $-
zmienna specjalna zawiera i
znak, co jest lepszym podejściem do tego problemu).
( export PS1='abc$ '; bash -c 'echo "[$PS1]"' )
, które po prostu drukuje[]
. Wydaje zsh nie to samo, co najmniej z doświadczenia ... W każdym razie zamiar z[ -n "$PS1" ]
jest sprawdzenie, czy powłoka jest interaktywna, czy nie.bash
rozbija PS1, gdy nieinteraktywny (literówka w poprzednim komentarzu) jest błędem IMO, PS1 nie jest zmienną specyficzną dla bash, nie ma biznesu, który mógłby go rozbroić. Jest to jedyna powłoka, która to robi (chociażyash
ustawia takżePS1
wartość domyślną, nawet gdy nie jest interaktywna).[[ $- = *i* ]] && source ~/.bash_profile
).[ -n "${PS1}" ]
, ale wciąż aktualizowałem swoją odpowiedź, aby podkreślić, że instrukcja bash sugeruje / zaleca sprawdzenie,$-
czy powłoka jest interaktywna, mam nadzieję, że znajdziesz lepszą odpowiedź. Twoje zdrowie!Co to robi?
Jest to szeroko rozpowszechniony sposób testowania, czy powłoka jest interaktywna. Uważaj, że działa tylko w trybie bash, nie działa z innymi powłokami. Więc jest w porządku (choć głupie)
.bashrc
, ale nie działałoby.profile
(co jest czytane przez sh, a bash jest tylko jedną z możliwych implementacji sh, a nie najczęstszą).Dlaczego to działa (tylko w bash!)
Interaktywna powłoka ustawia zmienną powłoki
PS1
na domyślny ciąg znaków zachęty. Więc jeśli powłoka jest interaktywna,PS1
jest ustawiona (chyba że użytkownik.bashrc
ją usunął, co nie mogło się jeszcze zdarzyć na górze.bashrc
, a można by uznać, że i tak jest to głupie).Odwrotna sytuacja jest prawdziwa w przypadku bash: nieinteraktywne instancje bash są rozbrojone
PS1
po uruchomieniu. Zauważ, że to zachowanie jest specyficzne dla bash i jest prawdopodobnie błędem (dlaczegobash -c '… do stuff with $var…'
nie miałoby działać, kiedyvar
jestPS1
?). Ale robią to wszystkie wersje bash do 4.4 (najnowsza wersja jak piszę).Wiele systemów eksportuje
PS1
do środowiska. Jest to zły pomysł, ponieważ wiele różnych powłok używa,PS1
ale ma inną składnię (np . Szybkie zmiany znaczenia bash są całkowicie różne od szybkich zmian znaczenia zsh ). Ale jest wystarczająco rozpowszechniony, że w praktyce sprawdzenie, czyPS1
jest ustawione, nie jest wiarygodnym wskaźnikiem interaktywności powłoki. Powłoka mogła odziedziczyćPS1
po środowisku.Dlaczego jest (źle) używany tutaj
.bashrc
to plik, który bash czyta podczas uruchamiania, gdy jest interaktywny. Mniej znanym faktem jest to, że bash czyta również.bashrc
powłokę logowania, a heurystyka basha stwierdza, że jest to sesja zdalna (bash sprawdza, czy jej rodzicem jestrshd
lubsshd
). W tym drugim przypadku jest mało prawdopodobne,PS1
aby został ustawiony w środowisku, ponieważ nie został jeszcze uruchomiony żaden plik kropkowy.Jednak sposób, w jaki kod wykorzystuje te informacje, przynosi efekt przeciwny do zamierzonego.
.bash_profile
w tej powłoce. Ale.bash_profile
to skrypt czasu logowania. Może uruchamiać niektóre programy, które mają być uruchamiane tylko raz na sesję. Może to zastąpić niektóre zmienne środowiskowe, które użytkownik celowo ustawił na inną wartość przed uruchomieniem tej powłoki. Uruchamianie.bash_profile
w powłoce niezalogowanej jest uciążliwe..bash_profile
. Ale jest to przypadek, w którym ładowanie.bash_profile
może być przydatne, ponieważ nieinteraktywna powłoka logowania nie ładuje się automatycznie/etc/profile
i~/.profile
.Myślę, że ludzie robią to dla użytkowników, którzy logują się przez GUI (bardzo częsty przypadek) i
.bash_profile
zamiast tego wprowadzają ustawienia zmiennych środowiskowych.profile
. Większość mechanizmów logowania GUI wywołuje,.profile
ale nie uruchamia się.bash_profile
(czytanie.bash_profile
wymagałoby uruchomienia bash w ramach uruchamiania sesji, zamiast sh). W tej konfiguracji, gdy użytkownik otworzy terminal, otrzyma swoje zmienne środowiskowe. Jednak użytkownik nie otrzyma swoich zmiennych środowiskowych w aplikacjach GUI, co jest bardzo częstym źródłem zamieszania. Rozwiązaniem jest użycie.profile
zamiast.bash_profile
ustawiania zmiennych środowiskowych. Dodanie pomostu.bashrc
i.bash_profile
stwarza więcej problemów niż rozwiązuje.Co zamiast tego zrobić
Istnieje prosty, przenośny sposób testowania, czy bieżąca powłoka jest interaktywna:
-i
sprawdź, czy opcja jest włączona.Przydaje się to
.bashrc
do odczytu.profile
tylko wtedy, gdy powłoka nie jest interaktywna - tzn. Odwrotnie niż w kodzie! Przeczytaj,.profile
czy bash jest (nieinteraktywną) powłoką logowania i nie czytaj jej, jeśli jest to powłoka interaktywna.źródło
[[ -o interactive ]]
(ksh, bash, zsh) lubcase $- in (*i*) ...; esac
(POSIX)PS1
jeśli nie działa interaktywnie. Łatwo jest przetestować:PS1=cuckoo bash -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'
nic nie wydrukuje, aPS1=cuckoo bash -i -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'
wypisze wartość$PS1
zestawu w twoich plikach startowych bash (nie wydrukuje ciągu „kukułka”).$-
zawierałi
interaktywną powłokę.[ -n "${PS1}" ]
niewłaściwe dzwonienie posuwa się trochę za daleko, w końcu psuje się tylko wtedy, gdy ktoś eksportuje PS1 (co w twojej odpowiedzi mówisz, że to zły pomysł, a nawet rozumiesz, dlaczego) i to nie ma wpływu i tak bash (ponieważ odznacza PS1 i PS2, jeśli powłoka nie jest interaktywna). Być może lepiej byłoby użyć słowa takiego jak „zniechęcenie” lub mówienie o „ograniczeniach” podejścia. Nie sądzę, żeby to było „złe”. Jeśli coś jest nie tak, to eksport PS1, to na pewno! Tak czy inaczej, dzięki za zapoznanie się ze szczegółami tego.Wygląda na to, że ta dziwna koncepcja wynika z faktu, że
bash
nie zaczął się jako klon powłoki POSIX, ale jakoBourne Shell
klon.W rezultacie zachowanie interaktywne POSIX (
$ENV
wywoływane dla interaktywnych powłok) zostało dodane późniejbash
i nie jest powszechnie znane.Jest jedna powłoka, która zapewnia podobne zachowanie. To jest
csh
i csh przyznaje, które$prompt
ma określone wartości:Ale nie dotyczy to ani powłoki Bourne'a, ani powłok POSIX.
W przypadku powłoki POSIX jedyną dozwoloną metodą jest umieszczenie kodu interaktywnych powłok w pliku:
który ma nazwę specyficzną dla powłoki. Jest to np
Inne osoby wspomniały o flagi powłoki
-i
, ale nie jest to użyteczne do niezawodnego programowania. POSIX nie wymaga, abyset -i
działał, ani że$-
zawierai
powłok interaktywnych. POSIX wymaga jedynie, abysh -i
wymusił powłokę w trybie interaktywnym.Ponieważ zmienna
$PS1
może być importowana ze środowiska, może mieć wartość nawet w trybie nieinteraktywnym. Fakt, żebash
unset
ówPS1
w dowolnym nieinterakcyjnym skorupy nie jest przyznawana w normie i nie odbywa się przez inną powłokę.Czyste programowanie (nawet przy pomocy
bash
) polega na wstawianiu poleceń interaktywnych powłok$HOME/.bashrc
.źródło
Najpierw porozmawiam o tym, co Debian, i przez większość czasu także Ubuntu ustawia się na bash. I ten ostatni dotyk w innych systemach.
W ustawieniach plików startowych powłoki jest wiele opinii.
Mam również swoją opinię, ale postaram się pokazać istniejące przykłady prawidłowych ustawień.
Użyję debuan, ponieważ dość łatwo jest znaleźć przykłady jego plików.
Debian jest często używany, więc ustawienia zostały dobrze przetestowane,
Jaki jest cel sprawdzenia, czy PS1 jest ustawiony?
Aby dowiedzieć się, czy powłoka jest interaktywna.
Domyślne
/etc/profile
w Debianie i Ubuntu (z / usr / share / base-files / profil):If jest czytany: jeśli interaktywny (domyślny zestaw PS1) i jest to powłoka bash (ale nie działa jako domyślna
sh
), to zmień PS1 na konkretną nową (nie domyślną).Domyślny
/etc/bash.bashrc
Debiana zawiera również:Co jest całkiem jasne w tym, co robi: Jeśli interaktywne nie źródło (reszta).
Jednak w
/etc/skel/.bashrc
jest przykładem poprawnego sposobu testowania interaktywnej powłoki (za pomocą$-
):To powinno jasno pokazać, dlaczego PS1 i jedna alternatywa.
Prawidłowa kolejność
Zgłaszanego ustawienia należy unikać.
Kolejność (od ustawień systemowych do bardziej szczegółowych ustawień użytkownika (bash)) jest
/etc/profile
,/etc/bash.bashrc
,~/.profile
i wreszcie~/.bashrc
. To umieszcza najszersze efekty (i więcej powłok) w/etc/profile
(który jest własnością roota), a następnie/etc/bash.bashrc
(który jest także własnością roota), ale wpływa tylko na bash. Następnie wprowadź ustawienia osobiste$HOME
, pierwsze dotyczy~/.profile
większości powłok i~/.bashrc
(prawie równoważne~/.bash_profile
), specyficzne tylko dla bash.Jest zatem właściwe źródła
~/.bashrc
w~/.profile
, to jest przekształcenie ustawienia dla bash do bardziej ogólnego, który jest użytkownikiem konkretnego wpływu na kolejne pociski . Z wyjątkiem sytuacji, gdy wykonano to w ten sposób :Sprawdza, czy bash jest uruchomiony i ładuje się tylko w
.bashrc
takim przypadku.Jest to decyzja podjęta przez Debiana. Uzasadnienie wyjaśniono tutaj .
Wręcz przeciwnie, pozyskiwanie
~/.profile
w~/.bash_profile
(lub~/.bashrc
) polega jedynie na ponownym stosowaniu ogólnych zasad, które powinny już zostać załadowane do konkretnego przypadku użycia, a zatem „nie jest tak źle” (nie mówię „dobry”). I nie mówię dobrze, ponieważ może to powodować zapętlenie pobierania plików. Podobnie jak w przypadku, gdy podkatalog ładuje element nadrzędny, jest to pętla katalogu.I właśnie w tym cross-sourcingu sprawdzanie interaktywnej powłoki ma sens. Tylko wtedy, gdy powłoka jest interaktywna, jest
~/.bashrc
ładowana, ale z kolei może się ładować~/.profile
(lub na odwrót) i w tym przypadku można użyć sprawdzenia powłoki interaktywnej.źródło