Я только что читал похожие вопросы о сборе PID и последующем уничтожении их всех в конце скрипта - проблема заключается в том, что PID для завершенного процесса может быть переработан и повторно использован в новом процессе до того, как ваш сценарий завершится, а затем вы можете убить новый (случайный) процесс.
Вы можете использовать управление заданиями bash, чтобы завершать только процессы, запущенные в сценарии, с помощью прерывания и задания %n, подсчитывая максимальное количество заданий, которые могут быть запущены (только 3 в этот пример):
#!/bin/bash
#trap 'kill %1 %2 %3' 0 # 0 or EXIT are equivalent
#trap 'kill %1 %2 %3' EXIT # or use {1..n} as below
trap 'kill %{1..3}' EXIT
sleep 33 &
sleep 33 &
sleep 33 &
echo processes are running, ctrl-c the next sleep
sleep 66
echo this line will never be executed
Любые дополнительные «убийства» несуществующих спецификаций заданий, которые уже завершились, приводят только к сообщению об ошибке, они не уничтожат никакие другие новые/случайные процессы.
Вот немного другой способ убить всю группу процессов вашего скрипта. Но если управление заданиями вашего скрипта/оболочки не настроено, то оно может наследовать PPID от своего родителя... но без управления заданиями описанное выше тоже не сработает.
Разница в том, что эта команда kill для trap использует PID bash, поскольку он становится PGID для новых процессов:
trap 'kill -- -$$' EXIT
См. этот связанный Q или здесь, где Йоханнес 'fish' Ziemke ловит SIGINT и SIGTERM и использует setsid
для «уничтожения всей группы процессов в новой группе процессов, чтобы мы не рисковали убить самих себя.»)