I recently had to find a solution to killing a process which wouldn't finish. This is what I managed to come up with:
(mycommand args) & pid=$!
sleep 1000 && kill -INT $pid
Should be self explanatory. Runs your command and grabs the process ID. Kills it after the timeout.
My specific use was for scanning DVB-S:
(w_scan -a 7 -E 0 -f s -c $1 -s $2 -o 7 -x >$tunefile) & pid=$!
sleep 1500 && kill -INT $pid
The w_scan command would never finish and would loop forever scanning the same frequencies.
EDIT: You can check if the pid is still running: This will at least allow your script to act accordingly.
if ps -p $id > /dev/null
then
: active
else
: inactive
fi
EDIT2: I just ran a quick script using ffmpeg to convert from one format to another. My test converted an mkv (2Gb file) to mp4. This would normally take a very long time but I wanted to get it working with just 10 seconds and then exits it.
It wasn't much, but the initial test ran fine.
film=/home/wlgfx/longfilm.mkv
output=/home/wlgfx/longfilm.mp4
(ffmpeg -i $film -y -vcodec copy -acodec copy $output) & pid=$!
#for i in 'seq 1 10' # 10 seconds
#do
# sleep 1
if wait $pid; then echo "$pid success $?"
else echo "$pid fail $?"
fi
#done
Exit status is $?
I also noticed that ffmpeg only took about 5 seconds to convert the 2Gb file into another container. I'll make an update so that it transcodes and I'll make further changes to the script to reflect them so that it will kill the process after x seconds.
Currently, I'm looking here: https://stackoverflow.com/a/1570351/2979092
EDIT4: By running a separate timeout process, this time, if your process exits properly within the timeout, then the successful exit code will be displayed. Otherwise it will terminate the hanging process.
film=/home/wlgfx/longfilm.mkv
output=/home/wlgfx/longfilm.mp4
while : ; do
#(ffmpeg -i $film -y -vcodec mpeg2video -acodec copy $output) & pid=$!
(ffmpeg -i $film -y -vcodec copy -acodec copy $output) & pid=$!
(sleep 25 ; echo 'timeout'; kill $pid) & killpid=$!
wait $pid # will get status if completed successfully
status=$?
(kill -0 $killpid && kill $killpid) || true
[[ $status == 0 ]] || break
done