How to run two commands with sudo?
Asked Answered
B

11

184

Is there any way how I can run two Db2 commands from a command line? They will be called from a PHP exec command.

  1. db2 connect to ttt (note that we need to have the connection live for the second command
  2. db2 UPDATE CONTACT SET EMAIL_ADDRESS = '[email protected]'

I tried this:

sudo -su db2inst1 db2 connect to ttt; db2 UPDATE CONTACT SET EMAIL_ADDRESS = '[email protected]'

The first command finishes correctly, but the second one fails with the following error message:

SQL1024N A database connection does not exist. SQLSTATE=08003

Note that I need to run this as php user. The command sudo -u db2inst1 id as php user gives me correct output.

Burge answered 6/4, 2011 at 1:13 Comment(1)
The close vote is for migration to serverfault, since this is a systems administration question, not programming.Nonsuit
K
171

sudo can run multiple commands via a shell, for example:

$ sudo -s -- 'whoami; whoami'
root
root

Your command would be something like:

sudo -u db2inst1 -s -- "db2 connect to ttt; db2 UPDATE CONTACT SET EMAIL_ADDRESS = '[email protected]'"

If your sudo version doesn't work with semicolons with -s (apparently, it doesn't if compiled with certain options), you can use

sudo -- sh -c 'whoami; whoami'

instead, which basically does the same thing but makes you name the shell explicitly.

Killjoy answered 6/4, 2011 at 1:20 Comment(16)
it gives me /bin/bash: db2: command not found /bin/bash: db2: command not found if running as php userBurge
sudo -u db2inst1 -s -- 'whoami; whoami' runs ok from php accountBurge
add the /full/path/to/db2 ; maybe the root shell doesn't have it in its $PATHFlorineflorio
the reason is that there is no $PATH to db2 command. I have to the full pathBurge
Then db2 is not in the path for php user. Add a link to its binary in /usr/bin/.Stramonium
this doesn't work on latest debian stable (squeeze) bash: sudo -s -- '/usr/bin/whoami; /usr/bin/whoami' /bin/bash: /usr/bin/whoami; /usr/bin/whoami: No such file or directory Closeknit
@Closeknit you can use sudo -- sh -c 'whoami; whoami; as a workaround when "sudo -s" is broken. I've updated the answer as well.Killjoy
In ubuntu, the result is: root ubuntuBackwoods
Can you please explain why you need "--" ?Behring
@VicSeedoubleyew The -- indicates the end of parameters to sudo, so everything else is part of the command; without it, arguments like -c could be interpreted as an argument to sudo. This works for most (but not all) command-line programs. For another (non-sudo) example, to remove a file called -f you can't just run rm -f, right?! But you can run rm -- -f to delete the file called -f.Killjoy
This answer lacks some explanations (though others are worse), in particular about -- (the explanation is hidden in comments), and the fact that sh is not a sudo option. This might seem obvious but comments prove it's not to everybody. @wjl, please consider updating your answer.Accompaniment
I am using the similar command on Redhat 7.8 system ssh userA@host sudo -u userB -- sh -c 'whoami; whoami' The output is userB userA Not able to fix this. Tried sudo options like -i, -s --Neuralgia
There's another non-obvious element here, which is the difference between single quotes and double quotes when variables are involved. Compare sudo -- sh -c 'echo $USER' (prints root on most systems) to sudo -- sh -c "echo $USER" (prints the current username instead of root).Basilius
As others have noted, this too breaks for me with a /bin/bash: line 1: whoami; whoami: command not found. I was able to work around this with eval: sudo -s -- eval 'whoami; whoami'Quaquaversal
What options does sudo need to be compiled with to take multiple commands with -s?Openair
I still don't see a way to make it not escape the command with -i or -s, but here's what I've found.Openair
H
207

For your command you also could refer to the following example:

sudo sh -c 'whoami; whoami'

Hartal answered 6/4, 2011 at 1:57 Comment(1)
I have found this a more reliable alternative.Food
K
171

sudo can run multiple commands via a shell, for example:

$ sudo -s -- 'whoami; whoami'
root
root

Your command would be something like:

sudo -u db2inst1 -s -- "db2 connect to ttt; db2 UPDATE CONTACT SET EMAIL_ADDRESS = '[email protected]'"

If your sudo version doesn't work with semicolons with -s (apparently, it doesn't if compiled with certain options), you can use

sudo -- sh -c 'whoami; whoami'

instead, which basically does the same thing but makes you name the shell explicitly.

Killjoy answered 6/4, 2011 at 1:20 Comment(16)
it gives me /bin/bash: db2: command not found /bin/bash: db2: command not found if running as php userBurge
sudo -u db2inst1 -s -- 'whoami; whoami' runs ok from php accountBurge
add the /full/path/to/db2 ; maybe the root shell doesn't have it in its $PATHFlorineflorio
the reason is that there is no $PATH to db2 command. I have to the full pathBurge
Then db2 is not in the path for php user. Add a link to its binary in /usr/bin/.Stramonium
this doesn't work on latest debian stable (squeeze) bash: sudo -s -- '/usr/bin/whoami; /usr/bin/whoami' /bin/bash: /usr/bin/whoami; /usr/bin/whoami: No such file or directory Closeknit
@Closeknit you can use sudo -- sh -c 'whoami; whoami; as a workaround when "sudo -s" is broken. I've updated the answer as well.Killjoy
In ubuntu, the result is: root ubuntuBackwoods
Can you please explain why you need "--" ?Behring
@VicSeedoubleyew The -- indicates the end of parameters to sudo, so everything else is part of the command; without it, arguments like -c could be interpreted as an argument to sudo. This works for most (but not all) command-line programs. For another (non-sudo) example, to remove a file called -f you can't just run rm -f, right?! But you can run rm -- -f to delete the file called -f.Killjoy
This answer lacks some explanations (though others are worse), in particular about -- (the explanation is hidden in comments), and the fact that sh is not a sudo option. This might seem obvious but comments prove it's not to everybody. @wjl, please consider updating your answer.Accompaniment
I am using the similar command on Redhat 7.8 system ssh userA@host sudo -u userB -- sh -c 'whoami; whoami' The output is userB userA Not able to fix this. Tried sudo options like -i, -s --Neuralgia
There's another non-obvious element here, which is the difference between single quotes and double quotes when variables are involved. Compare sudo -- sh -c 'echo $USER' (prints root on most systems) to sudo -- sh -c "echo $USER" (prints the current username instead of root).Basilius
As others have noted, this too breaks for me with a /bin/bash: line 1: whoami; whoami: command not found. I was able to work around this with eval: sudo -s -- eval 'whoami; whoami'Quaquaversal
What options does sudo need to be compiled with to take multiple commands with -s?Openair
I still don't see a way to make it not escape the command with -i or -s, but here's what I've found.Openair
E
49

If you would like to handle quotes:

sudo -s -- <<EOF
id
pwd
echo "Done."
EOF
Emelun answered 24/1, 2013 at 9:2 Comment(2)
This is the cleanest answer here, thanks. Maybe add a note "You can't run multiple commands from sudo - you always need to trick it into executing a shell which may accept multiple commands to run as parameters"Marathon
I think it's worth noting that, as with passing the commands to run inside a double quoted string, any variable substitution will use the local shell's environment not the target user's (typically root) environment. So $HOME will be your home, not root's, and $USER will be your username not "root", etc.Basilius
R
46

I usually do:

sudo bash -c 'whoami; whoami'
Rustler answered 14/8, 2013 at 18:19 Comment(0)
L
14

An alternative using eval so avoiding use of a subshell:

sudo -s eval 'whoami; whoami'

Note: The other answers using sudo -s fail because the quotes are being passed on to bash and run as a single command so need to strip quotes with eval. eval is better explained is this SO answer

Quoting within the commands is easier too:

$ sudo -s eval 'whoami; whoami; echo "end;"'
root
root
end;

And if the commands need to stop running if one fails use double-ampersands instead of semi-colons:

$ sudo -s eval 'whoami && whoamit && echo "end;"'
root
/bin/bash: whoamit: command not found
Lemuelah answered 10/3, 2017 at 11:27 Comment(1)
Thank you! Even the subshell didn't work for me.Inheritor
C
3

The -s option didn't work for me, -i did.

Here is an example of how I could update the log size from my bash:

sudo -u [user] -i -- sh -c 'db2 connect to [database name];db2 update db cfg for [database name] using logsecond 20;db2 update db cfg for [database name] using logprimary 20;'
Codification answered 18/7, 2013 at 22:58 Comment(0)
S
2

On the terminal, type:

$ sudo bash

Then write as many commands as you want. Type exit when you done.

If you need to automate it, create a script.sh file and run it:

$ sudo ./script.sh
Seldan answered 5/4, 2017 at 8:18 Comment(0)
S
2

On a slightly-related topic, I wanted to do the same multi-command sudo via SSH but none of the above worked.

For example on Ubuntu,

$ ssh host.name sudo sh -c "whoami; whoami"
[sudo] password for ubuntu:
root
ubuntu

The trick discovered here is to double-quote the command.

$ ssh host.name sudo sh -c '"whoami; whoami"'
[sudo] password for ubuntu:
root
root

Other options that also work:

ssh host.name sudo sh -c "\"whoami; whoami\""
ssh host.name 'sudo sh -c "whoami; whoami"'

In principle, double-quotes are needed because I think the client shell where SSH is run strips the outermost set of quotes. Mix and match the quotes to your needs (eg. variables need to be passed in). However YMMV with the quotes especially if the remote commands are complex. In that case, a tool like Ansible will make a better choice.

Scanty answered 29/5, 2019 at 7:12 Comment(0)
C
1

If you know the root password, you can try

su -c "<command1> ; <command2>"  
Clicker answered 1/11, 2019 at 8:37 Comment(1)
If you don't know the root password, use sudo su -c "<command1> ; <command2>" .Fleabitten
L
1

This is a clean solution that works well for multiple lines

sudo bash -c """
id
echo "testing"
"""
Lodestone answered 3/1, 2023 at 22:5 Comment(0)
D
0

The above answers won't let you quote inside the quotes. This solution will:

sudo -su nobody umask 0000 \; mkdir -p "$targetdir"

Both the umask command and the mkdir-command runs in with the 'nobody' user.

Dorladorlisa answered 14/9, 2012 at 8:49 Comment(2)
You can use single and double quotes and escape them.Burge
Ok, so how come,now matter what I set the umask to in this command, it has no effect?Mouthpiece

© 2022 - 2024 — McMap. All rights reserved.