Попытка закрыть все дочерние процессы, когда я прерываю мой скрипт - PullRequest
0 голосов
/ 30 декабря 2018

Я написал скрипт 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 ]

0 голосов
/ 30 декабря 2018

в 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

0 голосов
/ 31 декабря 2018

Я нашел решение, используя pkill.Этот пример также имеет дело со многими дочерними процессами.

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

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

0 голосов
/ 30 декабря 2018

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

pkill -TERM -P <your_parent_id_here>
...