How do I run a 'sudo' command inside a script?
Solution 1
It is rarely a good idea to have sudo
inside scripts. Instead, remove the sudo
from the script and run the script itself with sudo
:
sudo myscript.sh
That way, all commands within the script will be run with root privileges and you only need to give the password once when launching the script. If you need a particular command within the script to be run without sudo
privileges, you can run it as a regular user with (thanks Lie Ryan):
sudo -u username command
The space is irrelevant, it should not affect anything, there is always a space between a command and its arguments.
Solution 2
You could possibly modify the sudoers
file.
Run sudo visudo
.
Add an entry for your username and the script that you would like to run without being asked for a password.
username ALL=(ALL) NOPASSWD: /path/to/script
Solution 3
You could try something like:
echo "PASSWORD" | sudo -S ./playback_delete_data_patch.sh 09_delete_old_data_p.sql
This is not the most secure thing to do since you are writing a sudoer password in plain text. To make it a little more secure you can create a variable and read the sudo password into the variable and then you could execute the command as:
echo $PASSWORD | sudo -S ./playback_delete_data_patch.sh 09_delete_old_data_p.sql
Also, if you do not mind all your commands being executed as root you can simple execute your script using sudo
, as previously suggested.
sudo ./myscript
Solution 4
This answer is similar to terdon's answer. I would also suggest running the main script with sudo
so the script can run without having to ask for the user's password during its execution.
However, in case you want to drop root privileges to some of the commands and run them as the actual user who invoked the command with sudo
, you can check for the $SUDO_USER
variable to figure out the original user.
This is an example script of how you could achieve that:
#!/bin/bash
# ref: https://askubuntu.com/a/30157/8698
if ! [ $(id -u) = 0 ]; then
echo "The script need to be run as root." >&2
exit 1
fi
if [ $SUDO_USER ]; then
real_user=$SUDO_USER
else
real_user=$(whoami)
fi
# Commands that you don't want running as root would be invoked
# with: sudo -u $real_user
# So they will be run as the user who invoked the sudo command
# Keep in mind if the user is using a root shell (they're logged in as root),
# then $real_user is actually root
# sudo -u $real_user non-root-command
# Commands that need to be ran with root would be invoked without sudo
# root-command
Solution 5
There is actually a much simpler way to do this. For portability, this is my implementation but feel free to manipulate it to suit your need.
Enter your sudo password as a parameter when starting the script, capture it, and echo it with each command which will prompt for the sudo password.
#!/bin/bash
PW=$1
echo $PW | ./playback_delete_data_patch.sh 09_delete_old_data_p.sql
./command_wo_sudo.sh <param>
echo $PW | ./other_command_requires_sudo.sh <param>
You can add a prompt and capture after the script is kicked off like so:
echo "enter the sudo password, please"
read PW
But if someone else monitors what's run on the node; has access to logs created by it; or is just looking over your should randomly when you run a test, that could compromise security.
This also works with running commands/scripts that require a yes to continue:
echo $PW | yes | ./install.sh
The echo is in response to a prompt, so you can use anything you need to, there, if you're running other scripts that have prompts for progress, in sequential order. Make sure you know that order, though, or bad things can happen.
Related videos on Youtube
user251948
Updated on September 18, 2022Comments
-
user251948 over 1 year
To do a patch manually I must type this command
sudo ./playback_delete_data_patch.sh 09_delete_old_data_p.sql
There is a space just before the 09:
sudo ./playback_delete_data_patch.sh [space] 09_delete_old_data_p.sql
How can I run this inside a script?
There are also several other commands but this one is giving trouble.
-
Lie Ryan about 10 yearsJust put it in the script, what's the problem?
-
Wilf about 10 years@LieRyan - the
sudo
password - the script won't be able to run fully if someone is not there to enter it. -
SDsolar over 6 yearsMy system just runs them fine without prompting. Ubuntu 16.04 in October 2017. You have messed up your
sudoers
setup . No big deal. It just needs fixed. -
wizzwizz4 about 6 years@SDsolar Your system is the one that's messed up; it's a minor security vulnerability to not prompt for the password (makes users more vulnerable to some types of social engineering attacks).
-
caw almost 3 yearsHow you run the script (with regard to
sudo
) does affect the environment (i.e. available variables), though. This is important in some cases, for example withgsettings
.
-
-
Lie Ryan about 10 yearsthere may be commands in the script that don't need the root privilege, you can drop the root privilege temporarily for those commands by using sudo -u username
-
Krista K almost 9 yearsDidn't work for me, but thanks, good to know this exists. Perhaps I got the syntax wrong.
-
Krista K almost 9 yearsIn my situation, I wrote a script to fix permissions and ownership and keep forgetting to type
sudo
, so I put sudo before each command within the script. -
terdon almost 9 years@ChrisK yeah, don't do that. Just run
sudo script.sh
instead. It is both simpler and easier to do and makes for a more legible script. -
Joe over 8 yearsA lot of scripts I write do a whole bunch of user interaction and/or error checking. Then one command at the end - something like rsync - needs to be run as root. Why would I want to make the whole thing run elevated and leave myself open to many lines of code that could contain serious errors or vulnerabilities with root access - especially while debugging - when only one or a few commands require that access?
-
terdon over 8 years@Joe fair enough. Changed the "never a good idea" to "rarely".
-
escape-llc over 8 yearsNot sure anyone mentioned it, but you must terminate all login sessions of that user after you have edited the
sudoers
file. -
MttJocy almost 8 yearsJust to clarify here it is not the script that contains the "sudo ./playback_delete_data_patch.sh 09_delete_old_data_p.sql" line that should be specified in the sudoers file but the playback_delete_data_patch.sh script or whatever other command you want that user and/or their scripts to be able to run through sudo without specifying a password.
-
arainone over 7 years@Joe has a really good point here. Also when one says don't do that, it would be nice to know exactly why is that, or at least, in which context shouldn't I do that, and why
-
terdon over 7 years@arainone I didn't say don't do it, I said it is rarely a good idea. Largely because this means you can't run the script automatically since you will need to enter the password each time you are asked.
-
Zell Faze over 7 yearsWhen sudo is run on a script it sets the $SUDO_USER environmental variable to the user who called the script. Useful in conjunction with sudo -u
-
BeeOnRope almost 7 years@terdon - well if you run the script like
sudo script.sh
you'll have to enter your password initially. It seems the ubuntu default is to have a several-minutesudo
timeout, so whether your put 1 or moresudo
commands in the script, or do it outside, you'll likely only be entering the password one time, unless the script is very long running. -
terdon almost 7 years@BeeOnRope if you run with
sudo script
you will never need to enter the password again, not even if it runs for days. The script will be launched by the root user and root can run sudo with no password. That's the whole point of usingsudo script
instead of calling sudo inside the script. -
BeeOnRope almost 7 years@terdon - I know, I don't think I suggested otherwise above? I was pointing out that usually the entire script will run with a single sudo prompt even with multiple sudo commands inside the script due to a non-zero sudo timeout. Yes it will prompt you again for long running scripts. Usually you know if your script will fall into that category though. The downsides of running the entire script with sudo are pretty significant as well.
-
terdon almost 7 years@BeeOnRope no, that's what I am saying. It will never prompt for a password for any
sudo
calls inside the script if you have launched the script withsudo script
. The timeout has nothing to do with it. Once launched withsudo
, the script is running as root and root never needs to enter a password forsudo
. You can test this withsudo -i
(start a root shell) thensudo ls
and you will see it doesn't prompt you. To be extra sure, you can runsudo -k
to reset the password timestamp and it will still not prompt. Sudo will never prompt if you're root. -
BeeOnRope almost 7 years@terdon You aren't listening. I know that if you run the script as root it will never prompt you for sudo. I'm comparing that with not running the script as root and instead putting explicit
sudo
calls in the script, because elevating the entire script to root may be a terrible idea if there are only a handful of narrow actions that need root. In that context I was responding specifically to your comment: "Largely because this means you can't run the script automatically since you will need to enter the password each time you are asked." -
BeeOnRope almost 7 years... and I was pointing out that for most scripts, you will be printed for credentials the same number of times (zero or once) whether you choose run run
sudo script.sh
or justscript.sh
with certain commands prefixed with sudo within the script. The only except is scripts that run longer than the sudo timeout. Essentially, I'm agreeing with and providing some additional thoughts around @Joe's comment above. -
Job almost 6 yearsThat's so much more elegant and simple, I'm glad I scrolled all the way down! EDIT: wait, this will add the password to my terminal history
-
Job almost 6 yearsHow to ask for username/password with
read
: ryanstutorials.net/bash-scripting-tutorial/bash-input.php That should avoid this issue -
Christopher Hunter over 5 yearsGenerally this is a poor method. If you're going to add NOPASSWD sudo rules, especially for accounts that run automation, you should at minimum be restricting them to the exact command that is run (and not ALL)
-
Tobias Uhmann about 5 yearsReading password into variable securely:
read -s PASSWORD
-
Loenix over 4 yearsI think the advice is not good because in my case, there are commands that must be ran as non-root and with the real logged user (due to forwardagent usage inside).
-
terdon over 4 years@Loenix you can always use
sudo
to switch to that normal user then. But, as I said in the answer, it is rarely a good idea to have to sudo to root in the script. Rarely, not never. So maybe in your case it's useful. -
RichieHH over 4 yearsI use sudo inside interactive scripts all the time. And so do many people. It is patently false to say this is not done or is a good idea. You can STILL invoke the script with sudo with no ill effect. There are very good reasons NOT to invoke the entire script with sudo and to localise the sudo lines to those requiring sudo levels of access.
-
terdon over 4 years@HörmannHH please read my answer. Preferably, also read the many other comments that have already said the same thing as you. I didn't say never, I said it is rarely a good idea. I also never said anything about interactive scripts, and nor did the question. In fact, the whole point is about non-interactive scripts.
-
dez93_2000 about 4 yearsI'm trying to use this for a grub reboot to windows script. Code is: sudo grub-reboot "$(grep -i 'windows' /boot/grub/grub.cfg|cut -d"'" -f2)" && sudo reboot This works in a terminal but not in a shell script prepended with #!/bin/sh & set to executable. Any thoughts why this would be? Mousepad colouring suggests the && sudo reboot is being treated as if in quotes? I tried removing the sudos from that line and it didn't change anything. Thanks!
-
dez93_2000 about 4 yearsTurns out I needed to also add /usr/sbin/grub-reboot to /etc/sudoers and remove 'sudo' from before reboot
-
dotancohen over 3 yearsThis script has a very dangerous bug. For the duration of the time the script is running, the current user has elevated privileges. Furthermore, if the script crashes, these privileges are not revoked.
-
Emilio Grisolía over 3 yearsAdd a space before the command to avoid it appearing in the history.
-
Geronimo almost 3 yearsif I want to follow this advice but with a generic script, I would generally use $USER. I.e. sudo -u $USER. However if I start the script with sudo then $USER will be root, right? So is there a way to "generically" have most commands use sudo but some commands in the script use the users actual username??
-
terdon almost 3 years@Geronimo you have
$SUDO_USER
when launching things withsudo
. Trysudo env | grep USER
to see. -
EODCraft Staff over 2 yearsPerfect! Thanks, added pia.sh (Private Internet Access) to crontab with sudo, edited visudo (fith ALL=(ALL) NOPASSWD: /home/fith/pia.sh) worked!
-
Danijel over 2 yearsGreat tip, thanks!