Caching sudo privileges
Sometimes we would like to “conserve” the sudo privilege for later using it, without executing as root the full script.
Simple way:
#! /bin/bash
sudo -v
while [ -d /proc/$$ ]; do sudo -nv; sleep 3; done &
... your code ...It will launch a background process that will refresh sudo’s timestamp periodically as long as the main script is working. A disadvantage is that it will write lines periodically to the system logs.
A more complex and rather beautiful approach based on bash coprocesses:
function sudo_init {
[ "${SUDO[0]:-}" != "" ] && return ## Ignore multiple inits
coproc SUDO {
sudo "$@" $SHELL -c 'while read cmd
do
sh -exc "$cmd" </dev/null >&2
echo $?
done'
}
}
function sudo_run {
echo -n "cd '$PWD' && " >&${SUDO[1]} ## Go to the current dir
for w in "$@"
do
echo -n "'$w' " >&${SUDO[1]} ## Quote each word
done
echo >&${SUDO[1]} ## End the line
read -u ${SUDO[0]} ## Read response
return $REPLY
}The usage is simple: as soon as we know that we will require sudo, we run sudo_init. We can run it multiple times without any effects.
Then, whenever we need to run something as root, we use “sudo_run” instead of sudo.
if $SUDO_REQUIRED
then
sudo_init ## Ask for password here
if ! sudo_run ## Check everything is ok
then
die "Cannot run sudo"
fi
fi
make
sudo_run make install ## This might happen minutes later, but the password will not be asked againsudo_run respects multiple parameters given in the command line, as a normal sudo would, so that something this works:
$ sudo_run echo " a " "b c"
a
b cOptionally, extra options can be given for sudo:
$ sudo_init -u daemon
$ sudo_run whoami
daemonIt uses bash’s coprocesses. The sudo command is launched in the background and this as soon as the main script ends, which makes the setup very secure.
The drawback is that the stdin and stdout of the called programs cannot be used, since it is used for sending the requests and responses, but all in all it is very useful.