the accepted answer works well, but the idiom for the script callback with sudo on request can be simplified and made more portable :
[[ $(id -u) -eq 0 ]] || exec sudo /bin/bash -c "$(printf '%q ' "$BASH_SOURCE" " $@ ")"
Using [[ ... ]] instead of [ ... ] makes it impossible to add x to operands (or double quoting LHS).
Using bash -c instead of su -c to interpret the restored command line makes the command more portable since not all platforms support su -c (for example, macOS does not work).
In bash , $BASH_SOURCE is usually a more reliable way to reference an executable script.
Using the aforementioned approach, any references to variables or command / arithmetic substitutions in arguments are invariably expanded by the calling shell.
If you want a deferred extension so that variable references do not expand until the sudo shell is started, in the context of the root user, use this:
(( __reinvoked )) || exec sudo -s __reinvoked=1 "$BASH_SOURCE" " $@ "
Note that you will need to quote any arguments that contain references to variables or replace commands so that they are deferred; for example, '$USER' .
Note the use of the ad-hoc __reinvoked environment variable to ensure that the call is __reinvoked exactly once (even if it has already been run as the root user).
Here's a sample script that demonstrates the first method:
If not invoked as root, the script re-runs itself with sudo -s , passing all arguments through as-is.
If it has not been authenticated before and is still in the waiting period, sudo offer an administrator password.
#!/bin/bash [[ $(id -u) -eq 0 ]] || exec sudo /bin/bash -c "$(printf '%q ' "$BASH_SOURCE" " $@ ")" # Print the username and all arguments. echo "Running as: $(id -un)" echo "Arguments:" for arg; do echo " $((++i)): [$arg]"; done
acfreitas' helpful answer demonstrates the script -inide-a-script technique where document is used to provide shell code via stdin to sudo su .
Again, sudo -s sufficient and important to quote :
sudo -s -H <<'EOF' echo "$HOME" EOF
Note how the document-separator, EOF , is disclosed in this case to prevent the contents of the document from being pre-interpreted by the current shell.
If you did not specify (any part) of EOF , $HOME will expand to the user's current home directory.
If you want to mix forward and the extension delay , leave the opening here - the document delimiter without quotes and selectively \ -quote $ instances:
sudo -s -H <<EOF echo "Called by: $USER; root home dir: \$HOME" EOF