Run only parts of a script as sudo, entering password only once
I am writing a script (actually a combination of scripts and makefile) that installs external dependencies: some apt-get
commands, some git
cloning, building, installing, adding users to groups, ...
Some of the operations in these scripts require superuser permissions, some don't.
Until now I have run the entire make process with sudo, but it has some drawbacks:
-
git
repos I clone getroot
as owner, which means I can't modify them afterwards withoutsudo
orchown
- the scripts that add users to groups don't know which user to add since
whoami
returnsroot
What is the best way of running as superuser only the commands that require it? Ideally the process would still require me to enter my sudo
password, but only once at the very beginning of the install process. It would then forget it at the very end, but keep it all the time until then (it can take several hours).
The solutions I have found online include:
-
sudo -v
at the begninning of the script, but if I understand correctly this times out. My script could be running for a couple of hours - running the script with
sudo
, but the commands that do not need superuser withsudo -u $(logname) <command>
. This is what I do now, but it feels like it should be the other way around.
Ideally, I would like my script to:
- ask for superuser credentials
- run normal commands as the logged in user
- run sudo commands with the credentials entered at step 1
-
sudo -k
to close the superuser session
Since you have sudo access, create a sudoers file for yourself, then delete it when the script is done:
# grant this user access to the sudo commands without passwords
# add all required cmds to the CMDS alias
sudo tee /etc/sudoers.d/$USER <<END
$USER $(hostname) = NOPASSWD: /usr/bin/apt-get, /usr/sbin/adduser, /bin/rm, ...
END
# your script goes here
sudo apt-get install ...
git clone ...
sudo adduser group2 $USER
sudo adduser group1 $USER
: ...
# then, remove the sudo access
sudo /bin/rm /etc/sudoers.d/$USER
sudo -k
One way, that I wouldn't generally recommend, is to read in the password yourself, and use sudo
's -S
option to pass the password as and when needed:
#! /bin/bash
IFS= read -rsp 'Enter your password: ' password
git clone ...
sudo -S apt-get install foo -y <<<"$password"
From man sudo
:
-S, --stdin
Write the prompt to the standard error and read the password
from the standard input instead of using the terminal device.
The password must be followed by a newline character.