Ось спроба, яка намагається уникнути вбивства процесу після його завершення, що зменшує ймовірність вбити ще один процес із тим самим ідентифікатором процесу (хоча, мабуть, неможливо повністю уникнути подібної помилки).
run_with_timeout ()
{
t=$1
shift
echo "running \"$*\" with timeout $t"
(
# first, run process in background
(exec sh -c "$*") &
pid=$!
echo $pid
# the timeout shell
(sleep $t ; echo timeout) &
waiter=$!
echo $waiter
# finally, allow process to end naturally
wait $pid
echo $?
) \
| (read pid
read waiter
if test $waiter != timeout ; then
read status
else
status=timeout
fi
# if we timed out, kill the process
if test $status = timeout ; then
kill $pid
exit 99
else
# if the program exited normally, kill the waiting shell
kill $waiter
exit $status
fi
)
}
Використовуйте Like run_with_timeout 3 sleep 10000
, який працює, sleep 10000
але закінчується через 3 секунди.
Це подібно до інших відповідей, які використовують процес очікування в фоновому режимі, щоб убити процес дитини після затримки. Я думаю, це майже те саме, що розширена відповідь Дена ( https://stackoverflow.com/a/5161274/1351983 ), за винятком того, що оболонка тайм-аута не буде вбита, якщо вона вже закінчилася.
Після закінчення цієї програми ще буде кілька затяжних процесів "сну", але вони повинні бути нешкідливими.
Це може бути кращим рішенням, ніж моя інша відповідь, оскільки вона не використовує функцію не портативної оболонки read -t
і не використовує pgrep
.