Mehrere Befehle während einer SSH innerhalb einer SSH-Sitzung


10

Ich habe einen lokalen Computer, der eine SSH-Sitzung zu einem Remote- masterComputer und dann eine weitere innere SSH-Sitzung von masterjedem zu einem Remote- Computer durchführen und dann slaveszwei Befehle ausführen soll, dh ein bestimmtes Verzeichnis löschen und neu erstellen.

Beachten Sie, dass der lokale Computer ein passwortloses SSH für den Master und der Master ein passwortloses SSH für die Slaves hat. Außerdem sind alle Hostnamen in .ssh/configden lokalen / Master-Maschinen bekannt und die Hostnamen der Slaves sind slaves.txtlokal und ich lese sie von dort.

Was ich also mache und arbeite, ist Folgendes:

username="ubuntu"
masterHostname="myMaster"
while read line
do

    #Remove previous folders and create new ones.
    ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition""
    ssh -n $username@$masterHostname "ssh -t -t $username@$line "mkdir -p EC2_WORKSPACE/$project Input Output Partition""


    #Update changed files...
    ssh -n $username@$masterHostname "ssh -t -t $username@$line "rsync --delete -avzh /EC2_NFS/$project/* EC2_WORKSPACE/$project""

done < slaves.txt 

Dieser Cluster befindet sich auf Amazon EC2, und ich habe festgestellt, dass bei jeder Iteration 6 SSH-Sitzungen erstellt werden, was zu einer erheblichen Verzögerung führt. Ich möchte diese 3 Befehle zu 1 kombinieren, um weniger SSH-Verbindungen zu erhalten. Also habe ich versucht, die ersten beiden Befehle zu kombinieren

ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition && mkdir -p EC2_WORKSPACE/$project Input Output Partition""

Aber es funktioniert nicht wie erwartet. Es scheint das erste ( rm -rf Input Output Partition) auszuführen und verlässt dann die Sitzung und fährt fort. Was kann ich machen?


3
Anstelle einer solchen Indirektion im Befehl können Sie eine -JOption verwenden, die Ihren Sprunghost definiert.
Hauleth

Antworten:


15

Betrachten Sie das &&als logischen Operator. Es bedeutet nicht "auch diesen Befehl ausführen", sondern "diesen Befehl ausführen, wenn der andere erfolgreich war".

Das heißt, wenn der rmBefehl fehlschlägt (was passiert, wenn eines der drei Verzeichnisse nicht vorhanden ist), mkdirwird der Befehl nicht ausgeführt. Dies klingt nicht nach dem gewünschten Verhalten. Wenn die Verzeichnisse nicht vorhanden sind, ist es wahrscheinlich in Ordnung, sie zu erstellen.

Benutzen ;

Das Semikolon ;wird zum Trennen von Befehlen verwendet. Die Befehle werden nacheinander ausgeführt und warten jeweils, bevor sie mit dem nächsten fortfahren. Ihr Erfolg oder Misserfolg hat jedoch keine Auswirkungen aufeinander.

Entkomme inneren Zitaten

Anführungszeichen in anderen Anführungszeichen sollten maskiert werden, andernfalls erstellen Sie einen zusätzlichen Endpunkt und Startpunkt. Ihr Befehl:

ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition && mkdir -p EC2_WORKSPACE/$project Input Output Partition""

Wird:

ssh -n $username@$masterHostname "ssh -t -t $username@$line \"rm -rf Input Output Partition && mkdir -p EC2_WORKSPACE/$project Input OutputPartition\""

Ihr aktueller Befehl sollte aufgrund des Mangels an maskierten Anführungszeichen Folgendes ausführen:

ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition

wenn das gelingt:

mkdir -p EC2_WORKSPACE/$project Input Output Partition"" # runs on your local machine

Sie werden feststellen, dass die Syntaxhervorhebung den gesamten Befehl hier rot anzeigt. Dies bedeutet, dass der gesamte Befehl die Zeichenfolge ist, die an ssh übergeben wird. Überprüfen Sie Ihren lokalen Computer. Möglicherweise haben Sie die Verzeichnisse Input Outputund Partitionwo Sie dies ausgeführt haben.


Ich verstehe deine Punkte. Ein Teil, der mich verwirrte, war das Semikolon, da ich dachte, es würde mehr als 1 Befehle gleichzeitig ausführen, weshalb ich es nicht verwendete.
mgus

Das Semikolon bewirkt nicht, dass die Befehle gleichzeitig ausgeführt werden. Siehe hier als Referenz für die Ausführung von Befehlen. Die &Befehle werden im Hintergrund ausgeführt, was bedeutet, dass nicht darauf gewartet werden muss, bis sie beendet sind, bevor mit dem nächsten fortgefahren wird.
Centimane

10

Sie können in Ihrer Jumpbox Multiplexing jederzeit in OpenSSH definieren

Multiplexing ist die Fähigkeit, mehr als ein Signal über eine einzelne Leitung oder Verbindung zu senden. Beim Multiplexen kann OpenSSH eine vorhandene TCP-Verbindung für mehrere gleichzeitige SSH-Sitzungen wiederverwenden, anstatt jedes Mal eine neue zu erstellen.

Ein Vorteil beim SSH-Multiplexing besteht darin, dass der Aufwand für das Erstellen neuer TCP-Verbindungen entfällt. Die Gesamtzahl der Verbindungen, die ein Computer akzeptieren kann, ist eine endliche Ressource, und das Limit ist auf einigen Computern deutlicher als auf anderen und variiert stark je nach Auslastung und Nutzung. Es gibt auch erhebliche Verzögerungen beim Öffnen einer neuen Verbindung. Aktivitäten, die wiederholt neue Verbindungen öffnen, können durch Multiplexing erheblich beschleunigt werden.

Dafür tun Sie in /etc/ssh/ssh_config:

ControlMaster auto
ControlPath ~/.ssh/controlmasters/ssh_mux_%h_%p_%r
ControlPersist 30m

Auf diese Weise werden alle aufeinanderfolgenden Verbindungen, die in den folgenden 30 Minuten zum selben Server hergestellt wurden, wieder verwendet, wobei die vorherige SSH-Verbindung wiederverwendet wird.

Sie können es auch für eine Maschine oder eine Gruppe von Maschinen definieren. Entnommen aus dem angegebenen Link.

Host machine1
    HostName machine1.example.org
    ControlPath ~/.ssh/controlmasters/%r@%h:%p
    ControlMaster auto
    ControlPersist 10m

Das ist interessant! Gibt es eine Möglichkeit, es für eine bestimmte Verbindung explizit ein- und auszuschalten? Scheint übertrieben, alle SSH-Verbindungen für diesen einen Anwendungsfall so drastisch zu ändern. Kann es genauer verwendet werden? Um nur eine bestimmte Verbindung zu multiplexen?
Centimane

@ Centimane ja, aktualisiert die Antwort
Rui F Ribeiro

1
Ich würde vorschlagen, die Steckdose im Haus des Benutzers zu platzieren und nicht in einer lesbaren Welt /tmp/.
Heemayl

@heemayl Guter Punkt. Ich werde es in einem Computer bearbeiten.
Rui F Ribeiro

@RuiFRibeiro sieht auch wie, nach man ssh, ControlPath, ControlMasterund ControlPersistsind gültige Optionen einen passieren sshmit dem Befehl -o. Könnte ein noch genauerer Anwendungsfall sein, richten Sie das Multiplexing im ersten sshTeil des Skripts ein und recyceln Sie es für die anderen, aber vermeiden Sie ansonsten die Leistungseinbußen. Ich frage mich, was der Maßstab für das Multiplexen von VS nicht für 3 SSH-Verbindungen ist, da "es auch eine erhebliche Verzögerung beim Öffnen einer neuen Verbindung gibt"
Centimane

4

Sie können alle Ihre Befehle in einem separaten Skript auf Ihrem "Master" -Server ablegen.

Master Script

#!/bin/bash
rm -rf "Input Output Partition"
mkdir -p "EC2_WORKSPACE/$project Input Output Partition"

Rufen Sie es dann in Ihrem SSH-Skript folgendermaßen auf : SSH-Skript

username="ubuntu"
masterHostname="myMaster"
while read line
do
ssh -n $username@$masterHostname "ssh -t -t $username@$line < /path/to/masterscript.sh"
ssh -n $username@$masterHostname "ssh -t -t $username@$line "rsync --delete -avzh /EC2_NFS/$project/* EC2_WORKSPACE/$project""
done < slaves.txt 

ODER wenn sich alle Dateien auf dem ursprünglichen Computer befinden müssen, können Sie Folgendes tun:

script1

script2="/path/to/script2"
username="ubuntu"
while read line; do
cat $script2 | ssh -t -t $username@line
done < slaves.txt

script2

#!/bin/bash
rm -rf "Input Output Partition"
mkdir -p "EC2_WORKSPACE/$project Input Output Partition"
rsync --delete -avzh "/EC2_NFS/$project/* EC2_WORKSPACE/$project"

SSH-Skript

script1="/path/to/script1"
username="ubuntu"
masterHostname="myMaster"
cat $script1 | ssh -n $username@$masterHostname

1

Vor einiger Zeit hatte ich Gelegenheit, Control Sockets zu verwenden, wie es die anderen Antworten empfehlen (diese Antwort ist im Wesentlichen eine Kombination aus Control Sockets wie dieser Antwort und Skripten wie dieser Antwort ).

Der Anwendungsfall war ein Hack: Der authorized_keysdes Zielbenutzers wurde regelmäßig durch eine geplante Aufgabe überschrieben, und ich wollte die Dinge schnell testen, ohne Bürokratie zu benötigen, um dieser Datei etwas hinzuzufügen. Also habe ich eine while-Schleife eingerichtet, die den Schlüssel nach Bedarf zu dieser Datei hinzufügt, meinen Test ausgeführt und die Schleife abgebrochen. Es würde jedoch ein kleines Fenster geben, in dem die geplante Aufgabe die Datei überschreiben würde und meine Schleife immer noch sleepläuft. Wenn Sie also zu Beginn einen Control Socket einrichten, kann mein Skript später problemlos SSH ausführen:

#! /bin/bash -xe
. "${CONFIG_DIR}/scripts/setup-ssh.sh"

# Build and test
export TEST_LABEL="${_started_by}-${BUILD_TAG%-BUILD*}"
#...
xargs --arg-file test-list \
    --no-run-if-empty \
    --process-slot-var=NUM \
    --max-procs=${#SERVERS[@]} \
    --max-args="${BATCH_SIZE:-20}" \
    "${CONFIG_DIR}/scripts/run-test.sh"

Wo setup-ssh.shist:

export SSH_CONFIG="${CONFIG_DIR}/scripts/.ssh-config"
mapfile -t SERVERS < "${CONFIG_DIR}/scripts/hosts"

for SERVER in "${SERVERS[@]}"
do
    while ! ssh -F "${SSH_CONFIG}" "${SERVER}" -fnN; do sleep 1; done
    scp -F "${SSH_CONFIG}" "${CONFIG_DIR}/scripts/ssh-script.sh" "${SERVER}":"${TEST_LABEL}.sh"
done

Und .ssh-config:

Host test-*
  User test
  StrictHostKeyChecking no
  ControlMaster auto
  ControlPath /tmp/ssh-%h-%p-%r

Und run-test.sh:

mapfile -t TEST_SERVERS < "${CONFIG_DIR}/scripts/hosts"
ssh -F "${SSH_CONFIG}" "${TEST_SERVERS[$NUM]}" "./${TEST_LABEL}.sh"

Die Reihenfolge sieht folgendermaßen aus:

  • Das Hauptskript (zuerst gezeigt) Quellen setup-ssh.sh.
  • setup-ssh.shBusy-Loops der Server, bis alle über einen Control Socket-Setup verfügen. In der hostsDatei werden einfach die Server-Hostnamen pro Zeile aufgelistet.
  • Da die Konfiguration, die den Steuerungssocket angibt, nur in ${CONFIG_DIR}/scripts/.ssh-configist -F, wird sie von SSH-Verbindungen nicht verwendet, es sei denn, ich gebe diese Datei mit an . Auf diese Weise kann ich die Steuerbuchse nur dort verwenden, wo ich sie mit der FOption benötige .
  • Das Setup-Skript kopiert auch das Testausführungsskript auf die Server. Das Ausführungsskript selbst enthält eine Reihe von Befehlen. Da ich das Ausführungsskript kopiert habe, muss ich mir keine Gedanken über eine zusätzliche Zitierschicht für SSH machen (und den zusätzlichen kognitiven Aufwand, um herauszufinden, was wann erweitert wird).
  • Anschließend verteilt das Hauptskript xargsdie Arbeitslast auf die Server, indem neue Jobs gestartet werden, sobald die Ausführung beendet ist.
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.