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 :
Bash próbuje ustalić, kiedy jest uruchamiany ze standardowym wejściem podłączonym do połączenia sieciowego, tak jak w przypadku wykonania przez zdalny demon powłoki, zwykle rshd
lub bezpieczny demon powłoki sshd
. Jeśli Bash ustali, że jest uruchamiany w ten sposób, czyta i wykonuje polecenia z ~ / .bashrc, jeśli plik ten istnieje i jest czytelny. Nie zrobi tego, jeśli zostanie wywołany jako sh
. --norc
Opcja może być stosowane do hamowania to zachowanie, a --rcfile
opcja może być wykorzystane do wymuszenia innego pliku do odczytania, ale ani rshd
nie sshd
wywołuje powłoki z tymi opcjami lub mogły być określone.
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):
echo bashrc
fun()
{
echo functions work
}
Uruchom następujące polecenia lokalnie:
$ ssh remote_host 'echo $- $0'
bashrc
hBc bash
- Brak
i
w $-
oznacza, że powłoka jest nieinteraktywna .
- Nie prowadząc
-
w $0
wskazuje, że powłoka nie jest powłoką zgłoszeniową .
.bashrc
Można również uruchamiać funkcje powłoki zdefiniowane w pilocie :
$ ssh remote_host fun
bashrc
functions work
Zauważyłem, że ~/.bashrc
jest ono pozyskiwane tylko wtedy, gdy jako argument dla podano polecenie ssh
. Ma to sens: kiedy ssh
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
lub ssh
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 jak rcp
, scp
i sftp
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óra scp
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
i sftp
nie
SCP (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
Co często zdarza się jednak, że są stwierdzenia zawarte w każdym systemie lub pliki startowe powłoki na użytkownika na serwerze ( .bashrc
, .profile
,
/etc/csh.cshrc
, .login
, itp), które wysyłają wiadomości tekstowe przy logowaniu, przeznaczona do odczytania przez człowieka (takich jak fortune
, echo "Hi there!"
, itp.).
Taki kod powinien generować dane wyjściowe przy logowaniu interaktywnym tylko wtedy, gdy jest
tty
dołączone do standardowego wejścia. Jeśli nie wykona tego testu, wstawi te wiadomości tekstowe tam, gdzie nie należą: w tym przypadku, zanieczyszczając strumień protokołu między scp2
/ sftp
a sftp-server
.
Powodem, dla którego pliki startowe powłoki są w ogóle istotne, jest to, że sshd
używa powłoki użytkownika podczas uruchamiania jakichkolwiek programów w imieniu użytkownika
(przy użyciu np. / Bin / sh -c „polecenia”). Jest to tradycja uniksowa i ma zalety:
- Zwykłe ustawienia użytkownika (aliasy poleceń, zmienne środowiskowe, umask itp.) Obowiązują podczas uruchamiania poleceń zdalnych.
- Powszechna praktyka ustawiania powłoki konta na / bin / false, aby ją wyłączyć, uniemożliwi właścicielowi uruchamianie jakichkolwiek poleceń, jeśli z jakiegoś powodu uwierzytelnianie nadal będzie przypadkowo pomyślne.
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? :
Może się to na przykład zdarzyć, jeśli dodasz to do profilu powłoki w systemie zdalnym:
Echo ""
Dlaczego po prostu się zawiesza? Wynika to ze sposobu, scp
w jaki w trybie źródłowym czeka na potwierdzenie pierwszego komunikatu protokołu. Jeśli nie jest to wartość binarna 0, oczekuje, że jest to powiadomienie o zdalnym problemie i czeka, aż więcej znaków utworzy komunikat o błędzie, aż nadejdzie nowa linia. Ponieważ nie wydrukowałeś kolejnej nowej linii po pierwszej, Twój lokalny scp
po prostu pozostaje w pętli, zablokowany read(2)
. W międzyczasie, po przetworzeniu profilu powłoki po stronie zdalnej, scp
uruchomiono tryb sink, który również się blokuje read(2)
, czekając na binarne zero oznaczające początek przesyłania danych.
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
lub ssh
. 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 jak scp
lub sftp
. Wyjście po sprawdzeniu, że bieżąca powłoka jest nieinteraktywna, jest najbezpieczniejszym zachowaniem .bashrc
.