`ssh <Host>` ist eine Login-Shell, `ssh <Host> <Befehl>` jedoch nicht?


12

Ich habe festgestellt, dass beim Ausführen eines Befehls direkt auf einem SSH-Host mithilfe der ssh <host> <command>Syntax .bashrcdie Ausgabe von .bash_profile(oder .profile) angezeigt wird, jedoch nicht die Ausgabe von (oder ).

Wenn ich zum Beispiel den folgenden Befehl oben in beiden Dateien platziere,

echo ${BASH_SOURCE[0]}

und manuell Quelle .bash_profile(welche Quellen .bashrcwiederum), werde ich sehen

$ . .bash_profile
.bash_profile
.bashrc

Dies ist die gleiche Ausgabe, die ich sehe, wenn ich mich über SSH mit ssh <host>der Befehlsform remote bei diesem Computer anmelde . (Und wenn ich .bash_profilevorübergehend woanders verstaue , wird keine dieser Zeilen wiedergegeben.)

Wenn ich jedoch einen Befehl mit der ssh <host> <command>Form von direkt auf dem Remotecomputer ausführe ssh, sieht die Ausgabe folgendermaßen aus:

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

Mein Verständnis ist, dass der Unterschied zwischen .bash_profileund darin .bashrcbesteht, dass Ersteres für Login-Shells gilt, während Letzteres für interaktive Nicht-Login-Shells gilt .

Ich habe folgendes festgestellt:

  1. ssh <host>Quellen nur .bash_profile, während
  2. ssh <host> <command>nur Quellen .bashrc, was bedeutet
  3. Ersteres ist eine Login-Shell und Letzteres nicht.

Sind diese Schlussfolgerungen richtig? Warum wird ssh <host> <command>es als interaktive Shell ohne Anmeldung behandelt? Meldet sich SSH nicht immer noch auf dem Remotecomputer an, um den Befehl auszuführen?


Ausgang .bashrc? Diese Datei soll keine Ausgabe erzeugen. Jede Ausgabe von .bashrckann alle Tools beschädigen, die ssh als Transport verwenden.
Kasperd

Fair genug. In diesem Fall .bashrcwarfen einige Zeilen einen Fehler aus, ähnliche Zeilen .bash_profilejedoch nicht. Ich nutzte die Gelegenheit, um die Diskrepanz zu untersuchen, bevor ich die störenden Linien reparierte.
Ryan Lue

Antworten:


12

OpenSSH (höchstwahrscheinlich das, was Sie ausführen) entscheidet, ob eine Anmeldeshell erstellt werden soll oder nicht, und dies nur, wenn Sie keinen bestimmten Befehl ausführen. Von man ssh:

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

Es ist also eine Implementierungsoption für den SSH-Server, ob er eine Anmeldeshell erstellen möchte oder nicht, und wenn Sie einen Befehl zum Ausführen geben, ist dies nicht der Fall.

Während Sie ssheine Anmeldung durchführen, ist es viel ähnlicher, eine Shell zu erstellen, um diesen Befehl auszuführen, als eine Anmeldeumgebung abzurufen, wenn Sie einen Befehl ausführen und beenden. Angesichts dessen scheint es, dass die Leute, die OpenSSH schreiben, beschlossen haben, es wie eine solche Aufgabe zu behandeln.

Sie erstellen eine nicht interaktive Shell ohne Anmeldung, um den Befehl auszuführen, da dies der Geist ist, einen Befehl in einem anderen Kontext / einer anderen Shell auszuführen. Normalerweise werden nicht interaktive Shells jedoch nicht automatisch als Quelle verwendet, ~/.bashrcwas hier eindeutig geschieht. bashversucht tatsächlich, uns hier draußen zu helfen. Aus den Dokumenten

Wird vom Remote-Shell-Daemon aufgerufen

Bash versucht festzustellen, wann es ausgeführt wird, wenn seine Standardeingabe mit einer Netzwerkverbindung verbunden ist, wie dies vom Remote-Shell-Daemon (normalerweise rshd) oder vom Secure-Shell-Daemon sshd ausgeführt wird. Wenn Bash feststellt, dass es auf diese Weise ausgeführt wird, liest es Befehle von ~ / .bashrc und führt sie aus, sofern diese Datei vorhanden und lesbar ist. Dies wird nicht ausgeführt, wenn es als sh aufgerufen wird. Die Option --norc kann verwendet werden, um dieses Verhalten zu verhindern, und die Option --rcfile kann verwendet werden, um das Lesen einer anderen Datei zu erzwingen, aber weder rshd noch sshd rufen im Allgemeinen die Shell mit diesen Optionen auf oder erlauben deren Angabe.


"... es wird auf dem Remote-Host anstelle einer Login-Shell ausgeführt." Ich verstehe diese Zweiteilung nicht. Wird der Befehl auf dem Remote-Host anstatt in einer Login-Shell ausgeführt oder wird der Befehl auf dem Remote-Host ausgeführt, anstatt dass dort eine Login-Shell ausgeführt wird? Wenn erstere, wie ist es entweder / oder? (ist es nicht normal beides? ) Wenn letzteres, es noch im Rahmen der ausgeführt wird einige Schale, ist es nicht? (eine interaktive, nicht angemeldete?) Meine Frage bezieht sich also auch auf die Semantik - was bedeutet "Anmeldeshell" und warum sollte OpenSSH so konzipiert sein, dass keine für einzelne Befehle erstellt wird?
Ryan Lue

@RyanLue Die unterschiedlichen "Geschmacksrichtungen" von Shells machen bestimmte Aufgaben einfacher / sicherer / optimierter usw. Während ssheine Anmeldung erforderlich ist, haben die Implementierer anscheinend entschieden, dass unter bestimmten Umständen, z. B. wenn sie aufgefordert werden, einen Befehl auszuführen und zurückzukehren, dies getan wird Sie brauchen / profitieren nicht von den zusätzlichen Schritten, die eine Login-Shell ausführt, und überspringen diese. Es gibt also tatsächlich eine Shell, die ausgeführt wird. Ich gehe davon aus, dass die Umgebung hauptsächlich eingerichtet wird. Da die Shell dem angemeldeten Benutzer nicht zur Verfügung gestellt wird, wird sie so behandelt, als hätte der Benutzer gerade eine neue Shell gestartet, um diese auszuführen Befehl
Eric Renouf

"Es gibt also tatsächlich eine Shell, die ausgeführt wird. Ich gehe hauptsächlich davon aus, dass die Umgebung eingerichtet wird ..." <, aber ich habe gerade damit experimentiert, und es scheint, dass ssh <host> <command>die Umgebung keiner vorhandenen Anmeldeshell geerbt wird. Gibt beispielsweise $ ssh <host> \$PATHden Pfad so zurück, wie er ohne Sourcing .bash_profile(oder sozusagen .profile) wäre ... Warum sollten Sie diesen Schritt praktisch umgehen?
Ryan Lue

"... die Implementierer haben anscheinend entschieden, dass sie unter bestimmten Umständen, z. B. wenn sie aufgefordert werden, einen Befehl auszuführen und zurückzukehren, die zusätzlichen Schritte, die eine Anmeldeshell unternimmt, nicht benötigen / davon profitieren, und überspringen dies daher." <auch speziell auf der Suche nach Klarstellung / Einsicht in diese Designwahl. Ich definiere mein PATHIn .profile- ist das nicht genau das, was Sie laden möchten, bevor Sie einen beliebigen Befehl auf einem Remote-Host ausführen?
Ryan Lue

1
@RyanLue Der Boks-SSH-Server unterscheidet verschiedene Verwendungszwecke von SSH und kann für jeden Berechtigungen erteilen. Remote-Anmeldung, Remote-Ausführung, Remote-Kopie. Vielleicht hilft dies zu verstehen, warum Sie das von Ihnen beschriebene Verhalten haben würden. In einer Hochsicherheitsumgebung ist die Remote-Anmeldung (interaktive Verwendung) möglicherweise zu viel verlangt. Openssh kann durch Verwendung von rbash / rksh und 'logout' in .bash_profile oder chroot eingeschränkt werden.
bbaassssiiee

4

Das Warum dieses Verhaltens liegt auf einer niedrigeren Ebene als bei Shells: ssh host(der Fall "Login-Shell") verwendet ein Pseudoterminal auf dem Remote-Host, um zwischen dem sshdServerprozess und der Shell zu kommunizieren . ssh host commandverwendet stattdessen Pipes zwischen sshdund command. Pseudoterminals sind erforderlich, um einen Befehlsinterpreter wie eine Shell oder den " Read-Eval-Print " -Modus einer Skriptsprache interaktiv zu verwenden . Sie implementieren eine Reihe von benutzerfreundlichen Funktionen, z. B. die Möglichkeit, Tippfehler rückgängig zu machen. Sie haben jedoch einen höheren Overhead und lassen (abhängig von der Konfiguration) nicht zu, dass beliebige Daten unverändert übertragen werden. Daher vermeidet SSH die Verwendung dieser Daten, wenn keine Interaktion stattfinden soll.

Manchmal macht SSHs Befehl / keine Befehlsheuristik dies falsch; Es kann mit den Schaltern -tund überschrieben -Twerden. Um sich beispielsweise bei einem Remotecomputer anzumelden und eine angehaltene screenSitzung sofort wieder anzuschließen, müssen Sie Folgendes tun ssh -t host screen -R: ssh host screen -Rwird dazu führen screen, dass Sie sich beschweren, nicht an ein Terminal angeschlossen zu sein. Ich kann eine Situation nicht denken , wenn Sie tatsächlich würden wollen verwenden -T, aber es ist da , wenn Sie jemals ein finden.


1

Zuerst müssen Sie die verschiedenen Typen sehen, Sie können dies lesen:

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

Wenn Sie nun Ihren Bashrc öffnen, sehen Sie am Anfang Folgendes:

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

Das bedeutet, dass diese Datei je nachdem, wie Sie auf das System zugreifen, den Code darin lädt oder nicht.


Okay, aber dies wirft eine interessante Frage auf: .bashrcKann so geschrieben werden, dass sie nicht bezogen wird, wenn sie in einem nicht interaktiven Kontext aufgerufen wird ( dh wenn es keine „Eingabeaufforderung“ / $PS1Variable gibt). Ist ssh <host> <command> aber entschieden nicht interaktiv ; Das heißt, es wird keine Eingabeaufforderung ausgelöst. Warum sollte OpenSSH so konzipiert sein, dass .bashrcfür diesen scheinbar nicht angemeldeten, nicht interaktiven Anwendungsfall eine interaktive Eingabeaufforderung ohne Anmeldung (eine, die versucht, eine Quelle zu finden ) erstellt wird?
Ryan Lue
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.