Bash read -r -N skips some input

This line writes "foo", sleeps, and then writes "bla":

echo "woo"; sleep 2; echo "bla" 

I am trying to read the entire output of this in two consecutive read commands:

 (echo "woo"; sleep 2; echo "bla") 1> \ >(IFS=""; read -t 0.1 -r -N 10; \ echo "exit code: $? reply: $REPLY"; \ sleep 5; \ read -t 0.1 -r -N 10; \ echo "exit code: $? reply: $REPLY") 

First prints read:

exit code: 142 answer:

which is expected since 142 is a timeout, and I called read with -t 0.1. But the second reads the prints:

exit code: 1 answer: bla

Question: where to "go" ??

If I remove sleep 2 from the output line, everything works as expected - it reads / prints the entire sequence "woo \ nbla" on first reading and returns 1 (EOF).

The problem is reproduced with any dream, no matter how short it may be. It also doesn't matter if I use a channel to redirect output instead of> 1. This is Ubuntu.

Edit: I want to read into the buffer of N characters and read the input as is, without breaking words into metrics. Therefore, -N and IFS = "".

Edit: This is an example of a toy demonstrating a common problem. What I'm trying to do is implement a smarter version of tee in bash: it should behave like tee, except that it has to wait for the I / O process to complete, then flush its buffers and exit. A real tee hangs endlessly if the I / O process starts some of the zombie child processes because they then occupy the stdout descriptor and never close. Using tail -pid works, but unfortunately it doesn't work on Windows, and I need it to be multi-platform. I thought this could be achieved by calling read -t -N in a loop, but apparently this does not work ...

+5
source share
2 answers

Question: where to "go" ??

woo was read first by read -t 0.1 -r -N 10 , and then this command failed because 10 characters or the EOF character were not received during the set timeout.

According to read the man page :

  -N nchars return only after reading exactly NCHARS characters, unless EOF is encountered or read times out, ignoring any delimiter -t timeout time out and return failure if a complete line of input is not read withint TIMEOUT seconds. The value of the TMOUT variable is the default timeout. TIMEOUT may be a fractional number. If TIMEOUT is 0, read returns success only if input is available on the specified file descriptor. The exit status is greater than 128 if the timeout is exceeded 

Edit: I want to read into the buffer of N characters and read the input as is, without decomposing the words into metrics. Therefore, -N and IFS = "".

If you invoke the read command two times, each instance has a separate buffer. To solve this problem, use one read command and adjust or remove the timeout parameter, for example:

 (echo "woo"; sleep 2; echo "bla") 1> \ >(IFS=""; read -r -N 10; \ echo "exit code: $? reply: $REPLY";) 

And then, if you want to simultaneously view the input, you can add the tee command, for example:

 (echo "woo"; sleep 2; echo "bla") 1> \ >(tee >(IFS=""; read -r -N 10; \ echo "exit code: $? reply: $REPLY";)) 
+4
source

You need to enter sleep right before reading the output from stdout. This sleep must be at least the same or more as the input.

  (echo "woo"; sleep 1; echo "blah") 1> >( IFS=""; \ sleep 1; read -t 0.1 -N 10; echo $REPLY; sleep 2; \ read -t 0.1 -N 10; echo $REPLY) 

In your case, echo woo grunts with the next sleep command. By the time the output redirects, everything that it sees sleep 1; echo "blah" happens sleep 1; echo "blah" sleep 1; echo "blah" .

And you have one more problem. You are trying to read 10 characters with the -N option, where, as you provide, there are 3 , forcing it to exit with code 142 . Try -N 4 .

After that exit with code = 0 ;

  $ (echo "woo"; sleep 1; echo "blah") 1> >( IFS=""; \ sleep 1; read -t 0.1 -N 4; echo "code: $?"; \ echo $REPLY; sleep 2; read -t 0.1 -N 4; echo "code: $?"; \ echo $REPLY) code: 0 woo code: 0 blah 
+1
source

Source: https://habr.com/ru/post/1274714/


All Articles