Variable in ssh übergeben

7

Ich versuche, eine Variable an ssh remote zu übergeben, funktioniert aber nicht. Mein Code lautet:

#!/bin/bash
set -x
conexion="[email protected]"
parameter="$1"
ssh -T $conexion <<'ENDSSH' 
clear
echo "$parameter"
ENDSSH

Ich führe aus:

./script.sh try

Es sagt mir:

parameter: Undefined variable.

Hilfe bitte?

user650034
quelle
4
Versuchen Sie es mit ENDSSH ohne Anführungszeichen.
Archemar
1
@ user650034 Wenn dies Ihr Problem gelöst hat, markieren Sie bitte eine Antwort als genehmigt.
ddnomad

Antworten:

8

Das Übergeben von Variablen (Umgebungsvariablen) sshist möglich, aber im Allgemeinen eingeschränkt.

Sie müssen den Client anweisen, sie zu senden. Zum Beispiel mit OpenSSH, das ist mit:

ssh -o SendEnv=parameter host cmd...

Sie benötigen aber auch den Server, der dies akzeptiert ( AcceptEnvKonfigurationsanweisung mit OpenSSH). Das Akzeptieren einer Variablen stellt ein großes Sicherheitsrisiko dar und wird daher im Allgemeinen nicht standardmäßig durchgeführt, obwohl einige SSH-Bereitstellungen einige Variablen unter einem bestimmten Namespace zulassen (wie LC_*in einigen OpenSSH-Bereitstellungen).

Sie müssen die Variable auch exportieren, bevor Sie sie aufrufen ssh, z.

LC_parameter="$parameter" ssh -o SendEnv=LC_parameter host csh << 'END'
echo $LC_parameter:q
END

Oben übergeben wir den Inhalt der $parameter bashShell-Variablen als LC_parameterUmgebungsvariable an ssh. sshsendet das an sshd, das es, wenn es akzeptiert, als Umgebungsvariable an die Anmeldeshell des Benutzers übergibt, die es dann an diesen cshBefehl weitergibt (der es dann erweitern kann).

Wie bereits erwähnt, funktioniert dies nur, wenn der Administrator des hostComputers der Konfiguration ein AcceptEnv LC_parameteroder AcceptEnv LC_*(das manchmal standardmäßig erfolgt) hinzugefügt hat sshd.

Die Undefined variableFehlermeldung in Ihrem Beispiel weist darauf hin, dass die Anmeldeshell des Remotebenutzers cshoder ist tcsh. Es ist besser, die Shell explizit aufzurufen, um Überraschungen zu vermeiden ( ssh host cshbedeutet auch, dass kein tty angefordert wird, sodass Sie es nicht benötigen -T). Beachten Sie die $LC_parameter:qSyntax, mit der cshder Inhalt einer Variablen wörtlich übergeben wird, "$LC_parameter"die jedoch nicht funktioniert, wenn die Variable Zeilenumbrüche enthält.

Wenn die Verwendung von LC_*Variablen keine Option ist, können Sie alternativ die Client- Shell ( bashin Ihrem Fall) die Variable erweitern lassen. Ein naiver Weg wäre mit

ssh host csh << END
echo "$variable"
END

Dies wäre jedoch gefährlich, da der Inhalt der Variablen von der Remote-Shell interpretiert wird. Wenn $variableenthält `reboot`oder "; reboot; : "zum Beispiel, hätte das schlimme Konsequenzen.

Sie müssen also zuerst sicherstellen, dass die Variable in der Syntax der Remote-Shell korrekt in Anführungszeichen gesetzt ist. Hier würde ich vermeiden, cshwo es schwierig ist, zuverlässig zu arbeiten, und stattdessen sh/ bash/ kshverwenden.

Verwenden Sie eine Hilfsfunktion, um das sh-Zitat auszuführen:

shquote() {
  awk -v q=\' -v b='\\' '
    BEGIN{
      for (i=1; i<ARGC; i++) {
        gsub(q, q b q q, ARGV[i])
       printf "%s ", q ARGV[i] q
      }
      print ""
      exit
    }' "$@"
}

Und rufen Sie an sshals:

ssh host sh << END
parameter=$(shquote "$parameter")
echo "\$parameter"
END

Sehen Sie, wie wir dem dritten entkommen, $sodass die Erweiterung $parametervon der Remote-Shell und nicht von der lokalen Shell erfolgt.

Stéphane Chazelas
quelle
Es müssen keine Umgebungsvariablen sein, Variablen können erweitert und als Text übergeben werden. Dies scheint die Absicht zu sein und wird in der Antwort von @ ddnomad getan.
Strg-Alt-Delor
Gute Erklärung und Verwendung SendEnvund AcceptEnvwie mit dieser richtig geht eine Variable anstatt einen Wert . Genau darum wurde gebeten.
Kusalananda
@richard, aber wie gesagt, dieser naive Ansatz ist unzuverlässig und gefährlich. Meine Antwort gibt auch Details darüber, wie man diese Erweiterung zuverlässig / sicher macht
Stéphane Chazelas
@Kusalananda, ein Systemanalytiker darf nicht „streng genommen“ beantworten, was der Kunde war, er muss herausfinden, was er will, oft mit einer Reihe von Fragen. Ich war in vielen Situationen, in denen ein Kunde nach etwas fragte, indem er Wörter im Bereich des Programmierers / Softwareentwicklers / Analysten verwendete, ohne eine Ahnung zu haben, was die Wörter wirklich bedeuten, und die Mitglieder meines Teams werden diese Wörter zum Nennwert nehmen und liefern ihnen etwas, das nicht schwingt.
Strg-Alt-Delor
3

Unter anderen Tricks (wie dem Übergeben von LC_*Umgebungsvariablen) können Sie Folgendes tun:

PARAMETER="123"
ssh user@host PARAMETER="$PARAMETER" bash -s <<- __EOF
    echo \$PARAMETER
__EOF

Der Vorteil des Ansatzes besteht darin export PARAMETER, dass in der Konfiguration auf dem Remote-Host AcceptEnvkein Name hinzugefügt werden muss (falls die Namen nicht von beginnen LC_) /etc/ssh/sshd_configund SendEnvauf dem lokalen Host (zu -ooder zu /etc/ssh/ssh_config).

Tomilov Anatoliy
quelle
Dies hat das gleiche Problem mit der Code-Injektion wie die Antwort von ddnomad.
Brian McCutchon
2

Das Entfernen von Anführungszeichen aus ENDSSHder 4. Zeile sollte helfen.

Mit freundlicher Genehmigung von @Archemar in Kommentaren zur Frage.

WARNUNG Wie von @ StéphaneChazelas im Kommentar zu dieser Antwort angegeben, würde diese Lösung dazu führen, dass die $parameterVariable im hier gezeigten Dokument um die lokale Shell erweitert wird, was bedeutet, dass der Inhalt der Variablen von der Remote-Shell als Shell-Code interpretiert wird Dies bedeutet, dass eine Sicherheitsanfälligkeit bezüglich Befehlsinjektion eingeführt wird. Im Allgemeinen wird davon abgeraten.

ddnomad
quelle
2
Dies würde dazu führen, dass die $parameterVariable im Here-Dokument von der lokalen Shell erweitert wird. Dies bedeutet, dass der Inhalt der Variablen von der Remote-Shell als Shell-Code interpretiert wird. Dies bedeutet, dass beispielsweise eine Sicherheitsanfälligkeit bezüglich Befehlsinjektion eingeführt wird, wenn der Wert von $parameterist nicht ganz unter Ihrer Kontrolle und Sie haben es nicht bereinigt.
Stéphane Chazelas
@ StéphaneChazelas guter Punkt Ich würde eine Warnung zur Antwort hinzufügen
ddnomad