
Я очень стараюсь понять, что я делаю не так и почему?
У меня есть launch.sh
скрипт, который запускает process.sh
.
запуск.sh
#!/bin/bash
while true; do
./process.sh
done
процесс.sh
#!/bin/bash
function signalHandler() {
for i in {1..2}; do
sleep 0.1s
echo "process.sh: cleanup $i"
done
exit 130
}
trap "signalHandler" "SIGINT"
while true; do
sleep 1s
done
когда я бегу
./launch.sh &
а затем убить его с помощью
kill -s SIGINT -$!
где $!
берет PID последней команды (launch.sh) и минус посылает сигнал всем дочерним процессам, затем launch.sh
продолжает. Почему?
Я ожидал следующего поведения (согласно этому блогу)Сигнал и Баш) :
оболочка A со скриптом, launch.sh
работающим в фоновом режиме, прерывается, Bash ждет process.sh
завершения. Поскольку process.sh
происходит аварийный выход (выход 130) из-за обработчика сигнала в process.sh
, оболочка A должна завершиться. Почему этого не происходит?
Если статус этого потомка указывает на то, что он завершился ненормально из-за этого сигнала, оболочка очищается, удаляет свой обработчик сигнала и снова завершает себя, чтобы вызвать действие ОС по умолчанию (ненормальный выход). В качестве альтернативы она запускает обработчик сигнала скрипта, установленный с помощью trap, и продолжает работу.
решение1
Во-первых, exit 130
это не ненормальный выход. Это нормальный выход, со статусом выхода 130. Как видно изman 3 wait
(POSIX):
If the information pointed to by stat_loc was stored by a call to
waitpid() that specified the WUNTRACED and WCONTINUED flags,
exactly one of the macros WIFEXITED(*stat_loc), WIFSIGNALED(*stat_loc),
WIFSTOPPED(*stat_loc), and WIFCONTINUED(*stat_loc) shall evaluate to
a non-zero value.
WIFEXITED
проверяет нормальный выход, и WIFSIGNALLED
является завершением из-за неперехваченного сигнала. Поскольку они являются взаимоисключающими, exit 130
является нормальным.
Тот факт, что при завершении процесса по сигналу SIGINT код выхода равен 130, объясняется тем, что bash устанавливает его равным 130 за пределами процесса, поскольку он обнаружил выход по сигналу SIGINT:Почему bash устанавливает $? (статус выхода) в ненулевое значение при нажатии Ctrl-C или Ctrl-Z?
Во-вторых, процесс, который обрабатывает SIGINT и затем умирает, должен убить себя с помощью SIGINT. Вики Грега (отличный ресурс для shell-материалов) естьзаметка по этому поводу:
Если вы решили настроить обработчик для SIGINT (вместо использования ловушки EXIT), вы должны знать, что процесс, который завершается в ответ на SIGINT, долженубить себя с помощью SIGINTа не просто выйти, чтобы не создавать проблем для вызывающего. Таким образом:
trap 'rm -f "$tempfile"; trap - INT; kill -INT $$' INT
Теперь, если вы изменили exit 130
на:
trap - INT
kill -INT $$
Вы увидите ожидаемое поведение.