Bash, execute command after invoking a new shell

I am trying to make a script like this:

sudo -s

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?

Asked By: Matteo


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

sudo -s something...
Answered By: soumen

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

Or you can use here strings :

$ sudo -s <<<'whoami'

If you have multiple commands you can use here doc :

$ sudo -s <<'EOF'
> whoami
> hostname
Answered By: heemayl

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

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 If necessary, you can use sudo to drop privileges for specific commands. For example:

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

Running the script above returns:

$ sudo ~/scripts/
Answered By: terdon

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:

  cat <<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.

Answered By: Michaël Le Barbier
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.