1436 Stimmen

Wie kann man SSH verwenden, um ein lokales Shell-Skript auf einem entfernten Rechner auszuführen?

Ich muss ein lokales Shell-Skript (Windows/Linux) auf einem entfernten Rechner ausführen.

Ich habe SSH sowohl auf Rechner A als auch auf Rechner B konfiguriert. Mein Skript befindet sich auf Rechner A, der einen Teil meines Codes auf einem entfernten Rechner, Rechner B, ausführen wird.

Die lokalen und entfernten Computer können entweder Windows- oder Unix-basierte Systeme sein.

Gibt es eine Möglichkeit, dies mit plink/ssh zu tun?

7 Stimmen

Die gleiche Frage wurde bereits auf serverfault gestellt: serverfault.com/questions/215756/ Es hat also wahrscheinlich keinen Sinn, diese Frage zu migrieren.

9 Stimmen

Auf die Frage zu Server Fault gibt es allerdings nicht so viele Antworten. Vielleicht sollte diese Frage diese ersetzen.

5 Stimmen

Mir persönlich gefällt diese Antwort: unix.stackexchange.com/questions/87405/

1374voto

Jason R. Coombs Punkte 38667

Wenn Rechner A ein Windows-Rechner ist, können Sie Plink (Teil von PuTTY ) mit dem Parameter -m, und es führt das lokale Skript auf dem entfernten Server aus.

plink root@MachineB -m local_script.sh

Wenn Maschine A ein Unix-basiertes System ist, können Sie verwenden:

ssh root@MachineB 'bash -s' < local_script.sh

Sie sollten das Skript nicht auf den Remote-Server kopieren müssen, um es auszuführen.

13 Stimmen

Gibt es einen Vorteil bei der Verwendung des -s Option? diese Manpage führt mich zu der Annahme, dass es die Standardeingabe verarbeitet, wenn es mit der Verarbeitung der Optionen fertig ist, egal ob -s verwendet wird oder nicht.

2 Stimmen

@asia1281 Es gibt keinen Vorteil; ich habe diese Technik gewählt, weil sie mir eindeutiger erschien. Es ist wahrscheinlich sicher, das '-s' wegzulassen.

89 Stimmen

Für ein Skript, das Folgendes erfordert sudo , laufen ssh root@MachineB 'echo "rootpass" | sudo -Sv && bash -s' < local_script.sh .

746voto

Yarek T Punkte 9395

Dies ist eine alte Frage, und die Antwort von Jason ist gut, aber ich möchte Folgendes hinzufügen:

ssh user@host <<'ENDSSH'
#commands to run on remote host
ENDSSH

Dies kann auch mit su und Befehlen verwendet werden, die eine Benutzereingabe erfordern. (Beachten Sie die ' entkommen heredoc)

Edit: Da diese Antwort immer wieder auftaucht, möchte ich noch mehr Informationen zu dieser wunderbaren Verwendung von heredoc hinzufügen:

Sie können Befehle mit dieser Syntax verschachteln, und das ist die einzige Möglichkeit, wie die Verschachtelung zu funktionieren scheint (auf eine vernünftige Art und Weise)

ssh user@host <<'ENDSSH'
#commands to run on remote host
ssh user@host2 <<'END2'
# Another bunch of commands on another host
wall <<'ENDWALL'
Error: Out of cheese
ENDWALL
ftp ftp.secureftp-test.com <<'ENDFTP'
test
test
ls
ENDFTP
END2
ENDSSH

Mit einigen Diensten wie telnet, ftp usw. können Sie tatsächlich ein Gespräch führen. Aber denken Sie daran, dass heredoc die stdin einfach als Text sendet, es wartet nicht auf eine Antwort zwischen den Zeilen

Edit: Ich habe gerade herausgefunden, dass man die Innenseiten mit Registerkarten wenn Sie <<-END !

ssh user@host <<-'ENDSSH'
    #commands to run on remote host
    ssh user@host2 <<-'END2'
        # Another bunch of commands on another host
        wall <<-'ENDWALL'
            Error: Out of cheese
        ENDWALL
        ftp ftp.secureftp-test.com <<-'ENDFTP'
            test
            test
            ls
        ENDFTP
    END2
ENDSSH

(Ich denke, das sollte funktionieren)

Siehe auch http://tldp.org/LDP/abs/html/here-docs.html

6 Stimmen

Können Sie sich ein wenig behelfen, indem Sie Zeilen wie diese hinzufügen: # $(sleep 5)

59 Stimmen

Beachten Sie, dass mit einfachen Anführungszeichen um den Terminator ( <<'ENDSSH' ), werden die Zeichenketten nicht expandiert, Variablen werden nicht ausgewertet. Sie können auch <<ENDSSH o <<"ENDSSH" wenn Sie eine Erweiterung wünschen.

5 Stimmen

Expect kann verwendet werden, wenn Sie interaktive Befehle wie FTP automatisieren müssen.

270voto

dogbane Punkte 253146

Vergessen Sie auch nicht, die Variablen zu entschlüsseln, wenn Sie sie vom Zielhost abholen wollen.

Das ist mir in der Vergangenheit auch schon passiert.

Zum Beispiel:

user@host> ssh user2@host2 "echo \$HOME"

gibt /home/user2 aus

während

user@host> ssh user2@host2 "echo $HOME"

gibt /home/user aus

Ein weiteres Beispiel:

user@host> ssh user2@host2 "echo hello world | awk '{print \$1}'"

gibt "hallo" korrekt aus.

2 Stimmen

Beachten Sie jedoch folgende Punkte: ssh user2@host 'bash -s' echo $HOME /home/user2 exit

1 Stimmen

Ich möchte nur hinzufügen, dass in for Schleifen, die in ssh Sitzung darf die Schleifenvariable nicht escaped werden.

1 Stimmen

In vielen Situationen wäre die vernünftige Lösung für Ihr letztes Beispiel folgende ssh user2@host2 'echo hello world' | awk '{ print $1 }' d.h. Sie führen das Awk-Skript lokal aus. Wenn der Remote-Befehl eine riesige Menge an Ausgaben erzeugt, möchten Sie natürlich vermeiden, dass alles zurück auf den lokalen Server kopiert wird. Übrigens, einfache Anführungszeichen um den Remote-Befehl herum machen ein Escaping überflüssig.

175voto

chubbsondubs Punkte 35945

Dies ist eine Erweiterung der Antwort von YarekT, um Inline-Remote-Befehle mit der Übergabe von ENV-Variablen vom lokalen Rechner an den Remote-Host zu kombinieren, damit Sie Ihre Skripte auf der Remote-Seite parametrisieren können:

ssh user@host ARG1=$ARG1 ARG2=$ARG2 'bash -s' <<'ENDSSH'
  # commands to run on remote host
  echo $ARG1 $ARG2
ENDSSH

Ich fand es außerordentlich hilfreich, alles in einem Skript zusammenzufassen, so dass es sehr gut lesbar und wartbar ist.

Warum das funktioniert. ssh unterstützt die folgende Syntax:

ssh benutzer@host remote_befehl

In der Bash können wir Umgebungsvariablen angeben, die vor der Ausführung eines Befehls in einer einzigen Zeile wie folgt definiert werden:

ENV_VAR_1='Wert1' ENV_VAR_2='Wert2' bash -c 'echo $ENV_VAR_1 $ENV_VAR_2'

Das macht es einfach, Variablen vor der Ausführung eines Befehls zu definieren. In diesem Fall ist echo unser Befehl, den wir ausführen. Alles vor echo definiert Umgebungsvariablen.

Wir kombinieren also diese beiden Merkmale und die Antwort von YarekT und erhalten:

ssh user@host ARG1=$ARG1 ARG2=$ARG2 'bash -s' <<'ENDSSH'...

In diesem Fall setzen wir ARG1 und ARG2 auf lokale Werte. Wir senden alles nach user@host als remote_command. Wenn der entfernte Rechner den Befehl ausführt, werden ARG1 und ARG2 dank der lokalen Befehlszeilenauswertung, die Umgebungsvariablen auf dem entfernten Server definiert, auf die lokalen Werte gesetzt, und der Bash-Befehl wird mit diesen Variablen ausgeführt. Voilà.

1 Stimmen

Beachten Sie, dass Sie, wenn Sie Args wie -a übergeben wollen, -- verwenden können. z.B. 'ssh user@host -- -a foo bar 'bash -s' <script.sh'. Und die Argumente können auch nach der Umleitung stehen, z. B. 'ssh user@host 'bash -s' <script.sh -- -a foo bar'.

9 Stimmen

Wenn einer der env var-Werte Leerzeichen enthält, verwenden Sie: ssh user@host "ARG1=\"$ARG1\" ARG2=\"$ARG2\"" 'bash -s' <<'ENDSSH'...

3 Stimmen

Wie ich in einem anderen Kommentar schrieb, ist der eigentliche Sinn der Verwendung von -s ist es, Argumente auf Skripte anwenden zu können, die über stdin bezogen werden. Ich meine, Sie können es genauso gut weglassen, wenn Sie es nicht benutzen wollen. Wenn Sie es verwenden, gibt es keinen Grund, Umgebungsvariablen zu verwenden: ssh user@host 'bash -s value1 value2' <<< 'echo "$@"'

114voto

Vinko Vrsalovic Punkte 252104
<hostA_shell_prompt>$ ssh user@hostB "ls -la"

Dadurch werden Sie zur Eingabe eines Passworts aufgefordert, es sei denn, Sie haben den öffentlichen Schlüssel Ihres hostA-Benutzers in die Datei authorized_keys im Verzeichnis home of user .ssh kopiert. Dies ermöglicht eine passwortlose Authentifizierung (falls in der Konfiguration des ssh-Servers als Authentifizierungsmethode akzeptiert)

3 Stimmen

Ich habe Sie hochgestimmt. Dies ist eine gute Lösung. Natürlich müssen die Schlüssel geschützt werden, aber sie können auch wie ein Passwort über die Serverseite ungültig gemacht werden.

18 Stimmen

Ich glaube nicht, dass dies eine Antwort auf die Frage ist. Das Beispiel zeigt, wie man einen Remote-Befehl ausführt, aber nicht, wie man ein lokales Skript auf einem Remote-Rechner ausführt.

0 Stimmen

Ich bin mir nicht sicher, aber können Sie Ihr Skript auf HostA mit dieser Methode nicht über die Pipeline auf HostB laufen lassen?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X