脚本如何检查它是否以 root 身份运行?

Mal*_*rba 160 bash root scripts

我正在编写一个简单的 bash 脚本,但我需要它来检查它是否以 root 身份运行。我知道可能有一种非常简单的方法可以做到这一点,但我不知道该怎么做。

只是要清楚:
编写脚本foo.sh的简单方法是什么,以便命令./foo.sh输出0,命令sudo ./foo.sh输出1

ane*_*hep 214

#!/bin/bash
if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root" 
   exit 1
fi
Run Code Online (Sandbox Code Playgroud)

  • 此外,`$UID` 和 `$EUID` 是 bashisms。仅符合 POSIX 的 shell 没有这些变量,您需要使用 [`id(1)`](http://linux.die.net/man/1/id) 代替。 (21认同)
  • @Andrew:变量在传递给 `sudo` 之前被替换。如果您运行`sudo sh -c 'echo $EUID'`,您将看到预期的结果。 (9认同)
  • @Andrew – 我知道我来晚了,但为了后代:`$EUID` 是一种 Bashism(如@DavidFoerster 上面提到的),而你的 `/bin/sh` 很可能是指向 `/bin/ 的链接dash`,而不是`/bin/bash`。`sudo bash -c 'echo $EUID'` 将产生预期的结果。 (8认同)
  • 我接受了这个原因(经过一些测试)使用系统变量 EUID 结果证明比运行命令(id -u)快(大约 100 倍),但所有的答案都很好用。 (7认同)
  • 在 bash 脚本中,您可以使用 `if ((EUID)); 然后`,见[@geirha 的评论](http://askubuntu.com/questions/15853/how-can-a-script-check-if-its-being-run-as-root#comment33736_30161) (4认同)

Lek*_*eyn 141

root 用户不必命名为“root”。whoami返回带有用户 ID 的第一个用户名0$USER包含登录用户的名称,该名称可以具有用户 ID 0,但具有不同的名称。

检查帐户是否以 root 身份登录的唯一可靠程序:

id -u
Run Code Online (Sandbox Code Playgroud)

-u用于有效用户 ID,而不是-r用于真实用户 ID。权限判断有效用户ID,而不是真正的一个。

测试

/etc/passwd0按给定顺序包含以下带有用户 ID 的用户名:

rootx
root2
Run Code Online (Sandbox Code Playgroud)

以 身份登录root2,给出下一个结果:

  • whoamirootx
  • echo $USER:(root2如果程序是在空环境中启动的,这将返回一个空字符串,例如env -i sh -c 'echo $USER'
  • id -u:0 如您所见,其他程序在此检查中失败了,只是id -u通过了。

更新后的脚本如下所示:

#!/bin/bash
if ! [ $(id -u) = 0 ]; then
   echo "I am not root!"
   exit 1
fi
Run Code Online (Sandbox Code Playgroud)

  • 我总是尽量保持 POSIX 兼容,使用 `sh`(`dash`)作为解释器而不是 `bash`。但是很好的射击,节省了另一个叉子:) (5认同)
  • 我见过更短的版本,`[ -w / ]`。这个想法保持不变。注意:在某些 chroot 中,`[ -w /etc/shadow ]` 会失败,因为 `/etc/shadow` 不存在,因此使用 `/` 的方法是首选。更好的方法是检查对 root 权限的实际需求。如果脚本需要写入`/etc/someconfig`,只需检查该文件是否可写或该文件不存在且`/etc` 可写。 (3认同)

jfs*_*jfs 37

正如@Lekensteyn 所说,您应该使用有效的用户 ID。你不需要id -u在 bash 中调用:

#!/bin/bash

if [[ $EUID -ne 0 ]]; then
   echo "You must be root to do this." 1>&2
   exit 100
fi
Run Code Online (Sandbox Code Playgroud)

@geirha 从评论中提出的建议使用算术评估:

#!/bin/bash

if (( EUID != 0 )); then
   echo "You must be root to do this." 1>&2
   exit 100
fi
Run Code Online (Sandbox Code Playgroud)

  • 一般来说,应该使用`((..))` 来测试数字,使用`[[..]]` 来测试字符串和文件,所以我会使用`if (( EUID != 0 )); then` 代替,或者只是 `if ((EUID)); 然后` (8认同)
  • `EUID` 应该变成 `$EUID`。不要使用`(( $EUID != 0 ))`,而是使用`[ $EUID != 0 ]`。它也适用于`dash`。 (2认同)
  • @Lekensteyn:`EUID` 工作得很好。这个问题被标记为“bash”而不是“dash”。命令 `env -i sh -c '[ $EUID != 0 ]'` 失败,但 `env -i bash -c '(( EUID != 0 ))'` 有效。顺便说一句,`dash` 不适用于 Ubuntu http://stackoverflow.com/questions/5160125/how-to-create-a-non-ascii-file-using-redirection-with-sh 上的一些非 ascii 字符-c 现在是 2011 年,还有人使用其他语言。 (2认同)

Nat*_*man 22

您可以使用whoami返回当前用户的命令来完成此操作:

#!/bin/bash

if [ `whoami` != 'root' ]
  then
    echo "You must be root to do this."
    exit
fi

...
Run Code Online (Sandbox Code Playgroud)

You must be root to do this.如果当前用户不是 ,则运行上面的将打印root


注意:在某些情况下,另一种方法是简单地检查$USER变量:

if [ $USER != 'root' ]
Run Code Online (Sandbox Code Playgroud)

  • @George Edison:我建议不要使用`$USER`,尤其是这种方式。`$USER` 由登录 shell 设置,它不需要传播到程序(`env -i sh -c 'echo $USER'`)。这样,`$USER` 是空的并且会发生语法错误。 (4认同)
  • @Lekensteyn 不仅是由 shell 设置的 `$USER`,它也很容易被欺骗。Whoami 将返回实际用户。 (2认同)
  • @PauldeVrieze 愚弄那张支票有什么意义? (2认同)
  • `id -u` 是一个更优越的解决方案。我认为这个答案可能具有误导性,不应该被接受。 (2认同)
  • @andrewsomething:`$USER` 由你的 shell 解释,你的例子应该是 `sudo sh -c 'echo $USER'` 才有意义。@George:它错误地假设`whoami` 将始终为UID 0 返回`root`。 (2认同)

Luc*_*ein 12

考虑到效率,您可以先测试EUID环境变量,如果不存在,则调用标准id命令:

if ((${EUID:-0} || "$(id -u)")); then
  echo You are not root.
else
  echo Hello, root.
fi
Run Code Online (Sandbox Code Playgroud)

这样,由于OR 快捷方式,您可以避免调用系统命令,从而优先查询内存中的变量。

代码重用:

function amIRoot() {
  ! ((${EUID:-0} || "$(id -u)"))
}
Run Code Online (Sandbox Code Playgroud)

  • *`((${EUID:-0} || "$(id -u)"))` 总是运行 `id -u`*,就像 `((1 || $(echo hi >&2; echo 1) )))` 和 `((0 || $(echo hi >&2; echo 1)))` 都打印 `hi`。*外部* shell 算法,`&&` 和`||` 是控制操作符;在`a || "$(b)"`, `b` 仅在 `"$(b)"` 运行时运行。大多数扩展,包括命令替换,都由控制运算符的短路语义控制。Shell 算术的运算符 * 碰巧 * 也拼写为 `&&` 和 `||`——这也导致短路,因为 `((1 || 0/0))` 不是错误——但是 shell算术发生*在*嵌套命令替换被扩展之后。 (2认同)

Joã*_*nto 9

#!/bin/bash
[[ $(id -u) != 0 ]] 
echo $?
Run Code Online (Sandbox Code Playgroud)