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


273

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

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

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

  else (do stuff)
fi

exit

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

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


8
(1)使其无法由其他任何人执行,然后root(2)还要安排进一步的权限。(3)id -u返回0root。
2013年

Answers:


403

$ EUID环境变量保存当前用户的UID。根的UID为0。在脚本中使用如下代码:

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

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


良好的权限似乎是安全的双重保障
Kolob Canyon

25
我认为最好将字符串与字符串,数字与数字进行比较。使用双括号,您可以不带引号直接使用> [[$ EUID> 0]]
Sergio Abreu

7
我得到2: [: Illegal number:警告,直到将其更改为Sergio的版本。
alexeydemin

1
@ thekiwi5000仅then当与条件在同一行时才需要分号...
ptierno

1
@StephenAngelico Sudo应该工作。如果通过$ sudo echo $ EUID进行测试;那是一个糟糕的测试,并且会失败,因为在将命令传递给sudo之前会扩展$ EUID。尝试将echo $ EUID放在测试脚本中,然后使用sudo运行它。
user1169420 '19

79

在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

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

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

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

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


如果尝试运行该脚本的人员没有sudo特权,这将导致引发错误并且命令将无法运行?只是想确保,我理解正确。
Caperneoignis '16

1
我不确定此答案是否100%完全正确。在使用Bash 4.2.46的RHEL7.2上...如果我printf $EUID使用或不使用sudo,我都会得到自己的UID。如果使用,id -u我得到我的UID,当我用sudo调用它时,我得到0。我做错什么了吗?
0xSheepdog '16

4
@ 0xSheepdog,有可能在bash cli上先解析$ EUID变量扩展,然后sudo更改用户。因此,您将获得该行为,但是在脚本中,一切仍然可以正常工作。
亚历山大·伯德

@AlexanderBird好点,谢谢!我没有做任何实际的测试,只是报告了我的经验。
0xSheepdog '16

3
为测试使用“ herestring”以防止变量的局部shell扩展。比较sudo bash <<<'echo $EUID'bash <<<'echo $EUID'。可以在tldp.org/LDP/abs/html/x17837.html上找到
Bruno Bronosky

74

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

  • id -u
  • 如果以root用户身份运行,则将返回ID 0。

这似乎比其他方法更可靠,并且即使脚本运行通过,它也似乎返回的ID为0 sudo


太好了,这是最好的答案
Dan Ortega

58
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

:)


您可以考虑将Jeremy J Starcher的答案 与此部分集成,最后总是相同的东西……
真的很不错,2014年

我从终端知道,当我忘记给前缀加上前缀时,sudo我只需键入即可sudo !!为我完成工作,而无需按UP箭头,而是转到行的开头并sudo 手动添加。不知道这是BASH还是SUDO或其他东西,但是它在大多数时间都有效。
0xSheepdog '16

@ 0xSheepdog:这是一个Bash事情(也是IIRC起源于csh等其他shell的功能)。
暂停,直到另行通知。

总而言之,我将整体删除带引号的部分,然后将ok行重写为if [ "$(id -u)" -ne 0 ]; then echo 'Please run as root.' >&2; exit 1; fi。干杯。
LinuxSecurityFreak

29

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

另外,通过适当地使用sudo,您可以让脚本检查并查看它是否以root身份运行。如果不是,请通过调用它sudo,然后以root权限运行。

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


是否有一种优雅的方式可以让程序重新调用自己?也许有一些bash变量具有程序的绝对路径?
弥敦道

1
我现在不在要测试的BASH提示符附近,但是$0具有正在运行的脚本的名称。有一些例子在这里,可以帮助你。
Jeremy J Starcher

25

对于root用户,有一个简单的检查方法。

[[ stuff ]]语法是运行在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

这也假设您失败时要退出1。该error功能具有一定的才能,它将输出文本设置为红色(不需要,但是如果您问我,则非常漂亮)。


那是什么error命令?我的系统似乎没有它。。。
ruakh

哦,那只是小事。没什么大不了的,但是我会附上的。
Slater Victoroff

4
太酷了!如果我可以提出一些改进,请:(1)将换行符移到末尾;(2)写入标准错误而不是标准输出;(3)仅在标准错误是终端的情况下设置颜色(而不是冒用写转义字符到日志文件或其他方式的风险less);(4)设置背景颜色,因此无论用户终端的背景颜色如何,文本均可读。因此,类似function error () { if [[ -t 2 ]] ; then echo $'\033[31;2;47m'"$@"$'\033[0m' ; else echo "$@" ; fi >&2 ; }。(根据需要进行调整。)
ruakh

3
那不是“ -ne”而不是“ -eq”吗?
卡洛斯·雷登

2
@CarlosRendon Slater的代码是为了防止某些内容以超级用户身份运行。(这与OP的要求相反,但检查方法相同。)
Joshua Taylor

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

如果您使用字符串“ root”测试用户,是否不允许运行名为“ root”的任何人?
pcarvalho

您忘记了“;” 如果之后
Triskeldeian

1
@peteroak除了根以外,还有谁会被命名为根?
ptierno '16

3
+1用于实际回答有关whoami而不是使用的问题id;该whoami命令还可用于按名称检查root用户以外的其他用户。
Jez

10

0-阅读GNU Linux官方文档,有许多正确方法。

1-确保您放置了外壳签名,以避免解释错误:

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

10

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

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

但是,如果有什么需要进一步解释的,请不要犹豫,我将尽我所能填补空白。


优化的全方位(不仅是bash)解决方案,以提高性能和可靠性;所有壳兼容

新解决方案:

# 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                  ##
##          Tested with Dash version 0.5.8 and Bash version 4.4.18           ##
##                     Copyright: 2020 Vlastimil Burian                      ##
##                      E-mail: info@vlastimilburian.cz                      ##
##                             License: GPL-3.0                              ##
##                               Revision: 1.0                               ##
###############################################################################

# intentionally, the file does not have executable bit, nor it has no shebang
# to use it, please call the file directly with your shell interpreter like:

# bash is_user_root__benchmark
# dash is_user_root__benchmark

# bool function to test if the user is root or not
is_user_root () { [ ${EUID:-$(id -u)} -eq 0 ]; }

# helper functions
print_time   () { date +"%T.%2N"; }
print_start  () { printf '%s' 'Start  : '; print_time; }
print_finish () { printf '%s' 'Finish : '; print_time; }

readonly iterations=10000

printf '%s\n' '______BENCHMARK_____'
print_start

i=1; while [ $i -lt $iterations ]; do
    is_user_root
    i=$((i + 1))
done

print_finish

原始解决方案:

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

^^^被淘汰的解决方案被证明不能加快速度,但是已经存在很长时间了,因此只要有必要,我就将其保留在这里。


说明

由于读取$EUID标准bash变量(有效的用户ID号)要比执行id -u命令POSIX来查找用户ID的速度快很多倍,因此该解决方案将两者结合在一起,成为一个很好的打包函数。当且仅当$EUID由于某种原因而无法使用时,该id -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 # unnecessary, but here it serves the purpose to be explicit for the readers
else
    echo 'You are just an ordinary user.' >&2
    exit 1
fi

结论

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


6

如果脚本确实需要root用户访问权限,则其文件权限应反映出来。具有非root用户可执行的root脚本将是一个危险信号。我鼓励您不要用if支票来控制访问。

chown root:root script.sh
chmod u=rwx,go=r script.sh

4
如果某人获得他们的许可才能正常工作,但是我觉得过度使用777炸弹会使这种检查对于首先会犯错误的用户来说有点错误。
Slater Victoroff

7
这是假设用户正在运行可执行脚本。如果用户只是打电话bash /path/to/script,即使它仍然可以运行o=r
ptierno 2014年

5

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

#!/bin/su root


1
我很好奇为什么这个答案没有被投票更高?看起来最简单,最干净。这里有缺点吗?
Bassinator

@Bassinator我相信有人说它不能在某些nix上运行,但是到目前为止,它在我的Linux上都可以正常工作。试试吧!也许这个答案来得很晚,但是我想添加一个对社区来说很简单的知识(而不是像这个线程中的大多数人一样给出类似的答案:/)如果您很幸运地阅读了这篇文章,请投票给它在您的机器上工作
alexandre1985

@TamusJRoyce如果目标是检查您是否以root身份运行,而不是强制脚本仅以root身份运行,那么为什么在每个答案中,在检查是否以root身份运行之后,他们才制作脚本exit?那些答案仍然被否决吗?我想人们暗中不希望脚本以root身份运行。因此,我以一种简单的答案遵循了这种思维方式。但是,是的,您还可以从上面更详细的答案中学习
alexandre1985

@ alexandre1985确实如此。方案:如果以root身份运行,则当您询问如何安装程序时,可能希望脚本默认在全局范围内安装该程序。否则,默认设置为在本地安装。用户可以选择全局安装或本地安装,而不必按Enter键。但是,如果他们喜欢默认值,则可以按Enter键。并且不会提示您输入密码。如果您是root用户(按标题),您的shebang将永远不会“检查”。但是我仍然认为这个答案是有用的。
TamusJRoyce '19

@TamusJRoyce对您的评论完全有意义。确实存在问题,该解决方案不适用于该用例。你打开了我的视野。你是对的。谢谢
alexandre1985

4

试试下面的代码:

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


2

id -u比更好whoami,因为android等某些系统可能未提供root字样。

例:

# whoami
whoami
whoami: unknown uid 0

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

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


3
您尚未说明为什么要为5年之久的问题提供替代答案,而该问题已经有多个答案。
斯蒂芬,

0

检查您是否是root用户,如果不是,请退出:

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

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

检查您是否是root用户,如果可能的话,不提升用户身份:

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

-1

检查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

经过测试并以root身份运行。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.