1

I have a here document inside a bash script. I want to read a value from it like that :

su myUser<<SESSION set -x echo -n "Enter your name and press [ENTER]: " read name echo "the name is $name" SESSION 

But when I launch this script from another user, bash does not stop himself to wait for an input and ignore the read command.

Any ideas ?

    2 Answers 2

    4

    As L. Scott Johnson correctly found, the read reads from standard input. The standard input in the shell that su runs is connected to the here-document, so the read reads the literal string echo "the name is " (note that since the here-document is unquoted, the $name has already been expanded to an empty string, or to whatever value it had in the calling shell).

    Here is the same thing, but with a quoted here-document, and an extra line outputting $name again:

    su username <<'SESSION' set -x echo -n "Enter your name and press [ENTER]: " read name echo "the name is $name" echo "What I read was $name" SESSION 

    The output would be

    Password: + echo -n Enter your name and press [ENTER]: Enter your name and press [ENTER]: + read name + echo What I read was echo "the name is $name" What I read was echo "the name is $name" 

    To correctly do this, you can't have read reading from standard input. Instead, open a new file descriptor as a copy of standard input, and get read to read from that:

    su username 3<&0 <<'SESSION' set -x echo -n "Enter your name and press [ENTER]: " read name <&3 echo "the name is $name" SESSION 

    If the shell of the other user is bash or ksh, then read name <&3 may be replaced by read -u3 name.

    Note however that you can't expect the name variable to be set in the shell calling su as a child shell can't modify the environment (variables etc.) of a parent shell.

    3
    • Nice explanation, but, consider that we have a large heredoc script to be executed remotely then at some point we need the confirmation to continue the execution of the remaining of the script, how to properly do that ?
      – Enissay
      CommentedDec 21, 2021 at 20:39
    • 1
      @Enissay By some variant of the code, I show at the end. Or simply by transferring the script over to the remote host and running it there. However, it's quite seldom that much of a script has to run remotely. It's more common that parts of the script do user interaction locally and then use ssh to do a few things on the remote host, possibly processing the data locally.
      – Kusalananda
      CommentedDec 21, 2021 at 22:20
    • Noted, indeed, it will be easier to change the logic to make it more local
      – Enissay
      CommentedDec 21, 2021 at 22:50
    1

    It doesn't ignore the read command; it executes it and reads stdin. Then the line echo "the name is $name is read (from stdin) and assigned to $name.

    su myUser<<SESSION set -x echo -n \"Enter your name and press [ENTER]: \" read name someUser echo \"the name is \$name\" SESSION 

    output:

    + echo -n '"Enter' your name and press '[ENTER]:' '"' -n "Enter your name and press [ENTER]: " + read name + echo '"the' name is 'someUser"' "the name is someUser" 
    1
    • You're right, I understand now :)
      – Couim
      CommentedJun 12, 2019 at 14:52

    You must log in to answer this question.

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.