A very simple way to demonstrate this is to run
mkfifo /tmp/a
read -t 1 a < /tmp/a
the read never return.
Bash Manual says: This option is only effective if read is reading input from a terminal, pipe, or other special file; it has no effect when reading from regular files
but /tmp/a is a pipe, output of ls is
ls -l /tmp/a
prw-r--r-- 1 root root 0 Feb 4 22:18 /tmp/a
the bash version is:
GNU bash, version 4.3.46(1)-release (x86_64-pc-linux-gnu) Copyright (C) 2013 Free Software Foundation, Inc.
the OS is:
Ubuntu 16.04.1 LTS
See my detailed answer on unix.stackexchange.com .
TL;DR: your -t
flag does not seem to work because read
is even not executed since this is your shell that is blocked , not your command.
Before executing your read
command, bash
tries to open /tmp/a
and this is a blocking operation. Opening a named pipe for reading blocks until someone else opens it for writing.
You can check this with an erroneous command:
mkfifo my_fifo
a_command_that_does_not_exist < my_fifo
(your shell is blocked until someone opens my_fifo
for writing, and only then will it tell you command not found
)
Solution: read -t 1 a <> /tmp/a
(more on unix.stackexchange.com )
When you read from the pipe, there needs to be someone writing to the pipe as well. "pipe" is just a communication mechanism. It doesn't "generate" any input by itself; it'll just pass the its input to its output end. It appears that you are just reading but there's no one writing to /tmp/a
.
When read
waits for input do echo hello > /tmp/a
from another terminal and you'll see that read
returns and a
has the value "hello".
Read about pipes in detail here: http://man7.org/linux/man-pages/man7/pipe.7.html
I just confirm that timeout does not work on a pipe stream because of a race condition. The sub-shell is executing the read
statement before the input is made available.
Running:
echo 'hello' | {
if read -t0
then echo 'Input is available.'
else echo 'No input available on the FD.'
fi
}
Outputs:
No input available on the FD.
Introducing a dummy :
NOP command ( or wait 1
) before the read
, can change the deal:
echo 'hello' | {
:
if read -t0
then echo 'Input is available.'
else echo 'No input available on the FD.'
fi
}
Then suddenly:
Input is available.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.