Вот попытка избежать попытки завершить процесс после того, как он уже завершился, что уменьшает вероятность уничтожения другого процесса с тем же идентификатором процесса (хотя, вероятно, невозможно полностью избежать такого рода ошибок).
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
.