In brief
You are probably expecting read
to behave the same way when it’s run without a pipe and wait for user input … Well it won’t as it’s STDIN is tied to the anonymous pipe and the only normally expected input is what comes through that pipe.
Then, why does it return immediately and repeatedly in the loop when no input is coming anymore through the anonymous pipe and that pipe has actually closed?
This is most likely because read
receives EOF
through the closed pipe as its STDIN and returns everytime the while loop iterates ... You can reproduce this with e.g. :
echo 'while :; do read -r -p "Y/y" i; echo "${i}$(date)"; done' | bash
A workaround would be using bash
's own process substitution syntax i.e. <(...)
like so:
bash <(echo 'while :; do read -r -p "Y/y" i; echo "${i}$(date)"; done')
Therefore, you can do something like this:
bash <(curl https://server/test.sh)
In detail
From help read
:
Exit Status:
The return code is zero, unless end-of-file is encountered, read times out
(in which case it's greater than 128), a variable assignment error occurs,
or an invalid file descriptor is supplied as the argument to -u.
Testing and comparing EOF
exit status:
Termination with Ctrl+D (will result in EOF
):
$ read input; echo "Exit code for EOF with Ctrl+D is: $?"
Exit code for EOF with Ctrl+D is: 1
Reading empty file (will result in EOF
):
$ touch emptyfile
$ read input < emptyfile; echo "Exit code for EOF with reading an empty file is: $?"
Exit code for EOF with reading an empty file is: 1
Reading from a closed pipe:
$ echo 'read input; echo "Exit code for EOF when reading from a pipe is: $?"' | bash
Exit code for EOF when reading from a closed pipe is: 1
Isolating bash
's Exit code after a pipe without read
(for reference):
$ echo 'echo "Exit code for bash alone after a pipe: $?"' | bash
Exit code for bash alone after a pipe: 0