При работе с фоновыми процессами в скриптах часто возникает два вопроса:
1. Как реагировать на завершение первого из них, не дожидаясь всех?
2. Как корректно снять всю пачку, если что-то пошло не так?
В Bash на этот случай имеется удобный механизм:
wait -n и управление группами процессов.▪️ Проблема: несколько фоновых задач. Допустим, мы запускаем несколько параллельных процессов:
#!/bin/bash
long_task_1 &
long_task_2 &
long_task_3 &
Обычно wait ждет завершения всех процессов. Но что если нужно отреагировать на первый фейл или отменить остальных после успешной задачи?
Решение: wait -n. Команда
wait -n ждет завершения любого из фоновых процессов и возвращает его код выхода. Как пример: запускаем 3 задачи, как только одна успешно завершилась - гасим остальные:
#!/bin/bash
cmd1 & p1=$!
cmd2 & p2=$!
cmd3 & p3=$!
while true; do
if wait -n; then
echo "Одна из задач завершилась успешно, убиваем остальные..."
kill $p1 $p2 $p3 2>/dev/null
break
fi
done
▪️ Kill group: гасим всю пачку. У kill есть прием: если передать отрицательный PID, сигнал уйдет всей группе процессов.
# запустить группу
( cmd1 & cmd2 & cmd3 & wait ) &
# сохранить PID группы
PGID=$!
# ... позже убить всех одним движением:
kill -- -$PGID
Это удобно, если внутри группы запускаются дочерние процессы, которые обычный
kill $PID не заденет.▪️ Комбо. Представим сценарий: несколько загрузчиков качают один и тот же файл из разных зеркал. Как только первый скачал успешно - убиваем остальных.
#!/bin/bash
(
curl -s -O http://mirror1/file.iso &
curl -s -O http://mirror2/file.iso &
curl -s -O http://mirror3/file.iso &
wait -n # ждем первый завершившийся процесс
kill -- -$$ # убиваем всю группу (все ещё живые curl)
) &
wait
echo "Файл получен!"
BashTex 📱 #bash #utils