Let's say I have a script that will be executed on various machines with root privileges, but I want to execute certain commands within that script without root.
Is that possible?
Both su and sudo can do this. They run a command as another user; by default that "another user" is root, but it can be any user. For example,
sudo -u www-data ls will run ls as the user www-data.
However...
The usual way is to run the script as the invoking user and use sudo for those commands which need it. sudo caches the credentials, so it should prompt at most once.
sudo will only cache the credentials for a limited time; if the script spends enough time executing non-root commands these cached credentials may be lost. sudo exports environment variables SUDO_COMMAND, SUDO_GID, SUDO_UID, and SUDO_USER.
You can use SUDO_USER or SUDO_UID to get back to the invoking user:
sudo -u "$SUDO_USER" an_unprivileged_command sudo is a souped-up version of su with better access controls. If you're already running as root, su will do it with no fuss:
#!/bin/sh -e echo -n "Script User: " && id -un echo -n "Other user: " && su blrfl -c "id -un" echo -n "Back to script user: " && id -un When run, you get this:
Script User: root Other user: blrfl Back to script user: root I agree with AlexP’s answer that you should generally run as non-root and only invoke sudo only for commands that need it. Whitelisting is always safer than blacklisting.
In addition to AlexP’s answer: You might want to invoke sudo at the very top of the script, to make sure that you don’t execute a number of operations until you realize that the user isn’t permitted to run sudo, and create a broken state. Therefore, I recommend to put the following at the top of scripts which need sudo at some point:
#!/bin/bash sudo true || exit 1 # … other code … This will immediately ask for the password (if necessary) and abort executing the script if sudo fails.
sudofor those commands which needs it.sudocaches the credentials, so it should prompt at most once.sudofor short.