Testing for root in POSIX shell
Published: Wednesday, Sep 10, 2008 Last modified: Monday, Dec 9, 2024
In order of preference. The last code snippet is arguably the best.
Do not depend on bloated BASH extensions!
Use the bourne shell and
lint/check with the checkbashisms
tool from Debian
devscripts.
#!/bin/sh
$USER
could be forged with certain shells! Also dangerous with su
if test "$USER" != "xroot"
then
echo not root
exit 1
fi
Ugly !
[ `id -u` -ne 0 ] && echo "not root" && exit 1
Using test
is better, though still UGLY to string it along one line like that. And if you decide to do a else clause with ||, bugs can easily result.
test "x$(whoami)" != "xroot" && echo "not root" && exit 1
Old original bourne shell did not know test prepending !
if ! test `id -u` = 0; then
echo "not root" > /dev/stderr # /dev/stderror is not portable!
exit 1
fi
Old bourne shells did not know semi-colons either. Be careful to keep whitespace on the inner area of the square brackets and notice we are using a string comparison without quoting.
if [ `id -u` -ne 0 ]; then
echo >&2 "not root" # this works, but is not as readable as appending the stderr
exit 1
fi
Old bourne shells did not know $() subshell. Notice we are using numeric comparison with strings, which could lead to problems on certain shells.
if test "x$(whoami)" != "xroot" # in case whoami returns empty value
then
echo "not root" >&2
exit 1
fi
Easy to read POSIX shell, though missing quotes which is sadly needed always to “play safe” :(
if test `id -u` != 0
then
echo "not root" >&2
exit 1
fi
Modern shell style with quotes and no backticks
if [ "$(id -u)" -ne "0" ] # string comparison is better in shell as argument lists are strings
then
echo "not root" >&2
exit 1
fi
Old Bourne POSIX shell flavour. Safe, portable and compatible and a bit too verbose for my liking.
ID=`id -u` # id is _slightly_ better than whoami, though less readable imo
if test "x$ID" -ne "x0"
then
echo "not root" # you don't have to output to stderr if you don't want to
exit 1
fi
Using test
is a better practice than using square brackets. Here I assume
id
returns something. In certain rare environments you cannot make this
assumption!
if test "$(id -u)" -ne "0"
then
echo "not root" >&2
exit 1
fi