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?
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this communityAnother 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
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--
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.
Jul 23, 2015 at 12:03
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.
You need to add the command ahead of sudo -s, instead of in the next line.
sudo -s something...