Вот попытка избежать уничтожения процесса после того, как он уже завершился, что снижает вероятность уничтожения другого процесса с тем же идентификатором процесса (хотя, вероятно, невозможно полностью избежать такого рода ошибок).
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
)
}
Используйте как run_with_timeout 3 sleep 10000
, который запускает sleep 10000
, но завершает его через 3 секунды.
Это похоже на другие ответы, которые используют фоновый процесс тайм-аута для уничтожения дочернего процесса после задержки.Я думаю, что это почти то же самое, что расширенный ответ Дэна (https://stackoverflow.com/a/5161274/1351983),, за исключением того, что оболочка тайм-аута не будет уничтожена, если она уже закончилась.
После того, как эта программа закончилась, все еще будет несколькозапаздывающие "спящие" процессы запущены, но они должны быть безвредными.
Это может быть лучшим решением, чем мой другой ответ, поскольку он не использует функцию непереносимой оболочки read -t
и не использует pgrep
.