it-swarm.com.de

Was ist der sauberste Weg, um ssh auszuführen und mehrere Befehle in Bash auszuführen?

Ich habe bereits einen SSH-Agenten eingerichtet und kann Befehle auf einem externen Server in einem Bash-Skript ausführen.

ssh blah_server "ls; pwd;"

Nun möchte ich wirklich sehr lange Befehle auf einem externen Server ausführen. Alle diese Anführungszeichen in Anführungszeichen zu setzen, wäre ziemlich hässlich, und ich möchte lieber mehrmals ssh'ing machen, um dies zu vermeiden. 

Gibt es eine Möglichkeit, dies auf einmal zu tun, eingeschlossen in Klammern oder etwas? Ich suche etwas in der Art von:

ssh blah_server (
   ls some_folder;
   ./someaction.sh;
   pwd;
)

Grundsätzlich bin ich mit jeder Lösung zufrieden, solange sie sauber ist.

Bearbeiten

Um dies zu verdeutlichen, spreche ich davon, dass dies Teil eines größeren Bash-Skripts ist. Andere Leute müssen sich möglicherweise mit dem Skript befassen, also möchte ich es sauber halten. Ich möchte kein Bash-Skript mit einer Zeile haben, die wie folgt aussieht:

ssh blah_server "ls some_folder; ./someaction.sh 'some params'; pwd; ./some_other_action 'other params';"

weil es extrem hässlich und schwer zu lesen ist.

278
Eli

Wie wäre es mit einem Bash Here Document :

ssh otherhost << EOF
  ls some_folder; 
  ./someaction.sh 'some params'
  pwd
  ./some_other_action 'other params'
EOF

Um die von @Globalz in den Kommentaren genannten Probleme zu vermeiden, können Sie (je nachdem, was Sie auf der Remote-Site tun) die erste Zeile durch ersetzen

ssh otherhost /bin/bash << EOF

Beachten Sie, dass Sie im Here-Dokument eine Variablensubstitution durchführen können, dass Sie sich jedoch möglicherweise mit Zitierungsproblemen befassen müssen. Wenn Sie beispielsweise die "Begrenzungszeichenfolge" (z. B. EOF oben) angeben, können Sie keine Variablenersetzungen durchführen. Ohne die Begrenzungszeichenfolge anzugeben, werden die Variablen jedoch ersetzt. Wenn Sie beispielsweise $NAME oben in Ihrem Shell-Skript definiert haben, können Sie dies tun

ssh otherhost /bin/bash << EOF
touch "/tmp/${NAME}"
EOF

und es würde eine Datei auf dem Ziel otherhost mit dem Namen dessen erstellen, was Sie $NAME zugewiesen haben. Es gelten auch andere Regeln für das Zitieren von Shell-Skripten, die jedoch zu kompliziert sind.

387
Paul Tomblin

Bearbeiten Sie Ihr Skript lokal und leiten Sie es in ssh weiter, z.

cat commands-to-execute-remotely.sh | ssh blah_server

wo commands-to-execute-remotely.sh wie oben in deiner Liste aussieht:

ls some_folder
./someaction.sh
pwd;
102
bosmacs

Um Ihrem Beispielcode zu entsprechen, können Sie Ihre Befehle in einfache oder doppelte Anführungszeichen setzen. Zum Beispiel

ssh blah_server "
  ls
  pwd
"
32
Andrei B

Ich sehe zwei Möglichkeiten:

Zuerst machen Sie eine Kontrollbuchse wie folgt:

 ssh -oControlMaster=yes -oControlPath=~/.ssh/ssh-%r-%h-%p <yourip>

und führen Sie Ihre Befehle aus

 ssh -oControlMaster=no -oControlPath=~/.ssh/ssh-%r-%h-%p <yourip> -t <yourcommand>

Auf diese Weise können Sie einen ssh-Befehl schreiben, ohne sich tatsächlich mit dem Server zu verbinden.

Die zweite wäre, das Skript dynamisch zu generieren, scping und auszuführen.

31
terminus

Dies kann auch wie folgt durchgeführt werden: Geben Sie Ihre Befehle in ein Skript ein, nennen wir es befehle-inc.sh

#!/bin/bash
ls some_folder
./someaction.sh
pwd

Speicher die Datei

Führen Sie es jetzt auf dem Remote-Server aus.

ssh [email protected] 'bash -s' < /path/to/commands-inc.sh

Nie für mich gescheitert.

16
R J

SSH und mehrere Befehle in Bash ausführen.

Separate Befehle mit Semikolons innerhalb eines Strings, die an echo übergeben werden, alle an den Befehl ssh weitergeleitet. Zum Beispiel:

echo "df -k;uname -a" | ssh 192.168.79.134

Pseudo-terminal will not be allocated because stdin is not a terminal.
Filesystem     1K-blocks    Used Available Use% Mounted on
/dev/sda2       18274628 2546476  14799848  15% /
tmpfs             183620      72    183548   1% /dev/shm
/dev/sda1         297485   39074    243051  14% /boot
Linux newserv 2.6.32-431.el6.x86_64 #1 SMP Sun Nov 10 22:19:54 EST 2013 x86_64 x86_64 x86_64 GNU/Linux
8
arnab

Setzen Sie alle Befehle in ein Skript und es kann wie ausgeführt werden

ssh <remote-user>@<remote-Host> "bash -s" <./remote-commands.sh
7
Jai Prakash

Für jeden, der hier wie ich stolpert - ich hatte Erfolg damit, dem Semikolon und dem Newline zu entgehen:

Erster Schritt: das Semikolon. Auf diese Weise unterbrechen wir den Befehl ssh nicht:

ssh <Host> echo test\;ls
                    ^ backslash!

Das entfernte Verzeichnis hosts/home (als root angemeldet) wurde aufgelistet

ssh <Host> echo test;ls
                    ^ NO backslash

das aktuelle Arbeitsverzeichnis aufgelistet.

Nächster Schritt: Aufbrechen der Linie:

                      v another backslash!
ssh <Host> echo test\;\
ls

Hier wurde erneut das Remote-Arbeitsverzeichnis aufgelistet - verbesserte Formatierung:

ssh <Host>\
  echo test\;\
  ls

Ob wirklich schöner als hier Dokument oder Zitate um gebrochene Linien - na gut, ich entscheide nicht ...

(Mit bash, Ubuntu 14.04 LTS.)

5
Aconcagua

Dies eignet sich gut zum Erstellen von Skripts, da Sie keine anderen Dateien hinzufügen müssen:

#!/bin/bash
ssh <my_user>@<my_Host> "bash -s" << EOF
    # here you just type all your commmands, as you can see, i.e.
    touch /tmp/test1;
    touch /tmp/test2;
    touch /tmp/test3;
EOF
4
sjas

Der einfachste Weg, um Ihr System für die Verwendung einzelner SSH-Sitzungen standardmäßig mit Multiplexing zu konfigurieren.

Dazu können Sie einen Ordner für die Sockel erstellen:

mkdir ~/.ssh/controlmasters

Fügen Sie dann der .ssh-Konfiguration Folgendes hinzu:

Host *
    ControlMaster auto
    ControlPath ~/.ssh/controlmasters/%[email protected]%h:%p.socket
    ControlMaster auto
    ControlPersist 10m

Jetzt müssen Sie keinen Code ändern. Dies ermöglicht mehrere Aufrufe von ssh und scp, ohne dass mehrere Sitzungen erstellt werden müssen. Dies ist nützlich, wenn mehr Interaktion zwischen Ihren lokalen und Remote-Computern erforderlich ist.

Dank der Antwort von @ terminus http://www.cyberciti.biz/faq/linux-unix-osx-bsd-ssh-multiplexing-to-speed-up-ssh-connections/ und https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Multiplexing .

2
Jonathan

Die geposteten Antworten mit mehrzeiligen Zeichenfolgen und mehreren Bash-Skripts funktionierten für mich nicht.

  • Lange mehrzeilige Saiten sind schwer zu warten. 
  • Separate Bash-Skripts verwalten keine lokalen Variablen. 

Hier ist ein funktionaler Weg, um ssh auszuführen und mehrere Befehle auszuführen, während der lokale Kontext beibehalten wird.

LOCAL_VARIABLE=test

run_remote() {
    echo "$LOCAL_VARIABLE"
    ls some_folder; 
    ./someaction.sh 'some params'
    ./some_other_action 'other params'
}

ssh otherhost "$(set); run_remote"
2

Nicht sicher, ob das sauberste für lange Befehle ist, aber sicherlich das einfachste

ssh [email protected] "cmd1; cmd2; cmd;3"
0
DimiDak