Alle Beispiele sind in bash geschrieben, funktionieren aber (mit minimalen Änderungen) in ksh. Csh verfügt auch über eine Hintergrundfunktion für das Prozessmanagement, sodass ein ähnlicher Ansatz verwendet werden kann.
JOBKONTROLLE
Dies ist der Name des Abschnitts in man bash, in dem die Details beschrieben werden, falls Sie gerne man lesen. Wir verwenden die folgenden einfachen Funktionen:
Befehl & - führt einen Befehl in den Hintergrund
Jobs - druckt eine Liste von Hintergrund - Befehle
Ein einfaches Beispiel , das keine nützliche Wirkung tut. Zahlen werden aus der Datei test.txt gelesen und 3 Prozesse werden parallel gestartet, die für die entsprechende Anzahl von Sekunden in den Ruhezustand versetzt werden. Alle drei Sekunden wird die Anzahl der ausgeführten Prozesse überprüft, und wenn weniger als drei vorhanden sind, wird ein neuer gestartet. Der Start des Hintergrundprozesses wurde in eine separate Funktion mytask verschoben, Sie können ihn jedoch direkt in einer Schleife starten.
test.sh
#!/bin/bash
NJOBS=3 ; export NJOBS
function mytask () {
echo sleeping for $1
sleep $1
}
for i in $( cat test.txt )
do
while [ $(jobs | wc -l ) -ge $NJOBS ]
do
sleep 3
done
echo executing task for $i
mytask $i &
done
echo waiting for $( jobs | wc -l ) jobs to complete
wait
Eingabedaten:
test.txt
60
50
30
21
12
13
50
30
21
12
13
Achten Sie auf das Warten nach der Schleife. Der Befehl wartet, bis die im Hintergrund ausgeführten Prozesse abgeschlossen sind. Ohne diese Option wird das Skript sofort nach Ende der Schleife beendet und alle Hintergrundprozesse werden unterbrochen. Vielleicht wird dieses Warten im berühmten Mem "Oh, warte !!!" erwähnt.
Hintergrundprozesse beenden
Wenn Sie das Skript mit Strg-C unterbrechen, wird es bei allen Hintergrundprozessen beendet. Alle im Terminal ausgeführten Prozesse empfangen Signale von der Tastatur (z. B. SIGINT). Wenn das Skript mit dem Befehl kill von einem anderen Terminal beendet wird, werden die Hintergrundprozesse bis zur Beendigung ausgeführt, und Sie müssen sich daran erinnern.
Spoiler Header
user@somehost ~/tmp2 $ ps -ef | grep -E «test|sleep»
user 1363 775 0 12:31 pts/5 00:00:00 ./test.sh
user 1368 1363 0 12:31 pts/5 00:00:00 ./test.sh
user 1370 1368 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 60
user 1373 1363 0 12:31 pts/5 00:00:00 ./test.sh
user 1375 1373 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 50
user 1378 1363 0 12:31 pts/5 00:00:00 ./test.sh
user 1382 1378 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 30
user 1387 1363 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 3
user 1389 556 0 12:31 pts/2 00:00:00 grep --colour=auto -E test|sleep
user@somehost ~/tmp2 $ kill 1363
user@somehost ~/tmp2 $ ps -ef | grep -E «test|sleep»
user 1368 1 0 12:31 pts/5 00:00:00 ./test.sh
user 1370 1368 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 60
user 1373 1 0 12:31 pts/5 00:00:00 ./test.sh
user 1375 1373 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 50
user 1378 1 0 12:31 pts/5 00:00:00 ./test.sh
user 1382 1378 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 30
user 1399 556 0 12:32 pts/2 00:00:00 grep --colour=auto -E test|sleep
user 1363 775 0 12:31 pts/5 00:00:00 ./test.sh
user 1368 1363 0 12:31 pts/5 00:00:00 ./test.sh
user 1370 1368 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 60
user 1373 1363 0 12:31 pts/5 00:00:00 ./test.sh
user 1375 1373 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 50
user 1378 1363 0 12:31 pts/5 00:00:00 ./test.sh
user 1382 1378 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 30
user 1387 1363 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 3
user 1389 556 0 12:31 pts/2 00:00:00 grep --colour=auto -E test|sleep
user@somehost ~/tmp2 $ kill 1363
user@somehost ~/tmp2 $ ps -ef | grep -E «test|sleep»
user 1368 1 0 12:31 pts/5 00:00:00 ./test.sh
user 1370 1368 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 60
user 1373 1 0 12:31 pts/5 00:00:00 ./test.sh
user 1375 1373 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 50
user 1378 1 0 12:31 pts/5 00:00:00 ./test.sh
user 1382 1378 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 30
user 1399 556 0 12:32 pts/2 00:00:00 grep --colour=auto -E test|sleep
Diese Situation kann durch Abfangen der erforderlichen Signale behoben werden, für die wir am Anfang des Skripts einen Handler hinzufügen:
Falle
function pids_recursive() {
cpids=`pgrep -P $1|xargs`
echo $cpids
for cpid in $cpids;
do
pids_recursive $cpid
done
}
function kill_me () {
kill -9 $( pids_recursive $$ | xargs )
exit 1
}
#
#trap 'echo trap SIGINT; kill_me ' SIGINT
trap 'echo trap SIGTERM; kill_me' SIGTERM
kill -L zeigt eine Liste der vorhandenen Signale an. Bei Bedarf können Sie Handler für die erforderlichen hinzufügen.