How to check if running as root in a bash script
BashShellRootBash Problem Overview
I'm writing a script that requires root level permissions, and I want to make it so that if the script is not run as root, it simply echoes "Please run as root." and exits.
Here's some pseudocode for what I'm looking for:
if (whoami != root)
then echo "Please run as root"
else (do stuff)
fi
exit
How could I best (cleanly and securely) accomplish this? Thanks!
Ah, just to clarify: the (do stuff) part would involve running commands that in-and-of themselves require root. So running it as a normal user would just come up with an error. This is just meant to cleanly run a script that requires root commands, without using sudo inside the script, I'm just looking for some syntactic sugar.
Bash Solutions
Solution 1 - Bash
The $EUID environment variable holds the current user's UID. Root's UID is 0. Use something like this in your script:
if [ "$EUID" -ne 0 ]
then echo "Please run as root"
exit
fi
Note: If you get 2: [: Illegal number:
check if you have #!/bin/sh
at the top and change it to #!/bin/bash
.
Solution 2 - Bash
A few answers have been given, but it appears that the best method is to use is:
id -u
- If run as root, will return an id of 0.
This appears to be more reliable than the other methods, and it seems that it return an id of 0 even if the script is run through sudo
.
Solution 3 - Bash
In a bash script, you have several ways to check if the running user is root.
As a warning, do not check if a user is root by using the root
username. Nothing guarantees that the user with ID 0 is called root
. It's a very strong convention that is broadly followed but anybody could rename the superuser another name.
I think the best way when using bash is to use $EUID
, from the man page:
EUID Expands to the effective user ID of the current user, initialized
at shell startup. This variable is readonly.
This is a better way than $UID
which could be changed and not reflect the real user running the script.
if (( $EUID != 0 )); then
echo "Please run as root"
exit
fi
A way I approach that kind of problem is by injecting sudo
in my commands when not run as root. Here is an example:
SUDO=''
if (( $EUID != 0 )); then
SUDO='sudo'
fi
$SUDO a_command
This ways my command is run by root when using the superuser or by sudo
when run by a regular user.
If your script is always to be run by root, simply set the rights accordingly (0500
).
Solution 4 - Bash
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi
or
if [[ `id -u` -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi
:)
Solution 5 - Bash
There is a simple check for a user being root.
The [[ stuff ]]
syntax is the standard way of running a check in bash.
error() {
printf '\E[31m'; echo "$@"; printf '\E[0m'
}
if [[ $EUID -eq 0 ]]; then
error "Do not run this as the root user"
exit 1
fi
This also assumes that you want to exit with a 1 if you fail. The error
function is some flair that sets output text to red (not needed, but pretty classy if you ask me).
Solution 6 - Bash
In this answer, let it be clear, I presume the reader is able to read bash
and POSIX shell scripts like dash
.
I believe there is not much to explain here since the highly voted answers do a good job of explaining much of it.
Yet, if there is anything to explain further, don't hesitate to comment, I will do my best by filling the gaps.
Optimized all-round solution for performance and reliability; all shells compatible
New solution:
# bool function to test if the user is root or not
is_user_root () { [ "${EUID:-$(id -u)}" -eq 0 ]; }
is_user_root__benchmark
)
Benchmark (save to file #+------------------------------------------------------------------------------+
#| is_user_root() benchmark |
#| "Bash is fast while Dash is slow in this" |
#| Language: POSIX shell script |
#| Copyright: 2020-2021 Vlastimil Burian |
#| M@il: info[..]vlastimilburian[..]cz |
#| License: GPL 3.0 |
#| Version: 1.2 |
#+------------------------------------------------------------------------------+
readonly iterations=10000
# intentionally, the file does not have an executable bit, nor it has a shebang
# to use it, just call the file directly with your shell interpreter like:
# bash is_user_root__benchmark ## should take a fraction of one second
# dash is_user_root__benchmark ## could take around 10 seconds
is_user_root () { [ "${EUID:-$(id -u)}" -eq 0 ]; }
print_time () { date +"%T.%2N"; }
print_start () { printf '%s' 'Start : '; print_time; }
print_finish () { printf '%s' 'Finish : '; print_time; }
printf '%s\n' '___is_user_root()___'; print_start
i=1; while [ "$i" -lt "$iterations" ]; do
is_user_root
i=$((i+1))
done; print_finish
Examples of use and duration:
$ dash is_user_root__benchmark
___is_user_root()___
Start : 03:14:04.81
Finish : 03:14:13.29
$ bash is_user_root__benchmark
___is_user_root()___
Start : 03:16:22.90
Finish : 03:16:23.08
Explanation
Since it is multitude times faster to read the $EUID
standard bash
variable, the effective user ID number, than executing id -u
command to POSIX-ly find the user ID, this solution combines both into a nicely packed function. If, and only if, the $EUID
is for any reason not available, the id -u
command will get executed, ensuring we get the proper return value no matter the circumstances.
Why I post this solution after so many years the OP has asked
Well, if I see correctly, there does seem to be a missing piece of code above.
You see, there are many variables which have to be taken into account, and one of them is combining performance and reliability.
POSIX solution + Example of usage of the above function
Portable pure#!/bin/sh
# bool function to test if the user is root or not (POSIX only)
is_user_root () { [ "$(id -u)" -eq 0 ]; }
if is_user_root; then
echo 'You are the almighty root!'
exit 0 # implicit, here it serves the purpose to be explicit for the reader
else
echo 'You are just an ordinary user.' >&2
exit 1
fi
Conclusion
As much as you possibly don't like it, the Unix / Linux environment has diversified a lot. Meaning there are people who like bash
so much, they don't even think of portability (POSIX shells). Others like me prefer the POSIX shells. It is nowadays a matter of personal choice and needs.
Solution 7 - Bash
As @wrikken mentioned in his comments, id -u
is a much better check for root.
In addition, with proper use of sudo
, you could have the script check and see if it is running as root. If not, have it recall itself via sudo
and then run with root permissions.
Depending on what the script does, another option may be to set up a sudo
entry for whatever specialized commands the script may need.
Solution 8 - Bash
Very simple way just put:
if [ "$(whoami)" == "root" ] ; then
# you are root
else
# you are not root
fi
The benefit of using this instead of id
is that you can check whether a certain non-root user is running the command, too; eg.
if [ "$(whoami)" == "john" ] ; then
# you are john
else
# you are not john
fi
Solution 9 - Bash
0- Read official GNU Linux documentation, there are many ways to do it correctly.
1- make sure you put the shell signature to avoid errors in interpretation:
#!/bin/bash
2- this is my script
#!/bin/bash
if [[ $EUID > 0 ]]; then # we can compare directly with this syntax.
echo "Please run as root/sudo"
exit 1
else
#do your stuff
fi
Solution 10 - Bash
If the script really requires root access then its file permissions should reflect that. Having a root script executable by non-root users would be a red flag. I encourage you not to control access with an if
check.
chown root:root script.sh
chmod u=rwx,go=r script.sh
Solution 11 - Bash
One simple way to make the script only runnable by root is to start the script with the line:
#!/bin/su root
Solution 12 - Bash
try the following code:
if [ "$(id -u)" != "0" ]; then
echo "Sorry, you are not root."
exit 1
fi
OR
if [ `id -u` != "0" ]; then
echo "Sorry, you are not root."
exit 1
fi
Solution 13 - Bash
id -u
is much better than whoami
, since some systems like android may not provide the word root.
Example:
# whoami
whoami
whoami: unknown uid 0
Solution 14 - Bash
As far as I know the correct way to check it is:
if [ $(id -u) = "0" ]; then
echo "You are root"
else
echo "You are NOT root"
fi
See "Testing For Root" section here:
Solution 15 - Bash
The problem using: id -u, $EUID and whoami is all of them give false positive when I fake the root, for example:
$ fakeroot
id:
$ id -u
0
EUID:
$ echo $EUID
0
whoami:
$ whoami
root
then a reliable and hacking way is verify if the user has access to the /root directory:
$ ls /root/ &>/dev/null && is_root=true || is_root=false; echo $is_root
Solution 16 - Bash
Check if you are root and quit if you are not:
if ((EUID != 0)); then
echo "Root or Sudo Required for script ( $(basename $0) )"
exit
fi
Or in this example, try to create a directory in root location then try after rights were elevated.
Check if you are root and if not elevate if possible :
# Fails to create these dirs (needs sudo)
mkdir /test-dir-$(basename $0)
rmdir /test-dir-$(basename $0)
if ((EUID != 0)); then
echo "Granting root privileges for script ( $(basename $0) )"
if [[ -t 1 ]]; then
sudo "$0" "$@"
else
exec 1> output_file
gksu "$0" "$@"
fi
exit
fi
echo "Root privileges granted..."
# Creates Dirs as it now has rights
mkdir /test-dir-$(basename $0)
rmdir /test-dir-$(basename $0)
Solution 17 - Bash
It is important to notice that whenever you run a script using sudo
the 'user context' or environment will switch to root
.
But Teo what that means?
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 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 she the script is a total mess. Now the <user>
cannot get access to the profile
file neither can modify the config
without sudo
. At the beginning seams to be something not important but trust me if your project gets bigger someone will run the script and mess with your system.
Recommendation
My recommendation will be: request to the user to verify if is a sudoer or not. Then, add sudo
to the commands that require it.
Applying this changes to the script will be like this:
#!/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"
...
Solution 18 - Bash
One liner:
test `whoami` != "root" && echo Please run as root && exit 1
Tested under Debian, Ubuntu and Docker.
Solution 19 - Bash
#!/bin/bash
# GNU bash, version 4.3.46
# Determine if the user executing this script is the root user or not
# Display the UID
echo "Your UID is ${UID}"
if [ "${UID}" -eq 0 ]
then
echo "You are root"
else
echo "You are not root user"
fi
Editor's note: If you don't need double brackets, use single ones for code portability.
Solution 20 - Bash
Check for root:
ROOT_UID=0 # Root has $UID 0.
if [ "$UID" -eq "$ROOT_UID" ]
then
echo "You are root."
else
echo "You are just an ordinary user."
fi
exit 0
Tested and running in root.