Best practices on using sudo in a bash script
Solution 1
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
Solution 2
By reading man sudoers
, one sees:
PASSWD and NOPASSWD
By default, sudo requires that a user authenticate him or herself
before running a command. This behavior can be modified via the
NOPASSWD tag. Like a Runas_Spec, the NOPASSWD tag sets a default for
the commands that follow it in the Cmnd_Spec_List. Conversely, the
PASSWD tag can be used to reverse things. For example:
ray rushmore = NOPASSWD: /bin/kill, /bin/ls, /usr/bin/lprm
would allow the user ray to run /bin/kill, /bin/ls, and /usr/bin/lprm
as root on the machine rushmore without authenticating himself.
Thus, you could allow regular
on host machine1
to execute command1
and command2
as root, without password authentication with:
reguser machine1 root = NOPASSWD: /usr/local/command1, /usr/local/command2
but read each of man -k sudo
for details.
Related videos on Youtube
Dakkaron
Updated on September 18, 2022Comments
-
Dakkaron over 1 year
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 eachsudo
call is too longsudo
again asks for a password. Also, if the first execution ofsudo
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 aftersudo
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.
-
Dakkaron about 4 yearsI fear that does not work.
chmod 775
only allows you to execute the file and does not change the user which is executing the file or their rights. -
PiKey over 3 yearsin my case this does not work:
zsh:1: command not found: func
-
wjandrea over 3 years@PiKey Well, it's written for Bash, not Zsh. Is the
:1
there referring to the function definition (func(){
) or the call fromsu
(-c 'func'
)?