How can I execute a series of commands in a bash subshell as another user using sudo?

37,430

Solution 1

Run a shell inside sudo: sudo bash -c 'whoami; whoami'

You can use any character except ' itself inside the single quotes. If you really want to have a single quote in that command, use '\'' (which technically is: end single-quote literal, literal ' character, start single-quoted literal; but effectively this is a way to inject a single quote in a single-quoted literal string).

Solution 2

You can pass the commands as standard input into sudo'ed bash with a here document:

sudo bash <<"EOF"
whoami
id
EOF

This way there is no need to fiddle with correct quoting, especially if you have multiple levels, e.g.:

sudo bash <<"EOF"
whoami
echo $USER ~
sudo -u apache bash <<"DOF"
whoami
echo $USER ~
DOF
EOF

Produces:

root
root /root
apache
apache /usr/share/httpd

(Note that you can't indent the inner terminator — it has to be alone on its line. If you want to use indentation in a here document, you can use <<- instead of <<, but then you must indent with tabs, not spaces.)

Solution 3

If you would like to get syntax highlighting from your editor, not use quotes around your code, and have proper indentation, you can write your commands in a function and send it to bash using the declare command:

function run_as_root() {
    whoami
    id
    echo $USER
}

sudo bash -c "$(declare -f run_as_root); run_as_root"

Solution 4

for example try this, I tested it:

sudo bash -c "cd /;ls;ls|grep o"

In this example you first change dir to /root, next list root directory and finally for root directory filter only directories having name with letter 'o'.

But i thing better way is writting script that do all you need and give exitcode for all complex action. Then you can sudo script instead group of single commands like example above.

Share:
37,430

Related videos on Youtube

qrest
Author by

qrest

Updated on May 22, 2020

Comments

  • qrest
    qrest almost 4 years

    I'm writing a bash script that needs to sudo multiple commands. I can do this:

    ( whoami ; whoami )
    

    but I can't do this:

    sudo ( whoami ; whoami )
    

    How do I solve this?

  • schemacs
    schemacs almost 14 years
    What I mean is sudo only prompts for password at the first time.no prompt within 5 minutes or more.How long will your script run?exit with 5 minutes?You should never change the default value to -1. Few cmds require root permission.just use sudo foo anywhere in your script at each line,or connected by comma.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' almost 10 years
    @MaximYegorushkin Not really if you know the trick — see my edit.
  • Maxim Egorushkin
    Maxim Egorushkin almost 10 years
    The trick does not scale well to multiple levels of quoting. Unlike multiple levels of here-documents.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' almost 10 years
    Here documents (there's no pipe involved) are indeed more convenient for a long command, but you do need to take care about quoting. You need to quote the heredoc end marker after <<, otherwise the outer shell would perform $ expansion. And if you nest, remember that the end marker has to be alone on its line, it can't be indented (unless you use the <<- form and indent with tabs). And of course using a here document for the script input precludes passing data as input to the script.
  • Maxim Egorushkin
    Maxim Egorushkin almost 10 years
    @Gilles You are right, the opening marker has to be quoted, see my updated answer.
  • Znik
    Znik about 7 years
    alternatively you can configure defined list of commands and scripts for sudo without password. of course your scripts should be written with security good practices. you should prevent for using external attributes if it possible, because in bash are too many traps.
  • Martin Jambon
    Martin Jambon over 5 years
    Readers should note that it's <<"EOF" and not <<EOF, otherwise variables are expanded too early.
  • AnthonyD973
    AnthonyD973 over 5 years
    I believe escaping within single quotes requires the $'' syntax : echo '\'' is considered as echo <a string with just a backslash followed by a string that will continue on the next line>, whereas echo $'\'' shows '.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 5 years
    @AnthonyD. Inside $'…', you can use \' to include a single quote. Inside '…', you need '\'' instead. It isn't parsed as an escape, but it behaves like one. echo '\'' looks like an attempt to use \' as an escape inside single quotes, but it doesn't work that way, as I wrote in my answer.