如果不是root用户,如何停止脚本运行(并回显“不是root用户运行!正在退出...”)


17

这是我的资料来源:

#!/bin/bash

echo "Running script to free general cached memory!"
echo "";
echo "Script must be run as root!";
echo "";
echo "Clearing swap!";
swapoff -a && swapon -a;
echo "";
echo "Clear inodes and page file!";
echo 1 > /proc/sys/vm/drop_caches;
echo "";

它清除缓存和内容,并回显它需要以root用户身份在终端中运行。我基本上只是希望脚本检测到没有以root身份执行时停止运行。

例:

"Running script to free general cached memory!"
"Warning: script must be run as root or with elevated privileges!"
"Error: script not running as root or with sudo! Exiting..."

如果以提升的特权运行,它将正常运行。有任何想法吗?谢谢!



2
@muru,除了另一个问题相反:如果以root用户身份运行,则脚本失败。
斯特凡Chazelas

3
@StéphaneChazelas啊,我不好。缩回
大师

另一种方法是root通过为必须与root一起运行的所有命令加上前缀前缀来限制工作量sudo
reinierpost

Answers:


46
#!/bin/sh

if [ "$(id -u)" -ne 0 ]; then
        echo 'This script must be run by root' >&2
        exit 1
fi

cat <<HEADER
Host:          $(hostname)
Time at start: $(date)

Running cache maintenance...
HEADER

swapoff -a && swapon -a
echo 1 >/proc/sys/vm/drop_caches

cat <<FOOTER
Cache maintenance done.
Time at end:   $(date)
FOOTER

root用户的UID为0(无论“ root”帐户的名称如何)。如果返回的有效UID id -u不为零,则用户未使用root特权执行脚本。使用id -ru测试对真正的ID(用户的UID 调用脚本)。

不要$EUID在脚本中使用,因为这可能会由非特权用户修改:

$ bash -c 'echo $EUID'
1000

$ EUID=0 bash -c 'echo $EUID'
0

如果用户这样做,显然不会导致特权升级,但是可能导致脚本中的命令无法执行应做的事情以及使用错误的所有者创建的文件等。


1
注意:在Solaris 5.10上,/bin/id -u给出/bin/id: illegal option -- u Usage: id [-ap] [user]
jrw32982支持Monica 17'9

1
@ jrw32982您应该很/usr/xpg4/bin早就$PATH可以访问Solaris上的POSIX实用程序。
库萨兰达

1
关键是的-u选项id不是通用的,因此该解决方案仅在POSIX版本id必须首先出现在PATH中的警告下才是通用的。
jrw32982在17:25支持Monica

1
@ jrw32982为使您的脚本能够在Solaris上选择正确的POSIX实用程序$PATH,请在脚本顶部进行修改,使其/usr/xpg4/bin位于之前/bin。如果您坚持使用非POSIX id,那么显然您将不得不提出一个更可移植的解决方案。
库沙兰丹

1
@Harry是的,因此脚本可以使用PATH=$( getconf PATH )或设置其他显式默认路径,或使用显式路径进行调用id
库萨兰达

19

我认为您想要的是检查您是否具有超级用户特权,即您的有效用户ID为0。

zshbash使其在$EUID变量中可用,因此您可以执行以下操作:

if ((EUID != 0)); then
  echo >&2 "Error: script not running as root or with sudo! Exiting..."
  exit 1
fi

对于任何类似POSIX的外壳,您可以使用id标准命令:

if [ "$(id -u)" -ne 0 ]; then
  echo >&2 "Error: script not running as root or with sudo! Exiting..."
  exit 1
fi

请注意,其中的所有id -unor whoami$USERNAME变量zsh将为您提供uid 的第一个用户名。在具有其他ID为0的用户的系统上,root即使进程是经过身份验证为root

$USER通常给你的用户通过身份验证,但依靠它很脆。它不是由外壳程序设置的,而是通常由身份验证命令设置的(例如loginsu(在GNU / Linux系统上,不一定是其他系统),sudo,,sshd(至少是openssh中的一个)。)。并非总是如此(更改uid不会自动设置该变量,必须由更改uid的应用程序显式完成),并且它也可能已经在Shell祖先的其他进程中进行了修改。$LOGNAME,则相同的警告要比POSIX指定的更可靠(最初来自FIPS 151-2)


12

您可以使用$USERwhoami检查当前用户。

if [[ "$USER" != "root" ]]; then
    echo "Error: script not running as root or with sudo! Exiting..."
    exit 1
fi

if [[ $(whoami) != "root" ]]; then
    echo "Warning: script must be run as root or with elevated privileges!"
    exit 1
fi

if [[ $(id -u) != "0" ]]; then
    echo "Error: script not running as root or with sudo! Exiting..."
    exit 1
fi

1
NP。我建议从字面上直接阅读bash手册[ gnu.org/software/bash/manual/bashref.html]。实际上这是一个非常容易的准备。对于这个答案,我建议参考: 3.2.4.2 Conditional Constructs 3.5.4 Command Substitution
Jesse_b

9
id -u带有或不带有-n选项的命令是使用whoami的替代方法。如果没有-n并与零进行比较,则可以更好地匹配内核实际进行的测试。内核只关心ID,而不是密码文件中的名称。
icarus

6
我相信使用$(id -u)会更好。在某些(恶意)情况下,$USER可能是错误的。
巴西尔·斯塔林凯维奇

1
对于那些对@Jesse_b提供的链接感兴趣的人:有一个错字。应该是gnu.org/software/bash/manual/bashref.html
Kryten

1
某些系统不使用“ root”作为具有uid 0的特权帐户的名称。QNAP最早出现在其中。因此,您只应检查uid 0,而不要检查root帐户名。
roaima

10

您真正想要确定的是您是否有权执行这些操作。检查您是否以此为生是不道德的做法。

如果系统已配置为允许非root用户修改交换和删除页面缓存,那么为什么该用户不能运行您的脚本?

取而代之的是,您可以简单地尝试操作,如果失败则返回一条有用的消息:

if ! ( swapoff -a && swapon -a )
then
  echo "Failed to clear swap (rerun as root?)" >&2
  exit 1
fi

if ! echo 1 > /proc/sys/vm/drop_caches
then 
  echo "Failed to free page cache (rerun as root?)" >&2
  exit 1
fi

非root用户正在关闭交换吗?
库萨兰达

2
是。您可以使用SELinux进行设置。同样,您可以禁用根进程。
那位其他人

1
exit万一用户希望使用其当前权限尽其所能,则您可能不希望在某些操作失败之后执行此操作。(但对于所有这些都需要root用户的典型系统,退出将更有用/噪音更少。)
Peter Cordes

2
我不会说检查您是否是root是“错误的做法”。特别是如果这正是您想知道的。我的观点是,最好检查一下您是否具有足够的权限来执行所需的操作。
Erik Bennett
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.