`ssh <host>` jest powłoką logowania, ale `ssh <host> <polecenie>` nie jest?

12

Zauważyłem, że kiedy uruchamiam polecenie bezpośrednio na hoście SSH przy użyciu ssh <host> <command>składni, widzę dane wyjściowe ( .bashrcale) danych wyjściowych .bash_profile(lub .profile).

Na przykład, jeśli umieszczę następujące polecenie u góry obu plików,

echo ${BASH_SOURCE[0]}

i ręcznie źródła .bash_profile(które źródła .bashrcz kolei), zobaczę

$ . .bash_profile
.bash_profile
.bashrc

To jest to samo wyjście, które widzę, jeśli loguję się do tego komputera zdalnie przez SSH, używając ssh <host>formularza polecenia. (A jeśli .bash_profiletymczasowo schuję gdzie indziej, żadna z tych linii nie zostanie wyświetlona).

Jeśli jednak wykonam polecenie bezpośrednio na zdalnym komputerze w ssh <host> <command>formie ssh, wówczas dane wyjściowe wyglądają następująco:

$ ssh <host> echo foo
/home/rlue/.bashrc
foo

Rozumiem, że różnica między .bash_profilei .bashrcpolega na tym, że ta pierwsza służy do powłok logowania, a druga do interaktywnych powłok bez logowania .

Doszedłem do następujących wniosków:

  1. ssh <host>tylko źródła .bash_profile, podczas gdy
  2. ssh <host> <command>tylko źródła .bashrc, co oznacza
  3. ten pierwszy jest powłoką logowania, a drugi nie.

Czy te wnioski są prawidłowe? Dlaczego jest ssh <host> <command>traktowany jako interaktywna powłoka bez logowania? Czy SSH nadal nie loguje się na zdalnym komputerze, aby wykonać polecenie?

Ryan Lue
źródło
wyjście .bashrc? Ten plik nie powinien generować żadnych danych wyjściowych. Każde wyjście .bashrcmoże zepsuć wszystkie narzędzia, używając ssh jako ich transportu.
kasperd
Słusznie. W tym przypadku kilka linii .bashrcwprowadzało błąd, podczas gdy podobne linie .bash_profilenie. Skorzystałem z okazji, aby zbadać rozbieżność przed ustaleniem linii obrażających.
Ryan Lue,

Odpowiedzi:

12

OpenSSH (najprawdopodobniej to, co uruchamiasz) decyduje, czy utworzyć powłokę logowania, i robi to tylko wtedy, gdy nie uruchamiasz określonej komendy. Od man ssh:

 If command is specified, it is executed on the remote host instead of a
 login shell.

Jest to więc wybór implementacji dla serwera ssh, czy chce utworzyć powłokę logowania, czy nie, a jeśli wydasz polecenie uruchomienia, nie zrobi tego.

Chociaż sshwykonuje logowanie, jeśli wykonujesz polecenie i kończysz działanie, jest to o wiele bardziej podobne do tworzenia powłoki tylko po to, aby uruchomić to polecenie, niż do uzyskiwania środowiska logowania. Wydaje się, biorąc pod uwagę, że ludzie piszący OpenSSH postanowili potraktować to jako takie zadanie.

Tworzą nieinteraktywną powłokę niezalogowaną do wykonania polecenia, ponieważ taki jest duch uruchamiania polecenia w innym kontekście / powłoce. Zwykle jednak nieinteraktywne powłoki nie byłyby automatycznie źródłem, ~/.bashrcco wyraźnie dzieje się tutaj. bashpróbuje nam pomóc tutaj. Z dokumentów

Wywoływany przez zdalnego demona 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, odczytuje i wykonuje polecenia z ~ / .bashrc, jeśli ten plik istnieje i można go odczytać. Nie zrobi tego, jeśli zostanie wywołany jako sh. Opcji --norc można użyć do zahamowania tego zachowania, a opcji --rcfile można użyć do wymuszenia odczytania innego pliku, ale ani rshd, ani sshd nie wywołują powłoki z tymi opcjami ani nie pozwalają na ich określenie.

Eric Renouf
źródło
„... jest wykonywany na zdalnym hoście zamiast powłoki logowania.” Nie dostaję tej dychotomii. Czy polecenie jest wykonywane na zdalnym hoście zamiast w powłoce logowania , czy też polecenie jest wykonywane na zdalnym hoście, zamiast tam wykonywanej powłoki logowania ? Jeśli to pierwsze, jak to jest / (czy nie jest to normalnie jedno i drugie? ) Jeśli to drugie, jest nadal wykonywane w kontekście jakiejś powłoki, prawda? (interaktywny, bez logowania?) Więc moje pytanie dotyczy także semantyki - co oznacza „powłoka logowania” i dlaczego OpenSSH miałby być zaprojektowany tak, aby nie tworzyć jednego dla pojedynczych poleceń?
Ryan Lue
@RyanLue Różne „smaki” powłok sprawiają, że niektóre zadania są łatwiejsze / bezpieczniejsze / zoptymalizowane itp. Wykonując polecenie sshnie wymaga logowania, implementatorzy najwyraźniej zdecydowali, że w pewnych okolicznościach, np. Prosząc go o wykonanie polecenia i zwrócenie nie potrzebują / nie korzystają z dodatkowych kroków wykonywanych przez powłokę logowania, więc pomijają to. Tak więc rzeczywiście istnieje powłoka, która jest uruchomiona, domyślam się, że głównie konfiguruje środowisko, a ponieważ powłoka nie zostanie udostępniona użytkownikowi, który się zalogował, traktują ją tak, jakby użytkownik właśnie uruchomił nową powłokę do uruchomienia tej powłoki polecenie
Eric Renouf
„Więc rzeczywiście jest uruchomiona powłoka, domyślam się, że głównie konfiguruję środowisko ...” <ale właśnie z tym eksperymentowałem i wydaje się, że ssh <host> <command>nie dziedziczy środowiska żadnej istniejącej powłoki logowania. Na przykład $ ssh <host> \$PATHzwraca ścieżkę taką, jaka byłaby bez pozyskiwania .bash_profile(lub .profileniejako) ... W sensie praktycznym, dlaczego chcesz ominąć ten krok?
Ryan Lue,
„... implementatorzy najwyraźniej zdecydowali, że w pewnych okolicznościach, np. Prosząc go o wykonanie polecenia i powrót, nie potrzebują / nie korzystają z dodatkowych kroków podejmowanych przez powłokę logowania, więc pomijają to”. <także, szczególnie szukając wyjaśnień / wglądu w tym wyborze projektu. I definiować moje PATHin .profile- nie jest to dokładnie ten rodzaj rzeczą, którą chciałby załadowany przed uruchomieniem dowolnego polecenia na zdalnym komputerze?
Ryan Lue,
1
@RyanLue Serwer ssh Boks rozróżnia różne zastosowania ssh i może udzielić uprawnień dla każdego z nich. Zdalne logowanie, zdalne wykonywanie, zdalne kopiowanie. Może to pomaga zrozumieć, dlaczego miałbyś opisywane zachowanie. Zdalne logowanie (użycie interaktywne) może być zbyt duże, aby wymagać w środowisku o wysokim poziomie bezpieczeństwa. Otwarcie może być ograniczone przez użycie rbash / rksh i 'logout' w .bash_profile lub chroot.
bbaassssiiee
4

Dlaczego takiego zachowania leży na niższym poziomie niż muszli: ssh host(the „login shell” case) wykorzystuje pseudoterminalu na zdalnym komputerze, do komunikowania się między sshdprocesu serwera i powłoki; zamiast tego ssh host commandużywa potoków pomiędzy sshdi command. Pseudoterminy są niezbędne do interaktywnego korzystania z interpretera poleceń, takiego jak powłoka lub tryb „ odczytu-odczytu-wydruku ” języka skryptowego; wprowadzają szereg przyjaznych dla człowieka funkcji, takich jak możliwość cofania się nad literówkami. Ale mają one większy narzut i (w zależności od konfiguracji) nie pozwalają na przechodzenie dowolnych danych przez niezmodyfikowane, więc SSH unika ich używania, gdy interakcja nie będzie miała miejsca.

Czasami heurystyczna komenda SSH / brak komendy źle to rozumie; można go zastąpić przełącznikami -ti -T. Na przykład, aby zalogować się do zdalnego komputera i natychmiast ponownie dołączyć zawieszoną screensesję, musisz to zrobić ssh -t host screen -R; ssh host screen -Rspowoduje screennarzekanie na brak połączenia z terminalem. Nie mogę sobie wyobrazić sytuacji, w której naprawdę chciałbyś skorzystać -T, ale ma miejsce, jeśli kiedykolwiek ją znajdziesz.

zwol
źródło
1

Najpierw musisz zobaczyć różne typy, możesz przeczytać to:

/unix/170493/login-non-login-and-interactive-non-interactive-shells

Teraz, jeśli otworzysz bashrc, zobaczysz na początku:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

Oznacza to, że w zależności od tego, w jaki sposób uzyskujesz dostęp do systemu, ten plik ładuje kod wewnątrz, czy nie.

Genaro Morales
źródło
Okej, ale rodzi to interesujące pytanie: .bashrcmoże być napisane tak, aby nie być pozyskiwane, jeśli jest wywoływane w kontekście nieinteraktywnym ( tj. Jeśli nie ma „instrukcji szybkiej” / $PS1zmiennej). Ale ssh <host> <command> jest zdecydowanie nieinteraktywny ; to znaczy, że ma nie podnosić wiersz polecenia. Dlaczego więc OpenSSH miałby być zaprojektowany do tworzenia interaktywnego monitu bez logowania (takiego, który próbuje uzyskać źródło .bashrc) dla tego pozornie nieinteraktywnego przypadku użycia?
Ryan Lue,