How to check if running as root in a bash script

BashShellRoot

Bash 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 ]; }

Benchmark (save to file is_user_root__benchmark)
#+------------------------------------------------------------------------------+
#|                           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.


Portable pure POSIX solution + Example of usage of the above function

#!/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:

http://linuxcommand.org/lc3_wss0080.php

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 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 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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNathanView Question on Stackoverflow
Solution 1 - BashptiernoView Answer on Stackoverflow
Solution 2 - BashNathanView Answer on Stackoverflow
Solution 3 - BashsberderView Answer on Stackoverflow
Solution 4 - BashDale_ReaganView Answer on Stackoverflow
Solution 5 - BashSlater VictoroffView Answer on Stackoverflow
Solution 6 - BashLinuxSecurityFreakView Answer on Stackoverflow
Solution 7 - BashJeremy J StarcherView Answer on Stackoverflow
Solution 8 - BashMatthew TrotterView Answer on Stackoverflow
Solution 9 - BashSergio AbreuView Answer on Stackoverflow
Solution 10 - BashJohn KugelmanView Answer on Stackoverflow
Solution 11 - Bashalexandre1985View Answer on Stackoverflow
Solution 12 - BashMLSCView Answer on Stackoverflow
Solution 13 - BashSmeterlinkView Answer on Stackoverflow
Solution 14 - BashWebBrotherView Answer on Stackoverflow
Solution 15 - BashSr. LibreView Answer on Stackoverflow
Solution 16 - BashMike QView Answer on Stackoverflow
Solution 17 - BashTeocciView Answer on Stackoverflow
Solution 18 - BashContangoView Answer on Stackoverflow
Solution 19 - BashPramod KharadeView Answer on Stackoverflow
Solution 20 - Bashfvillalba89View Answer on Stackoverflow