To pytanie zamieściłem tutaj kilka tygodni temu. Podobnie jak terdon , zrozumiałem, że a .bashrcjest pozyskiwane tylko dla interaktywnych powłok Bash, więc nie powinno być potrzeby .bashrcsprawdzania, 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ą ~/.bashrcpoleceń 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 rshdlub 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. --norcOpcja może być stosowane do hamowania to zachowanie, a --rcfileopcja może być wykorzystane do wymuszenia innego pliku do odczytania, ale ani rshdnie sshdwywoł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 .bashrcpochodzi z .profilelub .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
iw $-oznacza, że powłoka jest nieinteraktywna .
- Nie prowadząc
-w $0wskazuje, że powłoka nie jest powłoką zgłoszeniową .
.bashrcMożna również uruchamiać funkcje powłoki zdefiniowane w pilocie :
$ ssh remote_host fun
bashrc
functions work
Zauważyłem, że ~/.bashrcjest ono pozyskiwane tylko wtedy, gdy jako argument dla podano polecenie ssh. Ma to sens: kiedy sshsłuży do uruchomienia zwykłej powłoki logowania .profilelub .bash_profilejest uruchamiany (i .bashrcjest 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 .bashrcprzypadku 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 rshlub sshsą 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, scpi sftpktó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 scppolecenia. Nie ma wzmianki o tym na stronie podręcznika - tylko wzmianka, która scpwykorzystuje się sshdo przesyłania danych. Powoduje to, że jeśli .bashrczawiera 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 scpi sftpnie
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
ttydołą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/ sftpa 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, scpw 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 scppo prostu pozostaje w pętli, zablokowany read(2). W międzyczasie, po przetworzeniu profilu powłoki po stronie zdalnej, scpuruchomiono 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 .bashrcjest użyteczna tylko dla interaktywnej powłoki - nie podczas uruchamiania poleceń zdalnych za pomocą rshlub 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 scplub sftp. Wyjście po sprawdzeniu, że bieżąca powłoka jest nieinteraktywna, jest najbezpieczniejszym zachowaniem .bashrc.