如果脚本不是 root,如何停止运行脚本(并回显“未以 root 身份运行!退出...”)

M. *_*per 18 root shell-script

这是我的来源:

#!/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 "";
Run Code Online (Sandbox Code Playgroud)

它清除缓存和内容,并回应它需要在终端中以 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..."
Run Code Online (Sandbox Code Playgroud)

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

Kus*_*nda 49

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

root 用户的 UID 为 0(无论“root”帐户的名称如何)。如果返回的有效 UIDid -u不为零,则用户没有以 root 权限执行脚本。用于id -ru针对真实 ID(调用脚本的用户的 UID )进行测试。

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

$ bash -c 'echo $EUID'
1000

$ EUID=0 bash -c 'echo $EUID'
0
Run Code Online (Sandbox Code Playgroud)

如果用户这样做,显然不会导致权限提升,但可能会导致脚本中的命令无法执行他们应该执行的操作以及使用错误的所有者创建的文件等。

  • @jrw32982 您应该将 `/usr/xpg4/bin` 放在 `$PATH` 的早期,以便访问 Solaris 上的 POSIX 实用程序。 (2认同)
  • @Harry是的,所以脚本可以使用 `PATH=$( getconf PATH )` 或设置其他一些显式默认路径,或者使用显式路径来调用 `id`。 (2认同)

Sté*_*las 21

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

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

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

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

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

请注意,所有id -unorwhoami$USERNAMEin 变量zsh都会为您提供 uid的第一个用户名。在具有 id 0 的其他用户的系统上,root即使该进程是已被验证为root.

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


jes*_*e_b 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
Run Code Online (Sandbox Code Playgroud)

  • 带有或不带有 `-n` 选项的命令 `id -u` 是使用 whoami 的替代方法。没有 -n 并与零进行比较可以更好地匹配内核实际进行的测试。所有内核关心的是 id,而不是密码文件中的名称。 (9认同)
  • 我相信使用 `$(id -u)` 更好。在某些(恶意)情况下,`$USER` 可能是错误的。 (6认同)

tha*_*guy 11

您真正想要的是确定您是否有权执行这些操作。检查你是否是 root 来代替它被认为是不好的做法。

如果系统已配置为允许非 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
Run Code Online (Sandbox Code Playgroud)

  • 我不会说检查你是否是 root 是“不好的做法”。特别是如果这*正是*您想知道的。我确实同意你的观点,最好检查你是否有足够的权限来做你想做的事。 (3认同)
  • 是的。您可以使用 SELinux 进行设置。同样,您可以禁止根进程执行此操作。 (2认同)