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
    Commented Dec 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
    Commented Dec 21, 2021 at 22:20
  • Noted, indeed, it will be easier to change the logic to make it more local
    – Enissay
    Commented Dec 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
    Commented Jun 12, 2019 at 14:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .