Ich habe ein Bash-Skript, das so aussieht:
#!/bin/bash
wget LINK1 >/dev/null 2>&1
wget LINK2 >/dev/null 2>&1
wget LINK3 >/dev/null 2>&1
wget LINK4 >/dev/null 2>&1
# ..
# ..
wget LINK4000 >/dev/null 2>&1
Aber jede Zeile zu verarbeiten, bis der Befehl beendet ist, und dann zur nächsten zu wechseln, ist sehr zeitaufwändig. Ich möchte zum Beispiel 20 Zeilen gleichzeitig verarbeiten. Wenn sie fertig sind, werden weitere 20 Zeilen verarbeitet.
Ich dachte wget LINK1 >/dev/null 2>&1 &
daran, den Befehl in den Hintergrund zu senden und weiterzumachen, aber hier gibt es 4000 Zeilen. Dies bedeutet, dass ich Leistungsprobleme haben werde, ganz zu schweigen davon, dass die Anzahl der Prozesse, die ich gleichzeitig starten sollte, begrenzt ist. Dies ist also nicht gut Idee.
Eine Lösung, an die ich gerade denke, besteht darin, zu überprüfen, ob einer der Befehle noch ausgeführt wird oder nicht. Zum Beispiel kann ich nach 20 Zeilen diese Schleife hinzufügen:
while [ $(ps -ef | grep KEYWORD | grep -v grep | wc -l) -gt 0 ]; do
sleep 1
done
Natürlich muss ich in diesem Fall & an das Ende der Zeile anhängen! Aber ich bin der Meinung, dass dies nicht der richtige Weg ist.
Wie gruppiere ich also tatsächlich alle 20 Zeilen und warte, bis sie fertig sind, bevor ich zu den nächsten 20 Zeilen übergehe. Dieses Skript wird dynamisch generiert, damit ich während der Generierung alles tun kann, was ich will, aber es muss NICHT benutze wget, es war nur ein Beispiel, also wird mir jede Lösung, die wget-spezifisch ist, nichts nützen.
wait
ist hier die richtige Antwort, aber Siewhile [ $(ps …
wären viel besser geschriebenwhile pkill -0 $KEYWORD…
- mit proctools ... das heißt, aus legitimen Gründen, um zu überprüfen, ob ein Prozess mit einem bestimmten Namen noch läuft.Antworten:
Verwenden Sie das
wait
eingebaute:Für das obige Beispiel würden 4 Prozesse
process1
...process4
im Hintergrund gestartet, und die Shell würde warten, bis diese abgeschlossen sind, bevor sie mit dem nächsten Satz beginnen.Aus dem GNU-Handbuch :
quelle
i=0; waitevery=4; for link in "${links[@]}"; do wget "$link" & (( i++%waitevery==0 )) && wait; done >/dev/null 2>&1
Siehe parallel . Die Syntax ähnelt der
xargs
, aber die Befehle werden parallel ausgeführt.quelle
wait
, da neue Jobs abgeschlossen werden müssen, während alte abgeschlossen sind, anstatt darauf zu warten, dass ein ganzer Stapel abgeschlossen ist, bevor mit dem nächsten begonnen wird.cat list_of_links.txt | parallel -j 4 wget {}
wodurch jeweils vierwget
Sekunden ausgeführt werden.parallel
.parallel --jobs 4 < list_of_commands.sh
Dabei ist list_of_commands.sh eine Datei mit einem einzelnen Befehl (z. B.wget LINK1
Notiz ohne&
) in jeder Zeile. Möglicherweise mussCTRL+Z
undbg
danach, um es im Hintergrund laufen zu lassen.In der Tat
xargs
können Befehle parallel für Sie ausgeführt werden. Dafür gibt es eine spezielle-P max_procs
Befehlszeilenoption. Sieheman xargs
.quelle
Sie können 20 Prozesse ausführen und den folgenden Befehl verwenden:
Ihr Skript wartet und fährt fort, wenn alle Hintergrundjobs abgeschlossen sind.
quelle