我正在编写一个需要根级权限的脚本,我想让它这样做,如果脚本不是以根身份运行,它只是回显“请以根身份运行”并退出。

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

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

  else (do stuff)
fi

exit

我怎样才能最好地(干净和安全地)完成这个任务呢?谢谢!

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


当前回答

$EUID环境变量保存当前用户的UID。Root的UID为0。在你的脚本中使用这样的东西:

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

注意:如果你得到2:[:非法数字:检查你是否有#!将/bin/sh改为#!/bin/bash。

其他回答

据我所知,正确的检查方法如下:

#!/bin/sh

if [ "$(id -u)" -eq 0 ]; then
    echo "You are root."
else
    echo "You are NOT root." >&2
fi

OP注释:你可以在linuxcommand.org上看到“测试Root”部分。

编者注:我稍微调整了这个shell片段,使其与posix兼容。

1-阅读官方的GNU Linux文档,有很多正确的方法。

2-确保你把shell签名,以避免错误解释:

#!/bin/bash

3-这是我的剧本

#!/bin/bash 

if [[ $EUID > 0 ]]; then  
  echo "Please run as root/sudo"
  exit 1
else
  #do your stuff
fi

需要注意的是,无论何时使用sudo运行脚本,“用户上下文”或环境都会切换到根目录。

但是特奥,这意味着什么?

好吧,我年轻的学徒,这意味着如果学徒用户使用sudo运行一个包含波浪号(~)的脚本,无论何时bash将展开~,结果将是/root而不是/home/<用户>(即,在这种情况下,/home/padawan),或者如果您创建一个目录或文件,所有者和组将是root,而不是执行脚本的人在这种情况下padawan,因为用户环境被切换了。

例如,让我们检查这个脚本install-app.sh:

#!/bin/bash
ROOT_UID=0   # Only users with $UID 0 have root privileges.
E_NOTROOT=87 # Non-root exit error.

## Prevent the execution of the script if the user has no root privileges
if [ "${UID:-$(id -u)}" -ne "$ROOT_UID" ]; then
    echo 'Error: root privileges are needed to run this script'
    exit $E_NOTROOT
fi
...
mkdir -vp ~/app/init
touch config
...
touch /home/<user>/app/init/profile
service mysql start
...

如果我们使用sudo运行:

sudo install-app.sh

这将创建目录,配置文件将如下所示:

##
## ~ (/root)
drwxr-xr-x 17 root root    4096 Nov 23 20:45 ./
drwxr-xr-x  5 root root    4096 Nov 15 19:04 ../
...
drwxr-xr-x  3 root root    4096 Nov 25 14:30 app/
...
drwxr-xr-x  2 root root    4096 Nov 16 19:08 tmp/

## ~/app (/root/app)
drwxr-xr-x  3 root root 4096 Nov 25 14:30 ./
drwxr-xr-x 17 root root 4096 Nov 25 14:33 ../
drwxr-xr-x  2 root root 4096 Nov 25 14:33 init/

## ~/app/init (/root/app/init)
drwxr-xr-x 2 root root 4096 Nov 25 14:33 ./
drwxr-xr-x 3 root root 4096 Nov 25 14:30 ../
-rw-r--r-- 1 root root    0 Nov 25 14:33 config

## /home/<user>/app/conf
drwxr-xr-x 2 <user> <user> 4096 Nov 25 14:43 ./
drwxr-xr-x 3 <user> <user> 4096 Nov 25 14:30 ../
-rw-r--r-- 1 root   root      0 Nov 25 14:43 profile

正如你所知,剧本简直一团糟。现在<用户>不能访问配置文件,也不能在没有sudo的情况下修改配置。一开始可能是不重要的,但相信我,如果你的项目变大了,有人会运行脚本,弄乱你的系统。

建议

我的建议是:请求用户验证是否是sudoer。然后,将sudo添加到需要它的命令中。

将这些更改应用到脚本将如下所示:

#!/bin/bash
E_NOTROOT=87 # Non-root exit error.

## Prevent the execution of the script if the user has no root privileges
## Check if is sudoer
if ! $(sudo -l &>/dev/null); then
    echo 'Error: root privileges are needed to run this script'
    exit $E_NOTROOT
fi
...
mkdir -vp ~/app/init
touch config
...
touch /home/<user>/app/init/profile
sudo service mysql start
...

这个修改允许用户像这样运行脚本:

install-app.sh

用户将被要求插入他的密码,以验证是否是sudoer。之后,mkdir -vp ~/app/init将在用户的home中创建文件:

/home/<user>/app/init
/home/<user>/app/init/config
/home/<user>/app/init/profile

此外,我建议获取用户的荷马目录并将其用作常量。

## Defines user home directory
USER_HOME_DIR=$(getent passwd ${SUDO_USER:-$USER} | cut -d: -f6)
...
mkdir -vp "$USER_HOME_DIR/app/init"
...

使用:id -u, $EUID和whoami的问题是,当我伪造根时,它们都给出了假阳性,就像这样:

$ fakeroot

id:

$ id -u
0

$ EUID:

$ echo $EUID
0

显示本用户信息:

$ whoami
root

那么一个可靠的(和黑客)方法是验证用户是否有权访问/根目录:

$ ls /root >/dev/null 2>&1 && is_root=true || is_root=false; echo "$is_root"

在Bash中,我的观点是:

#!/bin/bash

# Display the UID variable
echo "Your UID is $UID"

# Check for root user via UID
if [ "$UID" -eq 0 ]; then
    echo "You are root"
else
    echo "You are not root user" >&2
fi