Ist es möglich, ein HEREDOC über ssh aus einem lokal ausgeführten Skript an einen Remote-Host zu senden?

8

Ich möchte im Wesentlichen ein Skript auf Maschine A ausführen, das SSH in Maschine B ausführt, Befehle auf B ausführt und die Ausgabe an Maschine A zurückgibt.

Also erstelle ich ein csh-Skript, um dies zu tun, hoffentlich, wenn es möglich ist.

Diese Lösung aus dieser Antwort funktioniert beispielsweise über die Befehlszeile:

ssh user@host << 'ENDSSH'
ls -l
ENDSSH

Ich kann überprüfen, ob das ls auf der Fernbedienung und nicht lokal ausgeführt wird.

Ich möchte dies jedoch innerhalb der Backticks in meinem lokal ausgeführten csh-Skript tun können. Wird das möglich sein?

Ich weiß, dass es möglich ist, SSH in ein Skript auf der Fernbedienung einzubinden und auszuführen, aber das ist nicht mein Fall.

Ich habe auch gehört, dass es möglich ist, ein zweites lokal über SSH gespeichertes Skript zu senden (was ich auch nicht herausgefunden habe), aber ich mag die Idee, alle Befehle im ursprünglichen Skript zu haben, daher das HEREDOC.

Ich weiß, dass es eine ziemlich spezielle Frage ist, aber wenn es einen Weg gibt, wäre es sehr cool zu wissen, wie.

Dinge, die nicht funktionieren

1)

`ssh user@host<<'ENDSSH'`
`echo "ls -l"`
`echo "ENDSSH"`

Dies gibt den Fehler:

stty: standard input: Invalid argument. stty: standard input: Invalid argument. Warning: Command not found

Und dann wird es ls -llokal ausgeführt, und dann hat es versucht, ENDSSHlokal ausgeführt zu werden, und schlägt natürlich fehl, wenn der Befehl nicht gefunden wurde.

2)

`ssh user@host<<'ENDSSH'`
echo "ls -l"
echo "ENDSSH"

Das gleiche Problem wie oben, außer es wird nur angezeigt , ls -lund ENDSSHals Text. Sinnvoll ... da der HEREDOC-Teil fehlgeschlagen ist.

3) 3-5 sind nicht genau das, wonach ich gefragt habe, aber ich versuche immer noch, auch nur den Grundfall zum Laufen zu bringen.

`ssh user@host ls-l` 

Das kehrt zurück total: Command not found. Ja, ich habe keine Ahnung, woher das kommt.

4)

`cat ./test.csh | ssh user@host`

Gibt auch das gleiche wie Versuch 1 zurück

5)

`cat ./test.csh | ssh -t user@host`

Gleich wie Nr. 1 und 4.

Ich fange an, andere Lösungen von Stackoverflow / Ubuntu / Serverfault ... usw. Zu erschöpfen. Die meisten Leute fragen, wie ihr Skript auf einer Fernbedienung über die Befehlszeile ausgeführt werden soll, nicht wie Befehle auf einer Fernbedienung über ein lokal ausgeführtes Skript ausgeführt werden sollen.

Bearbeiten

Nun, ich glaube, ich habe einen Teil des Problems herausgefunden. In Fall 3 von oben wird beispielsweise ls -llokal ausgeführt, und der erste Teil der Ausgabe wird dann als Befehl über SSH gesendet.

Ich habe das bemerkt, weil ich es versucht habe ssh user@host $CMD, mit $CMDeingestellt auf "whoami". Die Ausgabe war username: Command not found, und dann wurde mir klar, dass die totalAusgabe von ls stammt. Ich bin mir jedoch immer noch nicht sicher, wie ich das lösen soll

krb686
quelle
Hast du es versucht ? Ich benutze meistens scp && ssh, um Probleme mit der Konnektivität oder dem Passwort / ssh-Schlüssel zu überprüfen. Ihre Lösung sieht jedoch in Ordnung aus.
Archemar
@Archemar Siehe den letzten Abschnitt, den ich hinzugefügt habe.
krb686
Bezüglich Ihres Edit-Kommentars ist das nicht wirklich richtig. Sie haben Fall 3 als `` `ssh user @ host ls -l`` `. Dies wird ausgeführt ssh user@host ls -l, was wiederum ls -lauf dem Remote-Host ausgeführt wird. Die resultierende Ausgabe wird von den Backticks erfasst und lokal ausgewertet. Da diese Ausgabe nicht erfasst werden kann, wird sie als lokaler Befehl ausgeführt.
Roaima
@roaima Okay, also hatte ich es umgeschaltet, damit es ls -lremote ausgeführt wird und die Ausgabe lokal im Gegensatz zu ls -llokal und die Ausgabe remote?
krb686
Ja, das ist richtig.
Roaima

Antworten:

4

Wenn Sie den gesamten Befehl, den Sie ausführen möchten, in Backticks einschließen, erhalten Sie wahrscheinlich die richtige Lösung. Es gibt Probleme bei der Bewertung von Variablen und anderen interpolierten Elementen, aber ich werde diese für einen Moment beiseite legen.

Ich bin mir jedoch nicht ganz sicher, warum Sie etwas in Backticks wollen. Ihre Frage besagt, dass Sie ein lokales Skript remote ausführen möchten. Ihr erstes Beispiel macht das.

ssh -q user@host << ENDSSH
hostname
ls -l
id
ENDSSH

Vielleicht möchten Sie die Ausgabe der Remote-Ausführung in eine Variable umwandeln? Das steht nirgendwo in der Frage, aber du würdest es so machen ( bash)

RESULT=$(ssh user@host <<ENDSSH
hostname
id
ENDSSH
)
...
echo "$RESULT"

Oder csh, wie Sie bereits erwähnt haben , so

set result = `ssh -q user@host` <<ENDSSH
hostname
id
ENDSSH
...
echo "$result"

Beachten Sie, dass für die cshVariante alle Ausgangsleitungen miteinander verkettet sind.

Ich sehe, dass Sie einen Fehler gemeldet haben. stty: standard input: Invalid argument.Dies tritt wahrscheinlich auf, weil Sie einen sttyBefehl in Ihrem Anmeldeskript auf dem Remote-Server haben. Dies sollte in einen Test für eine interaktive Shell eingeschlossen werden. In bashwürden Sie so etwas tun:

if test -n "$PS1"
then
    # Interactive setup here
    stty ...
fi
Roaima
quelle
1
Ja, Sie haben Recht. Ich möchte eventuell die Ergebnisse der Befehle, die auf der Remote ausgeführt werden, innerhalb der Variablen im lokal ausgeführten Skript speichern. Ihre cshLösung funktioniert leider nicht. Dies führt immer noch zu Fehlern : stty: standard input: Invalid argument. Ich habe meiner Frage am Ende eine Bearbeitung mit einigen interessanten Informationen hinzugefügt. Ich bin mir nicht sicher, ob Sie das schon gesehen haben, aber es gibt einen Hinweis.
krb686
1
@ krb686 Bitte beachten Sie das Update für stty. Wenn Sie die Option haben, würde ich Ihnen dringend empfehlen, das Schreiben von cshSkripten zu beenden und stattdessen sh/ zu bashverwenden. Es gibt eine Reihe bedeutender Probleme bei der Verwendung cshals Skriptsprache, so dass es wirklich von Vorteil ist, sh/ zu lernen bash, selbst wenn Sie die cshinteraktive Verwendung bevorzugen .
Roaima
Ah, das habe ich nicht gesehen. Ich werde das gleich überprüfen. Danke
krb686
2

Ich bin mir nicht sicher, was du versuchst zu tun, aber hier ist etwas, das für mich funktioniert hat.

(Wenn Sie Probleme haben, verhindern Sie, dass der Stackexchange-Texteditor die hinteren Häkchen als Formatierungszeichen behandelt, und verwenden Sie die vorderen, wenn ich die hinteren Häkchen meine.)

R='ssh -t hostname <<EOF
ls -l
EOF'

Beachten Sie, dass ich den Backtick erst nach EOF schließe und die Option -t verwende, um ein virtuelles TTY zu erstellen, obwohl stdio umgeleitet wird.

Cosmo F.
quelle
1
Hmm, die Eingabe in den Heredoc muss also innerhalb des Backticks liegen. Wie trenne ich diese Befehle im Heredoc in getrennten Zeilen des csh-Skripts? Dies beschwert sich nur über das Fehlen eines Backticks, da der Backtick in der ersten Zeile vor ssh gestartet und nach EOF beendet wird
krb686
Okay, Sie brauchen ein "\"am Ende jeder Zeile, um den Heredoc fortzusetzen. Interessant, das funktioniert fast. Es beschwert sich mit : ls: cannot access EOF: No such file or directory. Es glaubt, dass dies EOFein Argument für jeden Befehl ist, der davor steht. Auch versucht dies mit whoamiund es heißtwhoami: extra operand EOF
krb686
@roaima Danke, ich habe das an mehreren Stellen gehört. Wenn Sie eine gute Referenz haben, würde ich sie gerne lesen! Ich habe Bash gelernt (und bevorzuge es), aber ich bin möglicherweise gezwungen, es cshfür bestimmte Dinge zu verwenden. Ich bin mir jedoch nicht ganz sicher, und wenn es einen Weg gibt, dies erfolgreich zu tun bash, würde ich diese Informationen definitiv auch mögen, wenn jemand sie hat
krb686
@ krb686 Kommentare können nicht verschoben werden. Löschen Sie es einfach und veröffentlichen Sie es erneut an der richtigen Stelle.
Terdon