Ich habe ein paar PNG-Bilder in einem Verzeichnis. Ich habe eine Anwendung namens pngout, mit der ich diese Bilder komprimiere. Diese Anwendung wird von einem Skript aufgerufen, das ich erstellt habe. Das Problem ist, dass dieses Skript eines nach dem anderen ausführt:
FILES=(./*.png)
for f in "${FILES[@]}"
do
echo "Processing $f file..."
# take action on each file. $f store current file name
./pngout -s0 $f R${f/\.\//}
done
Die Verarbeitung von jeweils nur einer Datei nimmt viel Zeit in Anspruch. Nach dem Ausführen dieser App sehe ich, dass die CPU nur 10% beträgt. So entdeckte ich, dass ich diese Dateien in 4 Stapel aufteilen, jeden Stapel in ein Verzeichnis stellen und 4 aus vier Terminalfenstern vier Prozesse auslösen kann, so dass ich vier Instanzen meines Skripts gleichzeitig habe, die diese Bilder und das Skript verarbeiten Job dauert 1/4 der Zeit.
Das zweite Problem ist, dass ich Zeit verloren habe, die Bilder und Stapel aufzuteilen und das Skript in vier Verzeichnisse zu kopieren, 4 Terminalfenster zu öffnen, bla bla ...
Wie geht das mit einem Skript, ohne etwas teilen zu müssen?
Ich meine zwei Dinge: Erstens, wie kann ich aus einem Bash-Skript einen Prozess in den Hintergrund abfeuern? (Fügen Sie einfach & zum Ende hinzu?) Zweitens: Wie stoppe ich das Senden von Aufgaben an den Hintergrund, nachdem ich die vierten Aufgaben gesendet habe, und setze das Skript so lange, bis die Aufgaben beendet sind? Ich meine, nur eine neue Aufgabe in den Hintergrund zu schicken, wenn eine Aufgabe endet und immer 4 Aufgaben gleichzeitig erledigt sind? Wenn ich das nicht tue, wird die Schleife zig Millionen von Aufgaben im Hintergrund auslösen und die CPU wird verstopfen.
quelle
Antworten:
Wenn Sie eine Kopie davon haben
xargs
, die die parallele Ausführung mit unterstützt-P
, können Sie dies einfach tunFür andere Ideen enthält das Wooledge Bash-Wiki einen Abschnitt im Artikel zum Prozessmanagement, in dem genau beschrieben wird, was Sie möchten.
quelle
pngout
Befehl kombiniert, den das OP ausführen wollte. Die Schlüsseloption ist-P 4
, die xargs anweist, bis zu 4 gleichzeitige Befehle zu verwenden.printf
hier eher eine Funktion als eine normale Funktion verwendet habenls .. | grep .. *.png
. Auch die vonxargs
Ihnen verwendeten Parameter (-0
und-I{}
) haben mich interessiert . Vielen Dank!ls
können nicht zum portablen und sicheren Parsen von Dateinamen verwendet werden . Die einzigen sicheren Zeichen zur Begrenzung von Dateinamen sind\0
und/
, da jedes andere Zeichen, einschließlich\n
, Teil des Dateinamens sein kann. Dieprintf
verwendet\0
, um Dateinamen zu begrenzen, und die-0
informiertxargs
darüber. Die-I{}
Tells werdenxargs
durch{}
das Argument ersetzt.Zusätzlich zu den bereits vorgeschlagenen Lösungen können Sie ein Makefile erstellen, in dem beschrieben wird, wie eine komprimierte Datei aus einer nicht komprimierten Datei erstellt und
make -j 4
4 Jobs gleichzeitig ausgeführt werden. Das Problem ist, dass Sie komprimierte und unkomprimierte Dateien unterschiedlich benennen oder in unterschiedlichen Verzeichnissen speichern müssen, da sonst das Schreiben einer vernünftigen make-Regel unmöglich ist.quelle
Wenn Sie GNU Parallel http://www.gnu.org/software/parallel/ installiert haben, können Sie dies tun:
Sie können GNU Parallel einfach installieren, indem Sie:
In den Introvideos zu GNU Parallel erfahren Sie mehr: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
quelle
So beantworten Sie Ihre beiden Fragen:
wait
Befehl können Sie die Shell auffordern, zu warten, bis alle Prozesse im Hintergrund abgeschlossen sind, bevor Sie fortfahren.Hier ist das Skript so geändert, dass
j
es die Anzahl der Hintergrundprozesse protokolliert. Wenn diesNB_CONCURRENT_PROCESSES
erreicht ist, wird das Skriptj
auf 0 zurückgesetzt und wartet, bis alle Hintergrundprozesse abgeschlossen sind, bevor die Ausführung fortgesetzt wird.quelle
$f
usw. (3) Verwendung[
für POSIX-kompatible Skripte, aber für reine Bash[[
wird immer bevorzugt. In diesem Fall((
ist für die Arithmetik besser geeignet.