Parallelisierung von Remote-Tar und Ausgabe per SSH-Pipe

1

Ich habe versucht, das von mir verwendete Skript zu parallelisieren, aber bisher ist GNU Parallel sehr herausfordernd.

Ich habe 2 Dateien - eine mit Hosts, auf denen der Befehl ausgeführt werden soll, und eine mit Parametern für den Befehl. Unten ist beispieldaten:

$ cat workers.host 
foo@192.168.0.7
bar@192.168.0.8
jerry@192.168.0.9
tom@192.168.0.21



$ cat paths
/usr/local/jar/x/y/ jarxy
/usr/local/jar/z/y/ jarzy
/usr/local/jar/y/y/ jaryy
/usr/local/far/x/y/ farxy
/usr/local/jaz/z/z/ jazzz
/usr/local/mu/txt/ana/ acc01
/usr/local/jbr/x/y/ accxy

Und um das zu verarbeiten, benutze ich folgendes Skript:

#!/bin/bash

echo "Run this on 192.168.130.10";

DATA=`date +%F`
DDAY=`date +%u`
DOMBAC='nice tar cpzf'

readarray -t hosts < workers.host

len=${#hosts[@]};
processed=0;

while read -r -a line; do

  let hostnum=processed%len;

  ssh ${hosts[$hostnum]} -i /root/.ssh/id_rsa "$DOMBAC - ${line[0]}" > "/data/backup/$DDAY/${line[1]}_${DATA}_FULL.tgz"

  let processed+=1;
done < paths

Dies funktioniert gut, wird jedoch maschinenweise schrittweise abgearbeitet. Die Hosts sind ziemlich überlastet und das Netzwerk ist hier kein Problem. Deshalb wollte ich dies so weit wie möglich parallelisieren. Führen Sie zum Beispiel 4 Instanzen des Befehls tar auf jedem Host aus und leiten Sie die Ausgabe über ssh in eine ordnungsgemäß benannte Datei. Ich bin völlig verloren mit parallel --results --sshloginfile... Und was ich letztendlich erreichen möchte, ist, dass 4 Jobs auf jedem Host laufen, jeder mit unterschiedlichen Parametern (so dass zum Beispiel Host 2 nicht überschreibt, was Host 1 bereits getan hat). . Kann das in GNU Parallel gemacht werden?

Johnny_Bit
quelle

Antworten:

1

Zuerst müssen Sie wissen, wie Sie mehrere Argumente aus einer einzigen Eingabezeile extrahieren können:

cat paths | parallel --colsep ' ' echo {2} == {1}

(Ich stelle fest, dass ein Teil von {2} aus {1} generiert werden kann. Wenn dies immer der Fall ist, möchten Sie möglicherweise {= =} untersuchen; dies ist jedoch eine Geschichte für eine andere Frage.)

So führen Sie Jobs aus der Ferne aus -S:

cat paths | parallel --colsep ' ' -S server echo {2} == {1}

So steuern Sie, wie viele Jobs auf einem Remoteserver ausgeführt werden -j:

cat paths | parallel --colsep ' ' -j4 -S server echo {2} == {1}

Um die Ausgabe lokal --return --cleanupzu speichern, kann Folgendes verwendet werden:

cat paths | parallel --return {2} --cleanup --colsep ' ' -j4 -S server echo {2} == {1} '>' {2}

Da die Ausgabe lokal in einem anderen Verzeichnis gespeichert werden soll, müssen Sie den Trick /./ verwenden:

cat paths | parallel --return my/local/dir/./{2} --cleanup --colsep ' ' -j4 -S server echo {2} == {1} '>' {2}

Um einen speziellen sshBefehl zu verwenden, verwenden Sie --ssh:

parallel --ssh "ssh -i $HOME/.ssh/id_rsa.pub -lroot" --return {2} --cleanup --colsep ' ' -j4 -S server echo {2} == {1} '>' {2}

Verwenden Sie zur Ausführung auf mehreren Servern --slfanstelle von -S:

parallel --slf hosts.txt --ssh "ssh -i $HOME/.ssh/id_rsa.pub -lroot" --return {2} --cleanup --colsep ' ' -j4 echo {2} == {1} '>' {2}

Insgesamt könnte Ihr Befehl also so aussehen:

parallel --slf hosts.txt --ssh "ssh -i $HOME/.ssh/id_rsa.pub -lroot" --return /data/backup/$DDAY/./{2}_${DATA}_FULL.tgz --cleanup --colsep ' ' -j4 "$DOMBAC - {1} > {2}_${DATA}_FULL.tgz"
Ole Tange
quelle
Kommentare zum Stapelüberlauf eignen sich nicht für die gemeinsame Nutzung und Diskussion von Code. Auf jeden Fall muss ich Ihre Lösung ausprobieren. Mein jetziger (roher) parallel -j${JOBS} --link ./do_on_hosts.sh {1} {2} "$DATA" "$DDAY" :::: workers.host :::: to_backup.pathbasiert auf zwei Dingen: und in do_on_hosts.sh: ssh $1 "${REMOTE_CMD} ${arr[0]}"> ${LOCAL_STORAGE_PATH}${DDAY}/${arr[1]}_${DATA}_FULL.tgzIch frage mich, wie das im Vergleich zu Deinem ist ... brauche eine weitere Runde, um es zu versuchen.
Johnny_Bit
0

Sie könnten parallel dazu verwenden, um dies zu erreichen, aber ich denke, es wäre übertrieben für das, was Sie erreichen möchten. Stattdessen würde ich einfach Hintergrundjobs verwenden, um diese Befehle (in der Nähe von) gleichzeitig auszuführen.

Um dies mit einem Minimum an Änderungen an Ihrem vorhandenen Skript zu erreichen, müssen wir lediglich jede ausgeführte Task im Hintergrund ausführen (verwenden Sie dazu den Operator &). Um verwaiste Prozesse zu verhindern, sollten wir sicherstellen, dass das Skript erst beendet wird, wenn alle Jobs abgeschlossen sind, was mit der integrierten Bash erledigt wird wait. Der Befehl jobs gibt eine Liste der ausgeführten Tasks aus (möglicherweise sind nicht alle Tasks vorhanden, einige sind je nach Ausführungszeit bereits beendet, bevor Sie diesen Punkt erreichen).

Ich bin mir auch nicht sicher, warum Sie den Befehl nice ohne Argument verwenden. Ich glaube, dass er ohne Argument nur die relative Priorität der gestarteten Aufgabe ausgibt, was vermutlich Ihre Absicht sein könnte.

Hier ist eine modifizierte Version Ihres Skripts mit diesen Änderungen

#!/bin/bash

echo "Run this on 192.168.130.10";

DATA=`date +%F`
DDAY=`date +%u`
DOMBAC='nice tar cpzf'

readarray -t hosts < workers.host

len=${#hosts[@]};
processed=0;

while read -r -a line; do

  let hostnum=processed%len;

  ssh ${hosts[$hostnum]} -i /root/.ssh/id_rsa "$DOMBAC - ${line[0]}" > "/data/backup/$DDAY/${line[1]}_${DATA}_FULL.tgz" &

  let processed+=1;
done < paths
jobs
wait
Argonauten
quelle
Hallo! Ich habe es geschafft, dies mit gnu parallel zu parallelisieren. Ich muss jedoch warten, bis meine Lösung ordnungsgemäß funktioniert. Als Kommentar zu der vorgeschlagenen Lösung - nun, deshalb brauche ich eigentlich GNU Parallel - würden die Worker-Hosts sonst mit Aufgaben überflutet und könnten nicht fertig werden. Stellen Sie sich vor, dass die Hosts-Datei eher aus 4-8 Einträgen besteht, die Pfade jedoch aus 10-20 Tausend Pfaden. Wie für nice- ohne Argumente ändert sich die Freundlichkeit von 0 auf 10 :)
Johnny_Bit
Ich habe in der Manpage nach nice man7.org/linux/man-pages/man1/nice.1.html
Argonauts
Posten Sie Ihre Lösung mit parallel, wenn Sie können, damit andere Personen, die danach suchen, sie finden
Argonauts