sudo su - << 'EOF'
# do stuff...
EOF
This works, but with a limitation: the script is passed to the shell on its standard input, so you don't get to use the standard input for something else such as reading the name of the user to create.
The simple way of retaining standard input is to pass the shell command as an argument instead.
Note that sudo su
is redundant — sudo
runs the specified command as root, and that's the sole purpose of su
as well. Use sudo -i
instead of sudo su -
if you want to run a login shell as root — which is probably unnecessary here — or sudo sh
to just run a shell as root.
sudo sh -c '
# do stuff...
'
This makes it awkward to use a single quote in the shell snippet. You can use '\''
to put a single quote inside the single-quoted literal. If you want to retain the here document structure, there are several ways. The most straightforward is to pass the here document on a different descriptor. However this requires the closefrom_override
option to be activated in the sudo configuration, which is not the case by default; by default, sudo
closes all file descriptors other than stdin, stdout and stderr.
sudo -C 3 sh -c '. /dev/fd/3' 3<<'EOF'
# do stuff...
EOF
If you want your code to be portable to machines where this option isn't activated, you can read the script from a heredoc and pass it to the shell as an argument.
script=$(cat <<'EOF'
# do stuff...
EOF
)
sudo sh -c "$script"
Alternatively, if you want the sudoed script to be able to read from the terminal, you can pass the script body on standard input. A limitation of this approach is that it doesn't allow the input of the overall script to be redirected.
sudo sh <<'EOF'
exec </dev/tty
# do stuff...
EOF
sudo sh -c '. /dev/fd/3' 3<<'EOF' .. do stuff .. EOF
gives mesh: 1: .: Can't open /dev/fd/3
.*B)* If I try
strace sudo sh -c '. /dev/fd/3' 3<<'EOF' ... EOF
, I get this.*C)* This post looks relevant. But it's suggestions didn't work.
Any hints?
– Nutritioustim Jun 21 '14 at 14:33sudo
closes the file descriptor. See my edited answer. When a program is executed in strace, it loses privileges (the setuid bit is ignored). – Gilles 'SO- stop being evil' Jun 21 '14 at 14:59sudo sh -c "$script"
or ii)sudo sh <<'EOF'
, is there a way to pass parameters and get return values, in and out of this method? – Nutritioustim Jun 21 '14 at 21:01sh -c '…script…' param0 param1 param2
(i.e.param
becomes$1
, etc.).sudo
returns the return code (value between 0 and 255) from the script. – Gilles 'SO- stop being evil' Jun 21 '14 at 21:20sudo
closing the file descriptor if you just usedsu
as I recommended. – mikeserv Jun 23 '14 at 21:34