Ubuntu – Best practices on using sudo in a bash script

bashsusudo

I have a long and long-running bash script where a handful of commands need to be run as root while the majority of commands need to be run as the regular user before sudo, because it would mess up file ownership and such.

I came up with some methods, but each of them have some problems

Method 1: Using sudo inside the file

#!/bin/bash
sudo echo "I must be run by root"
touch needsToBeOwnedByUser1
echo "needs to be run by user"
sleep 1000
sudo echo "I, again, must be run by root"

This would look good, from the way the code is written. sudo is written before the few statements that actually need to be run by root, but if the time between each sudo call is too long sudo again asks for a password. Also, if the first execution of sudo fails, e.g. due to an invalid password, the rest of the script is still executed.

Method 2: using sudo to call the file and then change back to the original user when needed

#!/bin/bash
echo "I must be run by root"
su username -c 'touch needsToBeOwnedByUser1'
su username -c 'echo "needs to be run by user"'
su username -c 'sleep 1000'
echo "I, again, must be run by root"

This also sucks, because I need to add su username -c in front of almost every line. Also finding the original username after sudo is possible, but cumbersome.

Is there a better way?

Edit: I only posted small, nonsensical scripts here to show what I am talking about. In the actual script I have some lines that need sudo (starting and stopping services), some lines where it does not matter if there is sudo and quite a lot of lines that really need to be run without sudo.

Best Answer

Regarding method 2, it's easier to use a function. For example:

#!/bin/bash

func(){
    echo "Username: $USER"
    echo "    EUID: $EUID"
}

export -f func

func
su "$SUDO_USER" -c 'func'

$SUDO_USER is the sudoer's username. You could also use $(logname) in its place.

Running on my machine:

$ sudo bash test.sh
[sudo] password for wja: 
Username: root
    EUID: 0
Username: wja
    EUID: 1000