Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bash `read -t` doesn't work on pipe

Tags:

linux

bash

shell

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
like image 640
yuanjianpeng Avatar asked Oct 30 '22 12:10

yuanjianpeng


2 Answers

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)

like image 89
xhienne Avatar answered Nov 02 '22 22:11

xhienne


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

like image 34
P.P Avatar answered Nov 02 '22 22:11

P.P