Андреас Вайтен отмечает, что если вам не нужно возвращаться из вызова (как в примере с OP), достаточно просто вызвать exec
команду ( ответ @Stuart P. Bentley ). В противном случае «традиционный» trap 'kill $CHILDPID' TERM
(ответ @ cuonglm) является началом, но wait
вызов фактически возвращается после выполнения обработчика прерываний, который может быть еще до фактического завершения дочернего процесса. Поэтому wait
рекомендуется «дополнительный» вызов ( ответ @ user1463361 ).
Несмотря на то, что это улучшение, у него все еще есть состояние гонки, что означает, что процесс может никогда не завершиться (если сигнализатор не попытается отправить сигнал TERM). Окно уязвимости находится между регистрацией обработчика ловушек и записью PID ребенка.
Следующее устраняет эту уязвимость (упаковано в функции для повторного использования).
prep_term()
{
unset term_child_pid
unset term_kill_needed
trap 'handle_term' TERM INT
}
handle_term()
{
if [ "${term_child_pid}" ]; then
kill -TERM "${term_child_pid}" 2>/dev/null
else
term_kill_needed="yes"
fi
}
wait_term()
{
term_child_pid=$!
if [ "${term_kill_needed}" ]; then
kill -TERM "${term_child_pid}" 2>/dev/null
fi
wait ${term_child_pid}
trap - TERM INT
wait ${term_child_pid}
}
# EXAMPLE USAGE
prep_term
/bin/something &
wait_term