Score:6

bash builtin "read" after a pipe "|" doesn't wait for user input

pg flag

When I curl a script stored on my web server, it endlessly echos a prompt I coded in until I send ^c. All i do is a simple curl https://server/test.sh | bash. This is the code being ran through the pipe

while true
do
        read -r -p "[Y/n] " input

        case $input in
            [yY][eE][sS]|[yY])
                        echo "y"
                        break
                        ;;
            [nN][oO]|[nN])
                        echo "n"
                        break
                        ;;
            *)
                echo "y/n"
                ;;
        esac
done
Raffa avatar
jp flag
That is, most likely, because `read` recieves `EOF` through the pipe and returns everytime.
FireBADnoFire avatar
pg flag
@Raffa and how to i fix this issue?
David avatar
cn flag
Title makes no sense.
Raffa avatar
jp flag
@David You're right ... I changed the title to reflect the actual issue ... I hope it's clearer now.
Score:6
jp flag

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
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.