Wie kann ich eine Umgebungsvariable auf dem Server festlegen, die sich von Sitzung zu Sitzung ändert?

92

sshWie kann ich auf einem Server eine Umgebungsvariable vom Client an den Server übergeben? Diese Umgebungsvariable ändert sich zwischen verschiedenen Aufrufen von ssh, sodass ich nicht $HOME/.ssh2/environmentjedes Mal, wenn ich einen ssh-Aufruf mache, überschreiben möchte . Wie kann ich das machen?

Ross Rogers
quelle
2
Ihre Frage muss etwas genauer sein.
Ignacio Vazquez-Abrams
3
Die Frage war mir klar genug. Auf der sshManpage sehe ich jedoch keine andere Möglichkeit, als die Variable manuell festzulegen, nachdem Sie sich beim Server angemeldet haben, es sei denn, Sie ändern ~ / .ssh2 / environment.
Garyjohn
Ist es jedes Mal eine andere Variable? Oder einen anderen Wert?
Dennis Williamson
1
Umgekehrt, da dies schon beliebter ist. Es ist egal, es ist älter.
Kenorb

Antworten:

110

Natürlich können Sie die Umgebungsvariable innerhalb des Befehls festlegen, aber Sie müssen vorsichtig sein, wenn Sie Anführungszeichen setzen: Denken Sie daran, dass Ihre Shell Ihre lokale Befehlszeile parsen wird, und dann wird die Remote-Shell die Zeichenfolge durchgehen erhält.

Wenn Sie möchten, dass eine Variable auf dem Server denselben Wert erhält wie auf dem Client, probieren Sie die folgende SendEnvOption aus:

ssh -o SendEnv = MYVAR server.example.com mycommand

Dies erfordert jedoch Unterstützung vom Server. Bei OpenSSH muss der Variablenname in autorisiert werden /etc/sshd_config.

Wenn der Server nur bestimmte Variablennamen zulässt, können Sie das umgehen. Ein allgemeines Setup ermöglicht beispielsweise LC_*Folgendes:

ssh -o SendEnv = LC_MYVAR server.example.com 'MYVAR = $ LC_MYVAR; nicht gesetzt LC_MYVAR; Export MYVAR; mycommand '

Wenn gerade LC_*keine Option ist, können Sie Informationen in der TERMUmgebungsvariablen übergeben, die immer kopiert wird (es kann jedoch eine Längenbeschränkung geben). Sie müssen weiterhin sicherstellen, dass die Remote-Shell die TERMVariable nicht einschränkt , um einen bekannten Terminaltyp zu bestimmen. -tÜbergeben Sie die Option an ssh, wenn Sie keine interaktive Remote-Shell starten.

env TERM = "zusätzliche Informationen: $ TERM" ssh -t server.example.com 'MYVAR = $ {TERM%: *}; TERM = $ {TERM ## *:}; Export MYVAR; mycommand '

Eine andere Möglichkeit besteht darin, die Variable direkt im Befehl zu definieren:

ssh -t server.example.com 'export MYVAR = "zusätzliche Informationen"; mycommand '

Wenn Sie also eine lokale Variable übergeben, gilt Folgendes:

ssh -t server.example.com 'export MYVAR =' "'$ LOCALVAR'" '; mycommand '

Achten Sie jedoch auf Anführungszeichen: Der Wert der Variablen wird direkt in das Shell-Snippet interpoliert, das auf der Remote-Seite ausgeführt wird. Das letzte Beispiel oben geht davon aus, dass $LOCALVARkeine einfachen Anführungszeichen ( ') enthalten sind.

Gilles
quelle
2
Vielen Dank, ich war in der Wut, dass die dummen LC_ * -Variablen auf ssh exportiert werden und Ihre Antwort mich angewiesen hat, wo ich suchen soll. Ich muss das nur in ~ / .ssh / config
akostadinov
1
Ich bin in der Situation des ursprünglichen Posters, aber die Variable, die ich weiterleiten wollte, ist TERM, daher bin ich ein bisschen verwirrt über Ihre Antwort. Wurde diese automatische Weiterleitung von TERM in den letzten OpenSSH-Versionen deaktiviert?
Doub
1
@Doub Standardmäßig werden alle Umgebungsvariablen auf der Serverseite mit AcceptEnvAnweisungen abgelehnt, sshd_configwie vom Administrator gewünscht. Wird TERMaber speziell behandelt, soweit ich weiß, gibt es keine Möglichkeit, es auf der Serverseite zu filtern (es wird in der Umgebung der Shell festgelegt, unabhängig von Konfigurationseinstellungen). Sind Sie sicher, dass es kein Profilskript gibt, das es überschreibt (wie /etc/profileoder ~/.profileoder ~/.bashrc)?
Gilles
2
@ Gilles: Ich habe es erneut getestet und es sei denn, ich füge TERM explizit zu meiner AcceptEnv-Direktive hinzu, wird TERM nicht weitergegeben. Ich öffne keine Shell, sondern führe einen Befehl direkt aus, zum Beispiel: "ssh -o SendEnv = TERM shell.example.com env". Dadurch werden alle Umgebungsvariablen gedruckt, und TERM wird nur angezeigt, wenn SendEnv auf dem Client und AcceptEnv auf dem Server aktiviert sind. Wenn ich "ssh -o SendEnv = TERM shell.example.com echo \ $ {TERM}" ohne AcceptEnv oder SendEnv ausführe, wird "dumm" ausgegeben, wobei ich nicht sicher bin, woher es kommt (env nicht einmal) Liste TERM in diesem Fall).
Doub
7
@ Doub Oh, ich verstehe. TERMwird nur übertragen, wenn der Client den Server auffordert, ein tty zuzuweisen. Wenn es auf der Gegenseite kein Terminal gibt, wäre das Senden nutzlos TERM. Wenn Sie einen Befehl angeben und ein Terminal auf der Remote-Seite haben möchten, benötigen Sie die -tBefehlszeilenoption (oder RequestTTYin ~/.ssh/config).
Gilles
12

Wenn Sie den Zielhost verwalten können, können Sie sshd so konfigurieren, dass Ihre lokalen Umgebungsvariablen an den Zielhost weitergeleitet werden.

Aus der Manpage sshd_config:

 PermitUserEnvironment
     Specifies whether ~/.ssh/environment and environment= options in
     ~/.ssh/authorized_keys are processed by sshd.  The default is
     "no".  Enabling environment processing may enable users to bypass
     access restrictions in some configurations using mechanisms such
     as LD_PRELOAD.

SSHD-Konfiguration lebt in der Regel bei /etc/ssh/sshd_config

Duncan Beevers
quelle
7
Es ist sehr nützlich zu wissen, dass dies standardmäßig auf "nein" gesetzt ist!
jathanism
6

Sie haben also auf Ihrem Client eine Umgebungsvariable und möchten, dass diese für den Remote-Befehl verfügbar ist? Ich glaube nicht, dass es eine Möglichkeit gibt, ssh magisch weiterzugeben, aber Sie können wahrscheinlich so etwas tun. Anstatt zu verwenden, sagen Sie:

ssh remote.host my_command

Du kannst das:

ssh remote.host env ENV_VAR=$ENV_VAR my_command
Pioto
quelle
"wahrscheinlich"? Ich wünschte, ich würde das lesen, bevor ich diese Antwort probiere. Hat bei mir nicht funktioniert.
Tishma
1
Möchten Sie etwaige Fehler usw. näher erläutern?
Pioto
1
@pioto Könnte zitiert werden, zB wenn ENV_VAR Leerzeichen enthält
Martin C. Martin
Auf dem Mac muss die Option -t für eine interaktive Version vorhanden sein, sonst sieht es nicht aus. Das könnte also funktionieren: $ ssh -t remote.host env ENV_VAR = $ ENV_VAR my_command
muenalan
3

Die Antwort von @ emptyset (die bei mir nicht funktioniert hat) führte mich zu dieser Antwort:

Sie können diesen Befehl zu Ihrer ~/.ssh/authorized_keysDatei hinzufügen :

command="/usr/bin/env VARIABLE=<something> $SHELL" ssh-rsa <key>

export VARIABLE=<something>wurde sofort beendet und die SSH-Verbindung wurde geschlossen (wodurch ich vom Server ausgeschlossen wurde), während /usr/bin/env ... $SHELLIhre Standard-Shell mit einer geänderten Umgebung ausgeführt wird.

madprog
quelle
Dies hängt nur, wenn ich mich anmelde. Wenn ich es entferne, kehrt SSH zum Normalzustand zurück und ich erhalte meine gewohnte Login-Shell.
Nick Sweeting
@NickSweeting hast du versucht vielleicht durch $SHELLeine aktuelle Shell zu ersetzen ? Überprüfen Sie auch, ob / usr / bin / env auf dem Server vorhanden ist. Die Lösung ist jedoch nicht perfekt: Ich habe gemerkt, dass es hängt, wenn ich scpeinen Inline-Befehl verwenden wollte.
madprog
Ja, das war das erste, was ich versuchte. Leider hat es nie funktioniert, wurde aktiviert PermitUserEnvironment yesund environment="..."stattdessen verwendet command="...".
Nick Sweeting
Das funktioniert gut für mich.
Herr Tao
3

Auf Ihrem lokalen Client können Sie in Ihrem ~/.ssh/confighinzufügen SetEnv, z

Host myhost
  SetEnv FOO=bar

Hinweis: Überprüfen Sie man ssh_config.

Stellen Sie dann auf dem Server sicher, dass der Client bestimmte Umgebungsvariablen in Ihrer /etc/ssh/sshd_configKonfigurationsdatei übergeben kann:

AcceptEnv LANG LC_* FOO BAR*

Hinweis: Überprüfen Sie man sshd_config.

Kenorb
quelle
1

Sie könnten versuchen, einen benutzerdefinierten Befehl aufzurufen, vorausgesetzt, Sie haben ein passwortloses SSH-Anmelde-Setup. Bearbeiten Sie auf dem Server Ihren ~ / .ssh / authorized_keys-Eintrag, der dem Schlüssel Ihres Clients entspricht:

command="export VARIABLE=<something>" ssh-rsa <key>

Schauen Sie sich diesen Link im Abschnitt Erzwungener Befehl für ein wenig mehr Details an.

leeres Set
quelle
1
Ich habe es versucht, aber es funktioniert nicht. Der Befehl wird ausgeführt und beendet, sodass keine interaktive Sitzung stattfindet. Ist das das normale Verhalten? In diesem Fall kann dies hilfreich sein, wenn Sie lediglich zulassen möchten, dass eine bestimmte Taste einen bestimmten Befehl auslöst. Wenn Sie jedoch Informationen übergeben möchten, die in einer Sitzung verwendet werden (wie in der Frage angegeben), ist dies für diesen Zweck nicht sinnvoll . Es findet keine Sitzung statt.
Bilderstürmer
1

Ich habe einen benutzerdefinierten Build von OpenSSH für ein Gerät mit Cramfs im Ausgangsverzeichnis und / etc (Cram FS ist schreibgeschützt) erstellt, sodass ~ / .ssh / environment nicht funktionieren würde, ohne den gesamten FS neu zu erstellen, und diese wurden vor Ort bereitgestellt Geräte (Embedded Systems Daher die Verwendung von CRAMFS). Sie können in sshd_config den Speicherort der Datei authroized_keys angeben, aber aus irgendeinem Grund funktioniert environment = nur für Umgebungsvariablen in ~ / .ssh / authroized_keys. Das Bearbeiten der Datei / etc / profile war keine Option und ich musste ssh in ein nicht standardmäßiges Verzeichnis laden. Fügen Sie in session.c nach child_set_env (... "MAIL" ...) einfach die Umgebungsvariablen hinzu, die Sie benötigen (dies ist ein Hack, den ich kenne ...) Kompilieren aus dem Quellcode können Sie dies tun. TGI-FLOSS

Wille
quelle
0

nur ein einfacher Befehl:

ssh -t your_host_or_ip 'export some_var_name=whatever_you_want; bash'
Grepit
quelle