Jaki cel robi [ -n "$PS1" ]
się [ -n "$PS1" ] && source ~/.bash_profile;
służyć? Ta linia jest zawarta w repozytorium.bashrc
dotfiles .
Jaki cel robi [ -n "$PS1" ]
się [ -n "$PS1" ] && source ~/.bash_profile;
służyć? Ta linia jest zawarta w repozytorium.bashrc
dotfiles .
Odpowiedzi:
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).
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że PS1
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!
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ą).
Interaktywna powłoka ustawia zmienną powłokiPS1
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 (dlaczego bash -c '… do stuff with $var…'
nie miałoby działać, kiedy var
jest PS1
?). 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, czy PS1
jest ustawione, nie jest wiarygodnym wskaźnikiem interaktywności powłoki. Powłoka mogła odziedziczyć PS1
po środowisku.
.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 jest rshd
lub sshd
). 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.
Istnieje prosty, przenośny sposób testowania, czy bieżąca powłoka jest interaktywna: -i
sprawdź, czy opcja jest włączona.
case $- in
*i*) echo "This shell is interactive";;
*) echo "This shell is not interactive";;
esac
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.
if [[ $- != *i* && -r ~/.profile ]]; then . ~/.profile; fi
[[ -o interactive ]]
(ksh, bash, zsh) lub case $- 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, a PS1=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 jako Bourne Shell
klon.
W rezultacie zachowanie interaktywne POSIX ( $ENV
wywoływane dla interaktywnych powłok) zostało dodane później bash
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:
$prompt not set non-interactive shell, test $?prompt.
$prompt set but == "" .cshrc called by the which(1) command.
$prompt set and != "" normal interactive shell.
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:
$ENV
który ma nazwę specyficzną dla powłoki. Jest to np
$HOME/.kshrc for the korn shell
$HOME/.bashrc for bash
$HOME/.mkshrc for mksh
$HOME/.shrc for the POSIX Bourne Shell
Inne osoby wspomniały o flagi powłoki -i
, ale nie jest to użyteczne do niezawodnego programowania. POSIX nie wymaga, aby set -i
działał, ani że $-
zawiera i
powłok interaktywnych. POSIX wymaga jedynie, aby sh -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, że bash
unset
ów PS1
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
.
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,
Aby dowiedzieć się, czy powłoka jest interaktywna.
Domyślne /etc/profile
w Debianie i Ubuntu (z / usr / share / base-files / profil):
if [ "${PS1-}" ]; then
if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
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ż:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
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ą $-
):
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
To powinno jasno pokazać, dlaczego PS1 i jedna alternatywa.
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 :
# ~/.profile: executed by the command interpreter for login shells
# if running bash
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
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.
( 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.