Aqui está uma tentativa que tenta evitar matar um processo depois que ele já saiu, o que reduz a chance de matar outro processo com o mesmo ID de processo (embora seja provavelmente impossível evitar completamente esse tipo de erro).
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
)
}
Use like run_with_timeout 3 sleep 10000
, que roda sleep 10000
mas termina após 3 segundos.
Isso é como outras respostas que usam um processo de tempo limite em segundo plano para interromper o processo filho após um atraso. Eu acho que isso é quase o mesmo que a resposta estendida de Dan ( https://stackoverflow.com/a/5161274/1351983 ), exceto que o shell de tempo limite não será eliminado se já tiver terminado.
Após a conclusão desse programa, ainda haverá alguns processos de "suspensão" remanescentes em execução, mas eles devem ser inofensivos.
Essa pode ser uma solução melhor do que minha outra resposta, pois não usa o recurso de shell não portátil read -t
e não pgrep
.