W moim Arch zainstaluj /etc/bash.bashrc
i /etc/skel/.bashrc
zawierają te linie:
# If not running interactively, don't do anything
[[ $- != *i* ]] && return
W Debianie /etc/bash.bashrc
ma:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
I /etc/skel/.bashrc
:
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
Według man bash
nieinteraktywnych powłok nawet nie czytają tych plików:
When bash is started non-interactively, to run a shell script, for
example, it looks for the variable BASH_ENV in the environment, expands
its value if it appears there, and uses the expanded value as the name
of a file to read and execute. Bash behaves as if the following com‐
mand were executed:
if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
but the value of the PATH variable is not used to search for the file‐
name.
Jeśli dobrze rozumiem, *.bashrc
pliki zostaną odczytane tylko wtedy, gdy BASH_ENV
jest ustawione na ich wskazywanie. Jest to coś, co nie może się zdarzyć przypadkowo i nastąpi tylko wtedy, gdy ktoś wyraźnie ustawił odpowiednio zmienną.
Wydaje się, że łamie to możliwość .bashrc
automatycznego uruchamiania skryptów przez użytkownika, ustawiając BASH_ENV
coś, co może się przydać. Biorąc pod uwagę, że bash nigdy nie odczyta tych plików, gdy zostaną uruchomione bez interakcji, chyba że zostanie to wyraźnie nakazane, dlaczego *bashrc
pliki domyślne nie pozwalają na to?
Odpowiedzi:
To pytanie zamieściłem tutaj kilka tygodni temu. Podobnie jak terdon , zrozumiałem, że a
.bashrc
jest pozyskiwane tylko dla interaktywnych powłok Bash, więc nie powinno być potrzeby.bashrc
sprawdzania, czy działa w interaktywnej powłoce. Mylące jest to, że wszystkie używane przeze mnie dystrybucje (Ubuntu, RHEL i Cygwin) miały pewien rodzaj sprawdzania (testowania$-
lub$PS1
), aby upewnić się, że bieżąca powłoka jest interaktywna. Nie lubię programowania kultowego, więc postanowiłem zrozumieć cel tego kodu.bashrc
.Bash ma specjalny futerał na zdalne powłoki
Po zbadaniu problemu odkryłem, że odległe powłoki są traktowane inaczej. Chociaż nieinteraktywne powłoki Bash zwykle nie uruchamiają
~/.bashrc
poleceń podczas uruchamiania, zachodzi szczególny przypadek, gdy powłoka jest wywoływana przez zdalny demon powłoki :Przykład
Wstaw następujące na początku pilota
.bashrc
. (Jeśli.bashrc
pochodzi z.profile
lub.bash_profile
, tymczasowo wyłącz to podczas testowania):Uruchom następujące polecenia lokalnie:
i
w$-
oznacza, że powłoka jest nieinteraktywna .-
w$0
wskazuje, że powłoka nie jest powłoką zgłoszeniową ..bashrc
Można również uruchamiać funkcje powłoki zdefiniowane w pilocie :Zauważyłem, że
~/.bashrc
jest ono pozyskiwane tylko wtedy, gdy jako argument dla podano poleceniessh
. Ma to sens: kiedyssh
służy do uruchomienia zwykłej powłoki logowania.profile
lub.bash_profile
jest uruchamiany (i.bashrc
jest pozyskiwany tylko wtedy, gdy jest to jawnie zrobione przez jeden z tych plików).Główną korzyścią, jaką widzę po uzyskaniu
.bashrc
źródła podczas uruchamiania (nieinteraktywnego) polecenia zdalnego, jest możliwość uruchamiania funkcji powłoki. Jednak większość poleceń w typowym.bashrc
przypadku dotyczy tylko interaktywnej powłoki, np. Aliasy nie są rozwijane, chyba że powłoka jest interaktywna.Zdalne przesyłanie plików może się nie powieść
Zwykle nie stanowi to problemu, gdy
rsh
lubssh
są używane do uruchomienia interaktywnej powłoki logowania lub gdy nieinteraktywne powłoki są używane do uruchamiania poleceń. Jednak to może być problem dla programów takich jakrcp
,scp
isftp
które wykorzystują zdalne muszle do przesyłania danych.Okazuje się, że domyślna powłoka zdalnego użytkownika (jak Bash) jest domyślnie uruchamiana podczas korzystania z
scp
polecenia. Nie ma wzmianki o tym na stronie podręcznika - tylko wzmianka, którascp
wykorzystuje sięssh
do przesyłania danych. Powoduje to, że jeśli.bashrc
zawiera jakiekolwiek polecenia wypisywane na standardowe wyjście, przesyłanie plików zakończy się niepowodzeniem , np. Scp nie powiedzie się bez błędu .Zobacz także pokrewny raport o błędach Red Hat sprzed 15 lat, scp psuje się, gdy w / etc / bashrc znajduje się polecenie echa (które ostatecznie zostało zamknięte jako
WONTFIX
).Dlaczego
scp
isftp
nieSCP (Secure copy) i SFTP (Secure File Transfer Protocol) mają własne protokoły dla lokalnego i zdalnego końca do wymiany informacji o przesyłanych plikach. Każdy nieoczekiwany tekst ze zdalnego końca jest (nieprawidłowo) interpretowany jako część protokołu i przesyłanie nie powiedzie się. Według FAQ z Snail Book
Szczegóły protokołu SCP
Dla osób zainteresowanych szczegółami działania SCP znalazłem ciekawe informacje w artykule Jak działa protokół SCP, który zawiera szczegółowe informacje na temat Uruchamiania scp z gadatliwymi profilami powłoki po drugiej stronie? :
Wniosek / TLDR
Większość instrukcji w typowym przypadku
.bashrc
jest użyteczna tylko dla interaktywnej powłoki - nie podczas uruchamiania poleceń zdalnych za pomocąrsh
lubssh
. W większości takich sytuacji ustawianie zmiennych powłoki, aliasów i definiowanie funkcji nie jest pożądane - a drukowanie dowolnego tekstu na standard jest aktywnie szkodliwe, jeśli pliki są przesyłane za pomocą programów takich jakscp
lubsftp
. Wyjście po sprawdzeniu, że bieżąca powłoka jest nieinteraktywna, jest najbezpieczniejszym zachowaniem.bashrc
.źródło
Strona podręcznika nie wspomina o
bash
źródłach.bashrc
nieinteraktywnych zdalnych powłok, jak whttp://git.savannah.gnu.org/cgit/bash.git/tree/shell.c#n1010
http://git.savannah.gnu.org/cgit/bash.git/tree/shell.c#n1050
źródło
.bash_profile
pokazałby to samo zachowanie.rsh
(z których nigdy nie korzystałem) źródła~/.bashrc
? A przez to, że dystrybucje Linuksa blokują go nabash
wypadek, gdyby ktoś próbował uruchomić skryptrsh
?ssh server
nie powinien się dotykać,.bashrc
ponieważ i tak jest to powłoka logowania. Nie, chyba że twój system jest jednym z tych, które źródło ~ / .bashrc`~/.profile
. Issh server command
nawet nie powinienem tego robić. Na pewno nie ma w moim systemie.bash
źródłem, a nie zersh
źródłem. :) Komentarz dotyczyssh
również, został napisany bardzo dawno temu. Zobacz zaktualizowaną odpowiedź z większym źródłem.echo
na samym szczycie/etc/bash.bashrc
i~/.bashrc
(przed interaktywnymi testami powłoki), a następnie ssh na maszynie docelowej za pomocąssh server hostname
i podczashostname
działania, nie widziałem żadnego z moich ech. Czy to, że mójshell_level
(cokolwiek to jest) nie jest<2
?Zgodnie z konwencją
.bashrc
to miejsce, w którym użytkownik przechowuje niestandardową konfigurację powłoki.Tymi dostosowanymi konfiguracjami mogą być zmienne środowiskowe, aliasy, fantazyjne monity. Z nieinteraktywną powłoką te rzeczy są bez znaczenia. Co więcej, nieinteraktywna powłoka może być wywoływana w wielu kontekstach, nie jesteś pewien, że te zmienne środowiskowe mogą prowadzić do fałszywie ujemnych liter, a nawet podatności na zagrożenia.
Najbliższym przykładem jest alias taki jak:
Następnie zawiesi na zawsze twoją nieinteraktywną powłokę.
Sprawdzanie
.bashrc
odbywa się u góry, aby upewnić się, że nie wystąpią problemy.Ponieważ powłoka może być wywoływana jako nieinteraktywna powłoka logowania , więc jawne blokowanie pozyskiwania
*bashrc
nie ma sensu.Gdy powłoka została wywołana jako nieinterakcyjnym powłoki logowania , to źródło
/etc/profile
, a następnie pozyskać pierwszy znaleziony w~/.bash_profile
,~/.bash_login
i~/.profile
:Nic nie stoi na przeszkodzie, aby te pliki
.bashrc
same się pozyskiwały , więc sprawdzanie w środku.bashrc
jest bezpieczniejsze i upraszcza sprawę.źródło
*bashrc
plików. Moje pytanie brzmi: dlaczego różni dostawcy Linuksa mają problem z jawnym blokowaniem nieinteraktywnych powłok przed odczytaniem tych plików, jeśli te pliki i tak nie są odczytywane przez powłoki nieinteraktywne..bash_profile
, które może być źródłem.bashrc
.$BASH_ENV
. Zarówno*profile
i*bashrc
są ignorowane. A przynajmniej tak mówi strona podręcznika. Jednak, jak pokazał Mikel, strona podręcznika użytkownika może kłamać.bash -l -c :
wywołać nieinteraktywną powłokę logowania?--login
100 razy, ale najwyraźniej nigdy się nie zarejestrowała. Dzięki!