it-swarm.com.de

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

Ich habe einen lokalen Computer, der eine SSH-Sitzung mit einem Remote-Computer master durchführen soll, und dann eine weitere innere SSH-Sitzung von master zu jedem Remote-Computer slaves Führen Sie dann zwei Befehle aus, um ein bestimmtes Verzeichnis zu löschen und neu zu 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. Auch alle Hostnamen sind in .ssh/config Der lokalen/Master-Maschinen bekannt und die Hostnamen der Slaves sind lokal in slaves.txt 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 [email protected]$masterHostname "ssh -t -t [email protected]$line "rm -rf Input Output Partition""
    ssh -n [email protected]$masterHostname "ssh -t -t [email protected]$line "mkdir -p EC2_WORKSPACE/$project Input Output Partition""


    #Update changed files...
    ssh -n [email protected]$masterHostname "ssh -t -t [email protected]$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 [email protected]$masterHostname "ssh -t -t [email protected]$line "rm -rf Input Output Partition && mkdir -p EC2_WORKSPACE/$project Input Output Partition""

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

10
mgus

Berücksichtige das && ist ein logischer Operator. Es bedeutet nicht "auch diesen Befehl ausführen", sondern "diesen Befehl ausführen, wenn der andere erfolgreich war".

Das heißt, wenn der Befehl rm fehlschlägt (was passiert, wenn eines der drei Verzeichnisse nicht vorhanden ist), wird mkdir 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.

Verwenden ;

Das Semikolon ; wird verwendet, um Befehle zu trennen. 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.

Escape innere Anführungszeichen

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

ssh -n [email protected]$masterHostname "ssh -t -t [email protected]$line "rm -rf Input Output Partition && mkdir -p EC2_WORKSPACE/$project Input Output Partition""

Wird:

ssh -n [email protected]$masterHostname "ssh -t -t [email protected]$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 [email protected]$masterHostname "ssh -t -t [email protected]$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 InputOutput und Partition, in denen Sie dies ausgeführt haben.

15
Centimane

Sie können jederzeit in Ihrer Jumpbox Multiplexing 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 möglicherweise akzeptiert, ist eine endliche Ressource, und das Limit ist auf einigen Computern deutlicher als Bei anderen ist die Verzögerung beim Öffnen einer neuen Verbindung sehr unterschiedlich. Aktivitäten, bei denen wiederholt neue Verbindungen geöffnet werden, können durch Multiplexing erheblich beschleunigt werden.

Dafür 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/%[email protected]%h:%p
    ControlMaster auto
    ControlPersist 10m
10
Rui F Ribeiro

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 [email protected]$masterHostname "ssh -t -t [email protected]$line < /path/to/masterscript.sh"
ssh -n [email protected]$masterHostname "ssh -t -t [email protected]$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 [email protected]
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 [email protected]$masterHostname
4
jesse_b

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 diese Antwort und Skripten wie diese Antwort ). .

Der Anwendungsfall war ein Hack: Das authorized_keys des 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 sleeping wäre. 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.sh ist:

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.sh Busy-Loops der Server, bis alle über ein Control Socket-Setup verfügen. In der Datei hosts werden einfach die Server-Hostnamen pro Zeile aufgelistet.
  • Da die Konfiguration, die den Steuersockel angibt, nur in ${CONFIG_DIR}/scripts/.ssh-config, es sei denn, ich spezifiziere diese Datei mit -F, SSH-Verbindungen werden es nicht verwenden. Auf diese Weise kann ich den Control Socket nur dort verwenden, wo ich ihn mit der Option F 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 Anführungsschicht für SSH machen (und den zusätzlichen kognitiven Aufwand, um herauszufinden, was wann erweitert wird).
  • Anschließend verwendet das Hauptskript xargs, um die Arbeitslast auf die Server zu verteilen, indem neue Jobs gestartet werden, sobald die Ausführung beendet ist.
1
muru