Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a utility that has a nasty habit of going quiet and staying there, I already know how long into the process it does this so I am using timeout to fight this, but sometimes it does it before that time. Is there a tool similar to timeout that will kill the process if it stops directing output to stdout?

share|improve this question
add comment

2 Answers

up vote 7 down vote accepted

With zsh, you could do:

zmodload zsh/system
coproc your-command
while :; do
  sysread -t 10 -o 1 <&p && continue
  if (( $? == 4 )); then
    echo "Timeout" >&2
    kill $!
  fi
  break
done

The idea being to use the -t option of sysread to read from your-command output with a timeout.

Note that it makes your-command's output a pipe. It may be that your-command starts buffering its output when it doesn't go to a terminal, in which case you may find that it doesn't output anything in a while, but only because of that buffering, not because it's hung somehow.

You could work around that by using stdbuf -oL your-command to restore line-buffering (if your-command uses stdio) or use zpty instead of coproc to fake a terminal output.

With bash, you'd have to rely on dd and GNU timeout if available:

coproc your-command
while :; do
  timeout 10 dd bs=8192 count=1 2> /dev/null <&${COPROC[0]} && continue
  if (($? == 124)); then
    echo Timeout >&2
    kill "$!"
  fi
done

Instead of coproc, you could also use process substitution:

while :; do
  timeout 10 dd bs=8192 count=1 2> /dev/null <&3 && continue
  if (($? == 124)); then
    echo Timeout >&2
    kill "$!"
  fi
done 3< <(your-command)

(that won't work in zsh or ksh93 because $! doesn't contain the pid of your-command there).

share|improve this answer
1  
Hi! Thanks, Is it possible you could comment this so I can understand what this is doing? –  Benjojo Feb 17 at 11:17
add comment

I'd redirect STDOUT to a file and then use monit's timestamp testing to restart the process if the file's mtime is greater than a threshold.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.