Мне нужно запускать несколько скриптов каждые несколько минут. Логика была сделана на PHP, и она отлично работает. Чтобы все было вместе, я сделал приведенный ниже сценарий bash, который также отлично работает.
#!/bin/bash
calculaDiff() {
DIFF=0
while [ "$DIFF" -eq "0" ]; do
DIFF=`php calculaDiff.php`
done;
}
# need to calculate pending diffs
calculaDiff
# main loop
while true; do
CAPTURA=`php capturaRelatorio.php`
if [ "$CAPTURA" -eq "0" ]; then
calculaDiff
fi
VERIFICA=`php verificaLimites.php`
done
Сценарий capturaRelatorio.php
в нем спит, потому что я могу обрабатывать его только каждые N минут. Он напечатает сообщение о том, что он спит S секунд, чтобы я мог его контролировать.
Если я вызову сценарий bash и нажму Ctrl+C в это время, пока он спит, он убивает скрипт bash, но не убивает вызываемый скрипт php. Я понимаю, что это другой процесс.
Итак, есть ли способ убить сценарий bash и каждого «ребенка»? Или мне следует использовать другой подход для запуска этих сценариев?
Из этого ответа: bash - Как убить все подпроцессы оболочки? - Переполнение стека.
Если вы заботитесь только об убийстве прямых детей, вы должны уметь делать
pkill -P $$
-P
говорит
-P, --parent ppid,...
Only match processes whose parent process ID is listed.
И $$
означает PID текущего процесса.
Если вам нужно убить дочерние процессы и любые процессы, которые они могут запускать (внуки и т. Д.), Вы должны иметь возможность использовать функцию, которая находится в другом ответе на этот вопрос:
kill_descendant_processes() {
local pid="$1"
local and_self="${2:-false}"
if children="$(pgrep -P "$pid")"; then
for child in $children; do
kill_descendant_processes "$child" true
done
fi
if [[ "$and_self" == true ]]; then
kill "$pid"
fi
}
Как это
kill_descendant_processes $$ true
Что убьет текущий процесс и всех потомков. Вы, вероятно, захотите вызвать это из обработчика прерываний. То есть при нажатии ctrl+c, ваш сценарий будет отправлен SIGINT
и вы можете поймать этот сигнал и обработать его. Например:
trap cleanup INT
cleanup() {
kill_descendant_processes $$ true
}
Вы можете обновить сценарий bash, чтобы перехватить ctrl + c:
trap control_c SIGINT
function control_c() {
echo "## Trapped CTRL-C"
ps -ef | grep php | grep -v grep | awk '{ print $2 }' > php.kill
for i in $(cat php.kill)
do
kill -9 $i > /dev/null
done
rm php.kill
}