It is important to notice that whenever you run a script using sudo the 'user context' or environment will switch to root.
But what does that mean?
Well, my young padawan, this means that if a padawan user runs a script that contains a tilde (~) using sudo, whenever the bash will expand ~ the result will be /root and not /home/<user> (i.e., in this case /home/padawan), or if you create either a directory or a file the owner and group will be root and not the that executed the script in this case padawan, because the user environment was switched.
For instance, lets check this script install-app.sh:
#!/bin/bash
ROOT_UID=0 # Only users with $UID 0 have root privileges.
E_NOTROOT=87 # Non-root exit error.
## Prevent the execution of the script if the user has no root privileges
if [ "${UID:-$(id -u)}" -ne "$ROOT_UID" ]; then
echo 'Error: root privileges are needed to run this script'
exit $E_NOTROOT
fi
...
mkdir -vp ~/app/init
touch config
...
touch /home/<user>/app/init/profile
service mysql start
...
If we run using sudo:
sudo install-app.sh
This will create directories and a config file will look like this:
##
## ~ (/root)
drwxr-xr-x 17 root root 4096 Nov 23 20:45 ./
drwxr-xr-x 5 root root 4096 Nov 15 19:04 ../
...
drwxr-xr-x 3 root root 4096 Nov 25 14:30 app/
...
drwxr-xr-x 2 root root 4096 Nov 16 19:08 tmp/
## ~/app (/root/app)
drwxr-xr-x 3 root root 4096 Nov 25 14:30 ./
drwxr-xr-x 17 root root 4096 Nov 25 14:33 ../
drwxr-xr-x 2 root root 4096 Nov 25 14:33 init/
## ~/app/init (/root/app/init)
drwxr-xr-x 2 root root 4096 Nov 25 14:33 ./
drwxr-xr-x 3 root root 4096 Nov 25 14:30 ../
-rw-r--r-- 1 root root 0 Nov 25 14:33 config
## /home/<user>/app/conf
drwxr-xr-x 2 <user> <user> 4096 Nov 25 14:43 ./
drwxr-xr-x 3 <user> <user> 4096 Nov 25 14:30 ../
-rw-r--r-- 1 root root 0 Nov 25 14:43 profile
As you can see the script is a total mess. Now the <user> cannot get access to the profile file, nor can they modify the config without using sudo. At the beginning, this may seem not important, but I assure you that if your project gets bigger, someone will run the script and mess with your system.
Recommendation:
Prompt the user to verify if they are a sudoer. Then, add sudo to the commands that require it.
The following code shows how to apply these changes to the script:
#!/bin/bash
E_NOTROOT=87 # Non-root exit error.
## Prevent the execution of the script if the user has no root privileges
## Check if is sudoer
if ! $(sudo -l &>/dev/null); then
echo 'Error: root privileges are needed to run this script'
exit $E_NOTROOT
fi
...
mkdir -vp ~/app/init
touch config
...
touch /home/<user>/app/init/profile
sudo service mysql start
...
This modification allows the user to run the script like this:
install-app.sh
The user will be requested to insert his password to verify if is sudoer. After,mkdir -vp ~/app/init will create the file in the user's home:
/home/<user>/app/init
/home/<user>/app/init/config
/home/<user>/app/init/profile
Also, I recommend to get the users homer directory and use it as a constant.
## Defines user home directory
USER_HOME_DIR=$(getent passwd ${SUDO_USER:-$USER} | cut -d: -f6)
...
mkdir -vp "$USER_HOME_DIR/app/init"
...
id -ureturns0for root.