3

I'm trying to do something like this:

sudo su <<EOF
select x in a b c; do echo "Selected $x"; break; done
EOF

However, it terminates without accepting input.

It works if I do this:

sudo su -c 'select x in a b c; do echo $x; break; done'

But it's nicer writing longer scripts with heredoc (yes I know it's nicer still to put them in a file).

I'm sure this is answered in various places, but I can't seem to hit the right bash/heredoc/tty/stdin search term combo.

Is there any way to achieve this?

4
  • So, put it in a script?
    – Kusalananda
    Jun 8 '17 at 9:40
  • ⬑ "I know it's nicer still to put them in a file". For my use case, that's more of a workaround than a solution.
    – c24w
    Jun 8 '17 at 9:43
  • How about sudo -s instead of sudo su?
    – Barmar
    Jun 8 '17 at 15:14
  • The problem is that select is trying to read the response to the prompt from the here-doc.
    – Barmar
    Jun 8 '17 at 15:16
3

The problem is that select is trying to read from stdin, which is redirected to the here-doc. Since there's no response to the prompt there, it gets an error.

The solution is to redirect input back to the terminal within the here-doc.

sudo -s <<'EOF'
select x in a b c; do 
    echo "Selected $x"
    break
done </dev/tty
EOF

Also, you need to put quotes around EOF to prevent variable expansion in the here-doc. Otherwise it expands $x in the original shell, not in the subshell that gets the value from select.

1
  • Perfect! Thanks :) Man, I must have tried every other permutation of piping and redirecting, in my confusion.
    – c24w
    Jun 8 '17 at 19:57
0

One way with a file if you want the remainder run as something else

$ cat asdf
who am i
sudo su
who am i
$ bash < asdf
jhldoe   tty??    Jun  7 16:30 
root     tty??    Jun  7 16:30 
$ 

More simpler might be that shells given standard input will run those commands

$ sudo sh <<EOF
> who am i
> pwd
> EOF
root     tty??    Jun  7 16:31 
/var/tmp
$ 

For the problem of reading from standard input and also having access to the terminal, I can solve that with my feed script (documentation, unit tests, .feedrc file for root's home directory).

$ (echo 'select x in a b c; do echo "Selected $x"; break; done') | sudo feed - bash

Though this will leave you in a root shell, and shoves the input into that shell, so may or may not suit your need.

1
  • I want to avoid writing the script to a file, if possible. Your second suggestion is interesting, but, like using su, it doesn't attach to my stdin so I can't select an option (e.g. echo 'select x in a b c; do echo "Selected $x"; break; done' | sudo sh).
    – c24w
    Jun 8 '17 at 9:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.