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.
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
One simple way to make the script only runnable by root is to start the script with the line:
#!/bin/su root
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
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)
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).
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
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.
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
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.
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
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
.
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:
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
#!/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.
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 filling the gaps.
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
)#+------------------------------------------------------------------------------+
#| is_user_root() benchmark |
#| "Bash is fast while Dash is slow in this" |
#| Language: POSIX shell script |
#| Copyright: 2020 Vlastimil Burian |
#| M@il: info[..]vlastimilburian[..]cz |
#| License: GPL 3.0 |
#| Version: 1.1 |
#+------------------------------------------------------------------------------+
readonly iterations=10000
# intentionally, the file does not have executable bit, nor it has no shebang
# to use it, just call the file directly with your shell interpreter like:
# bash is_user_root__benchmark
# dash is_user_root__benchmark
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
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.
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.
#!/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
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.
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
:)
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
).
Source: Stackoverflow.com