
Ich habe eine große Anzahl großer Dateien (Hunderte von Dateien, jeweils Hunderte von MB), die ich durch eine Reihe von Programmen leiten muss, um sie zu filtern und zu konvertieren. Ich nutze mehrere CPU-Kerne, sodass ich für jede Datei mehrere Instanzen derselben Pipe ausführe (es könnten bis zu hundert Kerne sein, und ich könnte SSH als Teil der Pipe verwenden, falls das für die Antwort einen Unterschied macht). Ich möchte jede Pipe überwachen und verwende pv
dafür. Hier ist ein minimales Beispiel dessen, was ich habe:
$ pv file-001.gz | gunzip | xz > file-001.xz
1.58GB 0:00:02 [ 713MB/s] [=================================>] 100%
In Wirklichkeit mache ich in der Pipe auch noch einige andere Dinge, darunter das Weiterleiten von Daten an andere Rechner über SSH und das Weiterleiten durch Filter auf diesen Rechnern, aber die Pipe endet immer mit einer Umleitung in eine neue Datei auf dem Haupthost. Außerdem erfordert keine Stufe in der Pipe den gesamten Datensatz; sie können zeilenweise oder stückweise arbeiten.
Derzeit benötige ich für jede Instanz der Pipe ein separates Terminalfenster. Ich möchte n parallele Instanzen der Pipe in einem einzigen Terminal/einer einzigen Shell starten und die Ausgabe jeder pv-Instanz in einer eigenen Zeile erhalten. Etwa so:
1.48GB 0:00:54 [ 704MB/s] [===============================> ] 97% ETA 00:00:06
1.58GB 0:01:00 [ 713MB/s] [=================================>] 100%
0.75GB 0:00:31 [ 709MB/s] [================> ] 50% ETA 00:00:29
Der Wert für n wäre die Anzahl der Zeilen, die ich in ein Terminalfenster einfügen kann, also etwa 3-50. Das genaue Format des Fortschrittsberichts ist nicht wichtig, solange er die Geschwindigkeit, den Prozentsatz der Fertigstellung, die verstrichene Zeit und die geschätzte verbleibende Zeit enthält. Es ist auch nicht wichtig, dass ich verwende. pv
Es ist in Ordnung, ein anderes Programm zu verwenden, solange ich es einfach installieren kann, oder einfach eine einfache Shell (vorzugsweise Bash). Wichtig ist jedoch, dass die Methode mit gelegentlich unterbrochenen Pipes umgehen kann, falls ein Teil der Pipe aus irgendeinem Grund abstürzt. Ich möchte auch jedes Mal neue Jobs starten, wenn ein Job abgeschlossen ist (erfolgreich oder nicht) und noch unbearbeitete Dateien übrig sind.
Irgendwelche Ideen, wie das geht?
Beachten Sie, dass ich bereits versucht habeGNU Parallel, aber seine SSH-Funktionen scheinen davon auszugehen, dass jede Eingabedatei zuerst an den Remote-Host übertragen, dann verarbeitet und anschließend das Ergebnis zurückübertragen wird, was ich aufgrund der Datenmenge und des begrenzten Speicherplatzes auf jedem Verarbeitungsknoten vermeiden möchte.
Antwort1
Irgendwelche Ideen, wie das geht?
NEIN.
pv hat die Optionen -c und -N, die es Ihnen ermöglichen sollten, das zu tun, was Sie wollen
$ pv -cN source access.log | gzip | pv -cN gzip > access.log.gz
source: 760MB 0:00:15 [37.4MB/s] [=> ] 19% ETA 0:01:02
gzip: 34.5MB 0:00:15 [1.74MB/s] [ <=> ]
aber ich kann nicht sehen, wie man diese Funktion auf mehrere Pipelines anwenden kann
Wenn Sie jedoch die Manpage für pv ansehen, werden Sie Folgendes sehen
(tar cf - . \
| pv -n -s $(du -sb . | awk '{print $1}') \
| gzip -9 > out.tgz) 2>&1 \
| dialog --gauge 'Progress' 7 70
Sie könnten dies also erweitern, um mehrere Aufgaben parallel auszuführen, solange es akzeptabel ist, den Fortschritt in einer Gruppe kleiner Fenster anzuzeigen. Ich würde es mit Xdialog versuchen.
Derzeit benötige ich für jede Instanz der Pipe ein separates Terminalfenster
Mein Hauptpunkt ist, dass Sie nicht interaktiv viele Terminalfenster öffnen müssen, sondern dass ein Skript viele Dialogfelder selbst öffnen könnte.
Antwort2
--pipe
Haben Sie nach GNU Parallel gesucht ?
cat bigfiles* | pv | parallel --pipe -S server1,server2 'cat | process_pipe'
(Katze zur Hervorhebung miteinbezogen)
Die Blockgröße beträgt standardmäßig 1 MB und kann mit --block angepasst werden.
-- Bearbeiten für 1:1-Korrespondenz --
Auf Grundlage des oben Gesagten können Sie eine 1:1-Korrespondenz wie diese erhalten:
parallel --eta "cat {} | parallel --pipe -S server1,server2 'cat | process_pipe' > {}.out" ::: bigfiles*
(Katze zur Hervorhebung miteinbezogen)
Dies ist nicht ganz optimal, da der innere Parallelserver nichts von seinen Geschwistern weiß und daher möglicherweise mehr auf Server1 als auf Server2 erzeugt. Eine Möglichkeit, dies zu vermeiden, ist -j1 auf dem äußeren Parallelserver, aber dies ist nicht optimal, wenn der innere nur genug Blöcke für den ersten Server hat. Mit anderen Worten: Um Ihre Arbeitslast perfekt auszugleichen, müssen Sie möglicherweise ein wenig daran herumbasteln – vielleicht sogar --load 100% oder Ähnliches verwenden.
--- Bearbeiten: Mit Abstürzen umgehen ---
Wenn process_pipe
ein Fehler zurückgegeben wird, sollte der Befehl noch zweimal wiederholt werden:
parallel --retries 3 --eta "cat {} | parallel --pipe -S server1,server2 'cat | process_pipe' > {}.out" ::: bigfiles*