Андреас Вейтен зазначає, що якщо вам не потрібно повертатися з виклику (як у прикладі ОП), exec
достатньо просто зателефонувати через команду (відповідь @Stuart P. Bentley ). Інакше "традиційний" trap 'kill $CHILDPID' TERM
(відповідь @ cuonglm) - це початок, але wait
виклик насправді повертається після запуску обробника пастки, який все ще може бути до завершення дочірнього процесу. Тому бажаний "додатковий" дзвінок wait
(відповідь @ користувача1463361 ).
Хоча це вдосконалення, він все ще має стан гонки, що означає, що процес може ніколи не виходити (якщо тільки сигналізатор не намагається відправити сигнал 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