Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why `read -t` is not timing out in bash on RHEL?

Tags:

linux

bash

rhel5

Why read -t doesn't time out when reading from pipe on RHEL5 or RHEL6?

Here is my example which doesn't timeout on my RHEL boxes wile reading from the pipe:

tail -f logfile.log | grep 'something' | read -t 3 variable

If I'm correct read -t 3 should timeout after 3 seconds?

Many thanks in advance.

Chris

GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
like image 654
Chris Avatar asked May 14 '13 15:05

Chris


2 Answers

The solution given by chepner should work.

An explanation why your version doesn't is simple: When you construct a pipe like yours, the data flows through the pipe from the left to the right. When your read times out however, the programs on the left side will keep running until they notice that the pipe is broken, and that happens only when they try to write to the pipe.

A simple example is this:

cat | sleep 5

After five seconds the pipe will be broken because sleep will exit, but cat will nevertheless keep running until you press return.

In your case that means, until grep produces a result, your command will keep running despite the timeout.

like image 53
mata Avatar answered Oct 31 '22 16:10

mata


While not a direct answer to your specific question, you will need to run something like

read -t 3 variable < <( tail -f logfile.log | grep "something" )

in order for the newly set value of variable to be visible after the pipeline completes. See if this times out as expected.


Since you are simply using read as a way of exiting the pipeline after a fixed amount of time, you don't have to worry about the scope of variable. However, grep may find a match without printing it within your timeout due to its own internal buffering. You can disable that (with GNU grep, at least), using the --line-buffered option:

tail -f logfile.log | grep --line-buffered "something" | read -t 3

Another option, if available, is the timeout command as a replacement for the read:

timeout 3 tail -f logfile.log | grep -q --line-buffered "something"

Here, we kill tail after 3 seconds, and use the exit status of grep in the usual way.

like image 42
chepner Avatar answered Oct 31 '22 16:10

chepner