10

I am trying to make a script like this:

#!/bin/bash
sudo -s
something...

When I execute it, I get a new shell but something is executed only when I exit the shell created by sudo -s, not inside it.

Any help?

7

The problem is sudo -s without any argument will open an interactive shell for root.

If you just want to run a single command using sudo -s, you can simple do:

sudo -s command

For example :

$ sudo -s whoami
root

Or you can use here strings :

$ sudo -s <<<'whoami'
root

If you have multiple commands you can use here doc :

$ sudo -s <<'EOF'
> whoami
> hostname
> EOF
root
something--
  • 1
    It is not good to use sudo -s just in case the root user had the (rather poor) idea to change its shell. This should really be sudo sh which explicitly states which shell is to be used. – Michael Le Barbier Grünewald Jul 23 '15 at 12:03
5

Another way would be to pass a full bash command(s) to sudo:

#!/bin/bash
sudo bash -c 'command1; command2; command3;'

However, a better way would be to launch the script with sudo instead. It is not a very good idea to have sudo inside the script. Far better to run the entire script with root privileges (sudo script.sh). If necessary, you can use sudo to drop privileges for specific commands. For example:

#!/usr/bin/env bash
whoami
echo $HOME
sudo -u terdon whoami  ## drop privileges for specific command.

Running the script above returns:

$ sudo ~/scripts/a.sh
root
/root
terdon
3

The Bourne shell has a -c flag which you can use to pass an arbitrary script to the shell, so that you can write something like

sudo sh -c 'something'

This is however only useful for the simplest commands, because it is very cumbersome to quote the script correctly and the inconvenience is even higher if you send the command to a remote server over ssh because the argument script will be analysed twice, once on the side sending the script and once on the side running the script.

If something is a complex script or needs to be passed over a ssh line, it is common practice to write a function prepare_something_script whose job is to write the script 'something' on stdout. In its simplest form, this function can use a here-document to generate its output:

prepare_something_script()
{
  cat <<EOF
something
EOF
}

The script produced by prepare_something_script can then be executed locally with the privileges granted by sudo as follows:

prepare_something_script | sudo sh

In the scenario where the script must be executed remotely with privileges granted by sudo it is customary to encode the script in base 64 to avoid redirecting the standard input of ssh, like this:

something64=$(prepare_something_script | base64)
ssh usesr@remote-host "echo ${something64} | base64 --decode | sudo sh"

If you use that code in a function, do not forget to mark the something64 variable as local. Some implementations of base64 offer a -d flag to decode, which is less well supported than the verbose --decode variant. Some implementations require to add a -w 0 to the encoding command to avoid spurious line breaks.

0

You need to add the command ahead of sudo -s, instead of in the next line.

sudo -s something...

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.