364

我正在编写一个需要 root 级别权限的脚本,并且我想这样做,以便如果脚本不是以 root 身份运行,它只会回显“请以 root 身份运行”。并退出。

这是我正在寻找的一些伪代码:

if (whoami != root)
  then echo "Please run as root"

  else (do stuff)
fi

exit

我怎样才能最好地(干净而安全地)做到这一点?谢谢!

啊,只是为了澄清一下:(做东西)部分将涉及运行本身需要root的命令。因此,以普通用户身份运行它只会出现错误。这只是为了干净地运行需要 root 命令的脚本,而不在脚本中使用 sudo,我只是在寻找一些语法糖。

4

20 回答 20

538

$EUID 环境变量保存当前用户的 UID。Root 的 UID 为 0。在您的脚本中使用类似这样的内容:

if [ "$EUID" -ne 0 ]
  then echo "Please run as root"
  exit
fi

注意:如果你得到2: [: Illegal number:检查你是否#!/bin/sh在顶部并将其更改为#!/bin/bash.

于 2013-08-13T18:05:08.940 回答
131

已经给出了一些答案,但似乎最好的方法是使用:

  • id -u
  • 如果以 root 身份运行,将返回 0 的 id。

这似乎比其他方法更可靠,并且即使脚本通过sudo.

于 2015-02-27T23:29:34.427 回答
91

在 bash 脚本中,您有多种方法可以检查正在运行的用户是否为 root。

作为警告,不要使用root用户名检查用户是否为 root。没有任何东西可以保证调用 ID 为 0 的用户root。这是一个被广泛遵循的非常严格的约定,但任何人都可以将超级用户重命名为另一个名称。

我认为使用bash的最佳方法是使用$EUID手册页中的 , :

EUID   Expands to the effective user ID of the current  user,  initialized
       at shell startup.  This variable is readonly.

这是一种更好的方法$UID,可以更改并且不反映运行脚本的真实用户。

if (( $EUID != 0 )); then
    echo "Please run as root"
    exit
fi

我解决这类问题的一种方法是在不以 root 身份运行时注入sudo我的命令。这是一个例子:

SUDO=''
if (( $EUID != 0 )); then
    SUDO='sudo'
fi
$SUDO a_command

这样,我的命令在使用超级用户或由sudo普通用户运行时由 root 运行。

如果您的脚本始终由 root 运行,只需相应地设置权限 ( 0500)。

于 2014-02-07T08:09:30.497 回答
74
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi

或者

if [[ `id -u` -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi

:)

于 2014-01-27T03:01:18.013 回答
34

有一个简单的检查用户是否为 root。

语法是在 bash 中运行检查的[[ stuff ]]标准方式。

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

这也假设如果失败,您想以 1 退出。该error函数是一些将输出文本设置为红色的天赋(不需要,但如果你问我,它非常优雅)。

于 2013-08-13T18:04:45.170 回答
32

在这个答案中,要明确一点,我假设读者能够阅读POSIX shell 脚本,bash如.dash

我相信这里没有太多要解释的,因为投票率很高的答案很好地解释了其中的大部分内容。

但是,如果有什么要进一步解释的,请不要犹豫,发表评论,我会尽力填补空白。


性能和可靠性优化的全方位解决方案;所有外壳兼容

新解决方案:

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

使用和持续时间示例:

$ 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

解释

由于读取$EUID标准bash变量(有效用户 ID 号)比执行POSIXid -u命令查找用户 ID 快很多倍,因此该解决方案将两者结合成一个包装精美的函数。当且仅当由于任何原因不可用时,该命令才会被执行,以确保我们在任何情况下都能获得正确的返回值。$EUIDid -u


为什么我在 OP 询问了这么多年之后才发布这个解决方案

好吧,如果我没看错,上面似乎确实缺少一段代码。

你看,有很多变量需要考虑,其中之一就是性能和可靠性的结合


便携式 POSIX方案+上述函数使用示例

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

结论

尽管您可能不喜欢它,但 Unix / Linux 环境已经多样化了很多。这意味着有些人非常喜欢bash,他们甚至没有想到可移植性(POSIX shell)。像我这样的其他人更喜欢POSIX shell。如今,这是个人选择和需求的问题。

于 2018-10-01T08:02:33.440 回答
30

正如@wrikken 在他的评论中提到的那样,id -u对root 的检查要好得多。

此外,通过正确使用sudo,您可以检查脚本并查看它是否以 root 身份运行。如果没有,让它重新调用自己sudo,然后以 root 权限运行。

根据脚本的作用,另一个选项可能是为sudo脚本可能需要的任何专用命令设置一个条目。

于 2013-08-13T18:07:03.573 回答
11

非常简单的方法就是:

if [ "$(whoami)" == "root" ] ; then
    # you are root
else
    # you are not root
fi

使用它代替的好处id是您可以检查某个非 root 用户是否也在运行该命令;例如。

if [ "$(whoami)" == "john" ] ; then
    # you are john
else
    # you are not john
fi
于 2015-01-27T18:36:45.540 回答
10

0- 阅读官方 GNU Linux 文档,有很多方法可以正确地做到这一点。

1-确保放置shell签名以避免解释错误:

 #!/bin/bash

2-这是我的脚本

#!/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
于 2017-01-02T16:42:41.040 回答
7

如果脚本确实需要 root 访问权限,那么它的文件权限应该反映这一点。拥有非 root 用户可执行的 root 脚本将是一个危险信号。我鼓励你不要用if支票来控制访问。

chown root:root script.sh
chmod u=rwx,go=r script.sh
于 2013-08-13T18:01:45.527 回答
6

使脚本只能由 root 运行的一种简单方法是使用以下行启动脚本:

#!/bin/su root

于 2016-08-13T20:52:04.870 回答
5

试试下面的代码:

if [ "$(id -u)" != "0" ]; then
    echo "Sorry, you are not root."
    exit 1
fi

或者

if [ `id -u` != "0" ]; then
    echo "Sorry, you are not root."
    exit 1
fi
于 2014-02-03T06:24:07.937 回答
2

id -u比 好得多whoami,因为像 android 这样的一些系统可能不提供 root 这个词。

例子:

# whoami
whoami
whoami: unknown uid 0
于 2014-01-26T17:42:39.713 回答
2

使用id -u、$EUID 和 whoami的问题是,当我伪造根目录时,它们都会给出误报,例如:

$ fakeroot

ID:

$ id -u
0

EUID:

$ echo $EUID
0

我是谁:

$ whoami
root

那么一个可靠的黑客方法是验证用户是否有权访问 /root 目录:

 $ ls /root/ &>/dev/null && is_root=true || is_root=false; echo $is_root
于 2020-12-18T13:53:51.617 回答
2

据我所知,检查它的正确方法是:

if [ $(id -u) = "0" ]; then
    echo "You are root"
else
    echo "You are NOT root"
fi

请参阅此处的“测试根”部分:

http://linuxcommand.org/lc3_wss0080.php

于 2018-09-09T12:07:18.673 回答
1

检查您是否是 root,如果不是则退出:

if ((EUID != 0)); then
    echo "Root or Sudo  Required for script ( $(basename $0) )"
    exit
fi

或者在此示例中,尝试在根位置创建一个目录,然后在提升权限后尝试。

检查您是否是根用户,如果可能,请检查是否提升:

# 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)
于 2014-06-03T17:09:18.800 回答
-1

请务必注意,每当您使用sudo“用户上下文”或环境运行脚本时,都会切换到root.

但是Teo是什么意思?

好吧,我年轻的学徒,这意味着如果padawan用户使用 运行包含波浪号 ( ~)的脚本sudo,则无论何时 bash 将展开~结果将是/root而不是/home/<user>(即,在这种情况下/home/padawan),或者如果您创建目录或在这种情况下,所有者和组将是一个文件,root而不是执行脚本的文件padawan,因为用户环境已切换。

例如,让我们检查这个脚本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
...

如果我们使用sudo

sudo install-app.sh

这将创建目录,config文件将如下所示:

##
## ~ (/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

你可以,她的剧本是一团糟。现在<user>无法访问profile文件也无法修改config没有sudo. 一开始接缝似乎并不重要,但相信我,如果您的项目变得更大,有人会运行脚本并弄乱您的系统。

推荐

我的建议是:请求用户验证是否是 sudoer。然后,添加sudo到需要它的命令中。

将此更改应用于脚本将如下所示:

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

此修改允许用户像这样运行脚本:

install-app.sh

将要求用户输入他的密码以验证是否为 sudoer。之后,mkdir -vp ~/app/init将在用户家中创建文件:

/home/<user>/app/init
/home/<user>/app/init/config
/home/<user>/app/init/profile

另外,我建议获取用户 homer 目录并将其用作常量。

## Defines user home directory
USER_HOME_DIR=$(getent passwd ${SUDO_USER:-$USER} | cut -d: -f6)
...
mkdir -vp "$USER_HOME_DIR/app/init"
...
于 2021-11-25T06:06:18.263 回答
-2

一个班轮:

test `whoami` != "root" && echo Please run as root && exit 1

在 Debian、Ubuntu 和 Docker 下测试。

于 2021-11-21T11:04:33.660 回答
-3

检查根:

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

经过测试并在根目录下运行。

于 2018-08-06T16:11:39.177 回答
-3
#!/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

编者注:如果您不需要双括号,请使用单个括号以实现代码可移植性。

于 2018-06-13T15:47:34.753 回答