Попытка закрыть все дочерние процессы, когда я прерываю мой скрипт

Я написал скрипт bash для проведения некоторых тестов в моей системе. Тесты проходят в фоновом режиме и параллельно. Тесты могут занять много времени, и иногда я могу прервать тестирование на полпути.

Если я удерживаю Control+C, то он прерывает родительский сценарий, но оставляет работающих детей. Я хочу сделать так, чтобы я мог нажать Control+C или иным образом выйти и затем убить все дочерние процессы, работающие в фоновом режиме. У меня есть немного кода, который выполняет эту работу, если я запускаю фоновые задания прямо из терминала, но в моем сценарии это не работает.

У меня есть минимальный рабочий пример.

Я пытался использовать trap в сочетании с pgrep -P $$.

#!/bin/bash

trap 'kill -n 2 $(pgrep -P $$)' 2
sleep 10 &
wait

Я надеялся, что при нажатии control+c (SIGINT) будет убито все, что запускается скрипт, но на самом деле он говорит:

./breakTest.sh: line 1: kill: (3220) - No such process

Это число меняется, но, похоже, оно не относится ни к каким запущенным процессам, поэтому я не знаю, откуда оно.

Я предполагаю, что если содержимое команды trap будет оцениваться там, где происходит команда trap, то это может объяснить результат. Pid 3220 может быть для самого pgrep.

Буду признателен за понимание

Спасибо

3 ответа

Я нашел решение с помощью pkill. Этот пример также имеет дело со многими дочерними процессами.

#!/bin/bash
trap 'pkill -P $$' SIGINT SIGTERM
for i in {1..10}; do
   sleep 10 &
done
wait

Похоже, это элегантно убивает все дочерние процессы. Хотя я не совсем понимаю, в чем проблема с моим исходным кодом, кроме отправки правильного сигнала.

В Bash всякий раз, когда вы используете & после команды она помещает эту команду в качестве фонового задания (эти фоновые задания называются job_spec), которое увеличивается на единицу до тех пор, пока вы не завершите сеанс терминала. Вы можете использовать jobs команда, чтобы получить список запущенных фоновых заданий. Для работы с этой работой вы должны использовать % с идентификатором работы. jobs Команда также принимает другие параметры, такие как jobs -p чтобы увидеть все процессы процессов, jobs -p %JOB_SPEC чтобы увидеть процесс идентификации этой конкретной работы.

#!/usr/bin/env bash

trap 'kill -9 %1' 2

sleep 10 &

wait

или же

#!/usr/bin/env bash

trap 'kill -9 $(jobs -p %1)' 2

sleep 10 &

wait

Я реализовал что-то вроде этого несколько лет назад, вы можете взглянуть на это async bash

Вы можете попробовать что-то вроде следующего:

pkill -TERM -P <your_parent_id_here>
Другие вопросы по тегам