Shell – Read data from a pipe for a certain amount of time (in seconds)

pipeshellstdout

Is there an easy way to create a pipe that only lasts for a given amount of wall time?

I want to be able to take a "snapshot" of what's being written STDOUT for a period of time (rather than bytes or lines). Something like

tail -f /var/log/whatever.log | pipe_for_seconds 10 > ./10_second_sample_of_log

I'm using BASH, but if this is dramatically easier in some other shell, I'd like to hear about it.

Best Answer

Gnu coreutils since version 7.0 has a timeout command:

timeout 10 tail -f /var/log/whatever.log 

If you really need a pipe to timeout for some slightly different procedure, then pipe into timeout:

tail -f /var/log/whatever.log | timeout 10 cat > ./10_second_sample_of_log

Note though that killing some arbitrary part of a pipeline may cause problems due to buffering, depending on signals and program behaviour (this question covers related issues: Turn off buffering in pipe ). It will usually change the exit code of the process too.

If you don't have (a recent) coreutils, this simple timeout program also works well http://www.unixlabplus.com/unix-prog/timeout/timeout.html or the perl approach:

tail -f /var/log/whatever.log | perl -n -e 'BEGIN{alarm 10; $|=1}; print;'

(Note the $|=1 turns off output buffering, this is to prevent loss of output in the pipeline, as referred to above.)

The (slightly ancient) Netpipes package also has a timelimit command (which you can still find on some Linux systems).

This similar question has a few more options: How to introduce timeout for shell scripting?