Может быть полезно включить управление заданиями в скрипте для установки ловушек
SIGCHLD. Раздел «УПРАВЛЕНИЕ ЗАДАНИЕМ» в руководстве гласит:
Оболочка обучается сразу, когда задание меняет состояние. Обычно,
Bash ждет, пока он собирается напечатать приглашение, прежде чем сообщать
изменения в статусе задания, чтобы не прерывать любой другой вывод. Если
опция -b для встроенной команды set включена, отчеты bash
такие изменения сразу. Любая ловушка на SIGCHLD выполняется для каждого
выходящий ребенок.
(ударение мое)
В качестве примера рассмотрим следующий скрипт:
dualbus@debian:~$ cat children.bash
#!/bin/bash
set -m
count=0 limit=3
trap 'counter && { job & }' CHLD
job() {
local amount=$((RANDOM % 8))
echo "sleeping $amount seconds"
sleep "$amount"
}
counter() {
((count++ < limit))
}
counter && { job & }
wait
dualbus@debian:~$ chmod +x children.bash
dualbus@debian:~$ ./children.bash
sleeping 6 seconds
sleeping 0 seconds
sleeping 7 seconds
Примечание. Похоже, что перехват CHLD нарушен с bash 4.3
В bash 4.3 вы можете использовать wait -n для достижения того же самого,
хотя:
dualbus@debian:~$ cat waitn.bash
#!/home/dualbus/local/bin/bash
count=0 limit=3
trap 'kill "$pid"; exit' INT
job() {
local amount=$((RANDOM % 8))
echo "sleeping $amount seconds"
sleep "$amount"
}
for ((i=0; i<limit; i++)); do
((i>0)) && wait -n; job & pid=$!
done
dualbus@debian:~$ chmod +x waitn.bash
dualbus@debian:~$ ./waitn.bash
sleeping 3 seconds
sleeping 0 seconds
sleeping 5 seconds
Можно утверждать, что есть другие способы сделать это в более
переносным способом, то есть без CHLD или wait -n:
dualbus@debian:~$ cat portable.sh
#!/bin/sh
count=0 limit=3
trap 'counter && { brand; job & }; wait' USR1
unset RANDOM; rseed=123459876$$
brand() {
[ "$rseed" -eq 0 ] && rseed=123459876
h=$((rseed / 127773))
l=$((rseed % 127773))
rseed=$((16807 * l - 2836 * h))
RANDOM=$((rseed & 32767))
}
job() {
amount=$((RANDOM % 8))
echo "sleeping $amount seconds"
sleep "$amount"
kill -USR1 "$$"
}
counter() {
[ "$count" -lt "$limit" ]; ret=$?
count=$((count+1))
return "$ret"
}
counter && { brand; job & }
wait
dualbus@debian:~$ chmod +x portable.sh
dualbus@debian:~$ ./portable.sh
sleeping 2 seconds
sleeping 5 seconds
sleeping 6 seconds
Итак, в заключение установите -m , а не , что полезно в сценариях, так как
единственная интересная особенность, которую он приносит в сценарии, это возможность
работать с SIGCHLD. И есть другие способы добиться того же
либо более короткий (wait -n), либо более переносимый (отправка сигналов самостоятельно).