Während Sie dies richtig machen bash es wahrscheinlich unmöglich ist, , können Sie ein Semi-Recht ziemlich einfach machen. bstarkgab eine faire Annäherung an das Recht, aber seine hat die folgenden Mängel:
- Wortaufteilung: Sie können keine Jobs übergeben, die in ihren Argumenten eines der folgenden Zeichen verwenden: Leerzeichen, Tabulatoren, Zeilenumbrüche, Sterne, Fragezeichen. Wenn Sie dies tun, werden die Dinge möglicherweise unerwartet kaputt gehen.
- Es hängt vom Rest Ihres Skripts ab, nichts im Hintergrund zu haben. Wenn Sie dies tun oder später dem Skript etwas hinzufügen, das im Hintergrund gesendet wird, weil Sie vergessen haben, dass Sie aufgrund seines Snippets keine Jobs im Hintergrund verwenden dürfen, werden die Dinge kaputt gehen.
Eine andere Annäherung, die diese Mängel nicht aufweist, ist die folgende:
scheduleAll() {
local job i=0 max=4 pids=()
for job; do
(( ++i % max == 0 )) && {
wait "${pids[@]}"
pids=()
}
bash -c "$job" & pids+=("$!")
done
wait "${pids[@]}"
}
Beachten Sie, dass dieser leicht anpassbar ist, um auch den Beendigungscode jedes Jobs am Ende zu überprüfen, damit Sie den Benutzer warnen können, wenn ein Job fehlschlägt, oder einen Beendigungscode für festlegen können scheduleAll die Anzahl der fehlgeschlagenen Jobs .
Das Problem mit diesem Code ist genau das:
- Es plant vier (in diesem Fall) Jobs gleichzeitig und wartet dann, bis alle vier beendet sind. Einige werden möglicherweise früher als andere ausgeführt, wodurch der nächste Stapel von vier Jobs wartet, bis der längste des vorherigen Stapels abgeschlossen ist.
Eine Lösung, die sich um dieses letzte Problem kümmert, müsste verwenden, kill -0um abzufragen, ob einer der Prozesse anstelle des verschwunden ist, waitund den nächsten Job planen. Dies führt jedoch zu einem kleinen neuen Problem: Sie haben eine Race-Bedingung zwischen dem Beenden eines Jobs und der kill -0Überprüfung, ob es beendet ist. Wenn der Job beendet wurde und gleichzeitig ein anderer Prozess auf Ihrem System gestartet wird, wird eine zufällige PID verwendet, die zufällig die des gerade beendeten Jobs istkill -0 nicht bemerkt und die Dinge werden erneut unterbrochen.
Eine perfekte Lösung ist in nicht möglich bash.