如何检查是否在bash脚本中以root身份运行

Nat*_*han 245 bash shell root

我正在编写一个需要根级别权限的脚本,我想这样做,如果脚本不是以root身份运行,它只是回应"请以root身份运行".并退出.

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

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

  else (do stuff)
fi

exit
Run Code Online (Sandbox Code Playgroud)

我怎么能最好(干净,安全)完成这个?谢谢!

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

pti*_*rno 358

$ EUID环境变量保存当前用户的UID.Root的UID为0.在脚本中使用以下内容:

if [ "$EUID" -ne 0 ]
  then echo "Please run as root"
  exit
fi
Run Code Online (Sandbox Code Playgroud)

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

  • 我认为最好将字符串与字符串,数字与数字进行比较.使用双括号,您可以直接使用>不带引号[[$ EUID> 0]] (19认同)
  • 请注意,这是安全的,因为EUID是只读变量 (8认同)
  • 我得到了'2:[:非法数字:`警告,直到改成塞尔吉奥的版本. (7认同)
  • 这样做的问题是,如果您使用“sudo”,“$EUID”不会改变。因此,如果脚本使用“sudo”运行,则此检查会错误地抱怨它没有 root 权限(这正是您真正想要的 - 您不必成为 root)。 (4认同)
  • 在这里使用sudo可以正常工作 (2认同)
  • @thekiwi5000 仅当“then”与条件位于同一行时才需要分号... (2认同)
  • @StephenAngelico Sudo 应该可以工作。如果您通过执行 $ sudo echo $EUID 来测试它;这是一个糟糕的测试并且会失败,因为 $EUID 在命令传递给 sudo 之前被扩展。尝试将 echo $EUID 放在测试脚本中并使用 sudo 运行它。 (2认同)
  • `$EUID` 在 `dash`(常见的 `/bin/sh` 实现)中不起作用。 (2认同)

sbe*_*der 74

在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.
Run Code Online (Sandbox Code Playgroud)

这是一种比$UID可以改变的更好的方式,而不是反映运行脚本的真实用户.

if (( $EUID != 0 )); then
    echo "Please run as root"
    exit
fi
Run Code Online (Sandbox Code Playgroud)

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

SUDO=''
if (( $EUID != 0 )); then
    SUDO='sudo'
fi
$SUDO a_command
Run Code Online (Sandbox Code Playgroud)

这样我的命令在使用超级用户时由root运行,或者由sudo常规用户运行时运行.

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

  • @ 0xSheepdog,在bash cli上,有可能首先解析$ EUID变量扩展,然后sudo更改用户.因此,你会得到这种行为,但在脚本中,一切仍然可以正常工作. (4认同)
  • 我不确定这个答案是否 100% 完全正确。在使用 Bash 4.2.46 的 RHEL7.2 上...如果我使用或不使用 sudo `printf $EUID`,我都会得到我自己的 UID。如果我使用“id -u”,我会得到我的 UID,当我用 sudo 调用它时,我会得到 0。我做错什么了吗? (2认同)
  • 使用"herestring"进行测试,以防止变量的本地shell扩展.将`sudo bash <<<'echo $ EUID'`与`bash <<<'echo $ EUID'`进行比较.有关heredoc-like herestring的更多信息,请访问http://tldp.org/LDP/abs/html/x17837.html (2认同)

Nat*_*han 63

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

  • id -u
  • 如果以root身份运行,则返回id为0.

这看起来比其他方法更可靠,并且即使脚本运行,它似乎返回id为0 sudo.

  • 太好了,这是最好的答案 (2认同)

小智 50

if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi
Run Code Online (Sandbox Code Playgroud)

要么

if [[ `id -u` -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi
Run Code Online (Sandbox Code Playgroud)

:)


Jer*_*her 29

正如@wrikken在他的评论中提到的,id -u对root来说是一个更好的检查.

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

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


Sla*_*off 21

对root用户进行简单检查.

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

error() {
  printf '\E[31m'; echo "$@"; printf '\E[0m'
}

if [[ $EUID -eq 0 ]]; then
    error "This script should not be run using sudo or as the root user"
    exit 1
fi
Run Code Online (Sandbox Code Playgroud)

如果失败,这也假设您要退出1.该error函数是一些将输出文本设置为红色的天赋(不需要,但如果你问我,那就相当优雅).

  • 那太酷了!如果我可以提出一些改进:(1)将换行移至最后; (2)写入标准误差而不是标准输出; (3)只有在标准错误是终端时才设置颜色(而不是冒险将转义字符写入日志文件或"少"或什么); (4)设置背景颜色,因此无论用户终端的背景颜色如何,文本都是可读的.所以,像`function error(){if [[-t 2]]; 然后回音$'\ 033 [31; 2; 47m'"$ @"$'\ 033 [0m'; 否则回音"$ @"; fi>&2; }`.(根据需要调整.) (3认同)
  • 不应该是"-ne"而不是"-eq"? (2认同)
  • @CarlosRendon Slater 的代码是*防止*某些东西以root身份运行。(这与 OP 要求的相反,但检查方法是相同的。) (2认同)

小智 10

非常简单的方法就是:

if [ "$(whoami)" == "root" ] ; then
    # you are root
else
    # you are not root
fi
Run Code Online (Sandbox Code Playgroud)

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

if [ "$(whoami)" == "john" ] ; then
    # you are john
else
    # you are not john
fi
Run Code Online (Sandbox Code Playgroud)

  • 实际上回答关于`whoami`而不是使用`id`的问题的+1; `whoami`命令也可用于按名称检查除root之外的*其他*用户. (2认同)

Ser*_*reu 10

0-阅读官方GNU Linux文档,有很多方法可以正确地完成它.

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

 #!/bin/bash
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)


Lin*_*eak 9

在此答案中,请明确说一下,我假设读者能够阅读bashPOSIX shell脚本dash

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

但是,如果有什么需要进一步解释的,请随时发表评论,我会尽我所能填补空白。


优化的全方位bash解决方案,提高性能和可靠性

新解决方案:

is_user_root ()
{
    [ ${EUID:-$(id -u)} -eq 0 ]
}
Run Code Online (Sandbox Code Playgroud)

原始解决方案:

#!/bin/bash

is_user_root()
# function verified to work on Bash version 4.4.18
# both as root and with sudo; and as a normal user
{
    ! (( ${EUID:-0} || $(id -u) ))
}

if is_user_root; then
    echo 'You are the almighty root!'
else
    echo 'You are just an ordinary user.'
fi
Run Code Online (Sandbox Code Playgroud)


说明

由于读取$EUID标准bash变量(有效的用户ID号)要比执行id -u命令POSIX来查找用户ID的速度快很多倍,因此该解决方案将两者结合在一起,成为一个很好的打包函数。当且仅当$EUID由于某种原因而无法使用时,该id -u命令才会执行,以确保无论何种情况我们都能获得正确的返回值。


为什么OP询问了这么多年后才发布此解决方案

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

您会看到,必须考虑许多变量,其中之一是将性能和可靠性结合在一起


便携式POSIX解决方案

#!/bin/sh

is_user_root()
# function verified to work on Dash version 0.5.8
# both as root and with sudo; and as a normal user
{
    [ "$(id -u)" -eq 0 ]
}

if is_user_root; then
    echo 'You are the almighty root!'
else
    echo 'You are just an ordinary user.'
fi
Run Code Online (Sandbox Code Playgroud)

结论

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


Joh*_*ica 6

如果脚本确实需要root访问权限,则其文件权限应该反映出来.使非root用户可执行的根脚本将是一个红旗.我鼓励你不要用if支票来控制访问.

chown root:root script.sh
chmod u=rwx,go=r script.sh
Run Code Online (Sandbox Code Playgroud)

  • 这假设用户正在运行可执行脚本.如果用户只是调用`bash/path/to/script`,即使`o = r`,它仍然可以运行 (7认同)
  • 如果有人拥有他们的权限,这样做很好,但我觉得过度使用'777`炸弹使得这个检查对于那些首先会犯错误的用户来说有点不对劲. (4认同)

ale*_*985 6

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

#!/bin/su root


MLS*_*LSC 5

尝试以下代码:

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

要么

if [ `id -u` != "0" ]; then
    echo "Sorry, you are not root."
    exit 1
fi
Run Code Online (Sandbox Code Playgroud)