Вчера написал простенькую, но (для меня) уже вполне функциональную запускалку задач из bash-скриптов. Её предназначение простое: брать из стандартного потока ввода текст задачи (на том же bash) и запускать её «в фоне». Отличие от простого «амперсанда» простое, но существенное: количество одновременно запущенных таким образом задач должно быть меньше или равно количеству процессорных ядер. Если требуется запустить задачу тогда, когда все ядра уже заняты ранее запущенными ones, моя функция будет ждать освобождения хотя бы одного из ядер.
Собственно, актуальный текст данной функции можно будет всегда найти на github'е (https://github.com/DRVTiny/bash4-debug-infra), а сюда скопирую текущую версию просто для того, чтобы было понятно, о чём речь и как э
то реализовано.
Если есть идеи, как реализовать чистку списка запущенных задач без дорогостоящего полинга - с использованием какого-нибудь SIGCHLD, например, - буду очень признателен.
declare -i CPU_KERNELS=$(fgrep processor /proc/cpuinfo | wc -l)
declare -A TASKS_QUEUE=()
unset wait4_cpu_free push_task
rotate_tq () {
declare -i taskPID flTaskGone=0
for taskPID in ${!TASKS_QUEUE[@]}; do
[[ -f /proc/$taskPID/cmdline && ${TASKS_QUEUE[$taskPID]} == "$(</proc/$taskPID/cmdline)" ]] 2>/dev/null || {
flTaskGone=1
unset TASKS_QUEUE[$taskPID]
}
done
return $flTaskGone
}
wait4_cpu_free () {
while :; do
rotate_tq || break
done
return 0
}
push_task () {
local taskPID
if (( ${#TASKS_QUEUE[@]} )); then
rotate_tq
(( ${#TASKS_QUEUE[@]} >= CPU_KERNELS )) && wait4_cpu_free
fi
eval "$(cat -)" &
taskPID=$!
[[ -f /proc/$taskPID/cmdline ]] && \
TASKS_QUEUE[$taskPID]="$(</proc/$taskPID/cmdline)"
return $?
}