180

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 = 'mytestaccount@gmail.com'

I tried this:

sudo -su db2inst1 db2 connect to ttt; db2 UPDATE CONTACT SET EMAIL_ADDRESS = 'mytestaccount@gmail.com'

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.

informatik01
  • 16,038
  • 10
  • 74
  • 104
Radek
  • 13,813
  • 52
  • 161
  • 255
  • please leave a comment why you want to close this question. Thank you. – Radek Apr 06 '11 at 01:19
  • 1
    The close vote is for migration to serverfault, since this is a systems administration question, not programming. – bdonlan Apr 06 '11 at 01:23

11 Answers11

203

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

sudo sh -c 'whoami; whoami'

schnatterer
  • 7,525
  • 7
  • 61
  • 80
Jason
  • 3,237
  • 4
  • 26
  • 28
169

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 = 'mytestaccount@gmail.com'"

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.

Nobody
  • 192
  • 3
  • 12
wjl
  • 7,519
  • 2
  • 32
  • 41
  • 3
    it gives me `/bin/bash: db2: command not found /bin/bash: db2: command not found` if running as php user – Radek Apr 06 '11 at 01:29
  • `sudo -u db2inst1 -s -- 'whoami; whoami'` runs ok from php account – Radek Apr 06 '11 at 01:33
  • 1
    add the /full/path/to/db2 ; maybe the root shell doesn't have it in its $PATH – ggiroux Apr 06 '11 at 01:34
  • the reason is that there is no $PATH to db2 command. I have to the full path – Radek Apr 06 '11 at 01:36
  • Then db2 is not in the path for php user. Add a link to its binary in /usr/bin/. – Swiss Apr 06 '11 at 01:40
  • 14
    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 ` – Valor Nov 02 '12 at 11:48
  • 13
    @Valor you can use `sudo -- sh -c 'whoami; whoami;` as a workaround when "sudo -s" is broken. I've updated the answer as well. – wjl Nov 03 '12 at 15:19
  • In ubuntu, the result is: root ubuntu – Ardee Aram Dec 05 '14 at 03:13
  • 6
    Can you please explain why you need "--" ? – Vic Seedoubleyew May 15 '16 at 09:24
  • 9
    @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`. – wjl May 15 '16 at 16:00
  • 2
    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. – Skippy le Grand Gourou Oct 26 '16 at 07:23
  • 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 --` – afsd Apr 23 '20 at 08:41
  • 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`). – kbolino May 26 '23 at 15:30
49

If you would like to handle quotes:

sudo -s -- <<EOF
id
pwd
echo "Done."
EOF
Nebojša
  • 491
  • 4
  • 2
  • 6
    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" – trs Dec 03 '17 at 20:47
  • 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. – kbolino May 26 '23 at 15:24
46

I usually do:

sudo bash -c 'whoami; whoami'
Samer Atiani
  • 695
  • 1
  • 6
  • 8
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
Community
  • 1
  • 1
Cas
  • 6,123
  • 3
  • 36
  • 35
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;'
Simon H
  • 2,495
  • 4
  • 30
  • 38
abhihome
  • 39
  • 5
3

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
Moshe Simantov
  • 3,937
  • 2
  • 25
  • 35
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.

Eugene Chow
  • 1,688
  • 1
  • 11
  • 18
1

If you know the root password, you can try

su -c "<command1> ; <command2>"  
nomad
  • 471
  • 6
  • 12
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.

arberg
  • 4,148
  • 4
  • 31
  • 39
0

This is a clean solution that works well for multiple lines

sudo bash -c """
id
echo "testing"
"""
Akaisteph7
  • 5,034
  • 2
  • 20
  • 43