Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 如何在shell脚本中请求根权限?_Linux_Bash_Shell_Unix_Sh - Fatal编程技术网

Linux 如何在shell脚本中请求根权限?

Linux 如何在shell脚本中请求根权限?,linux,bash,shell,unix,sh,Linux,Bash,Shell,Unix,Sh,假设您有一个可能需要root权限的shell脚本。您不想强制用户以sudo的身份运行它。但是,如果确实需要该权限,则您希望提示用户输入密码,而不是抱怨并强迫用户使用sudo重新输入命令 您将如何在Bash脚本中执行此操作SudoTrue似乎有效,但感觉像是黑客攻击。有更好的方法吗?命令 sudo -nv 检查用户是否具有当前的sudo凭据(-v),但如果访问已过期(-n),将失败而不是提示 因此: if sudo -nv 2>/dev/null && sudo -v ;

假设您有一个可能需要root权限的shell脚本。您不想强制用户以sudo的身份运行它。但是,如果确实需要该权限,则您希望提示用户输入密码,而不是抱怨并强迫用户使用
sudo
重新输入命令

您将如何在Bash脚本中执行此操作
SudoTrue
似乎有效,但感觉像是黑客攻击。有更好的方法吗?

命令

sudo -nv
检查用户是否具有当前的
sudo
凭据(
-v
),但如果访问已过期(
-n
),将失败而不是提示

因此:

if sudo -nv 2>/dev/null && sudo -v ; then
    sudo whoami
else
    echo No access
fi
将检查用户的sudo凭据是否为最新凭据,并仅在不为最新凭据时提示输入密码

存在可能的竞争条件:用户的凭据可能在检查后立即过期


正如ghoti在评论中指出的那样,如果将
sudoers
文件设置为只允许执行某些命令,则这可能不起作用。出于这个原因和其他原因,请务必检查每个
sudo
命令是成功还是失败。

以下是我经常做的事情。这是松散的伪代码,但应该让您了解:

# myscript -- possibly execute as sudo

if (passed -e option) then
    read variables from envfile
else
    ...

    need_root = ...

    # set variables ...

    if ($need_root && $uid != 0) then
        env [or whatever] > /tmp/envfile
        exec sudo myscript -e/tmp/envfile ...
    fi
fi

# stuff to execute as root [or not] ...

如果您的计划是使用
sudo
进行权限提升,那么您可能需要解决的一个问题是,sudo可以设置为允许root用户访问某些命令,而不是其他命令。例如,假设您有一台运行VirtualBox的服务器,管理应用程序的人员与管理操作系统的人员不同。您的
sudoers
文件可能包含以下内容:

Cmnd_别名SAFE=/bin/true、/bin/false、/usr/bin/id、/usr/bin/who*
Cmnd_别名SHUTDOWN=/sbin/SHUTDOWN、/sbin/halt、/sbin/reboot
Cmnd_别名SU=/bin/SU、/usr/bin/vi*、/usr/sbin/visudo
Cmnd_别名shell=/bin/sh、/bin/bash、/bin/csh、/bin/tcsh
Cmnd_别名VBOX=/usr/bin/VBoxManage
%轮子全部=(全部)全部!苏!!贝壳!关闭
%全体职员=(全体)!苏!!炮弹,无子弹:安全
%操作员全部=(全部)安全,关闭
%vboxusers ALL=(全部)NOPASSWD:VBOX
在这种情况下,
vboxusers
unix组的成员将始终获得对
sudo-nv
的成功响应,因为该组存在NOPASSWD条目。但是,该组中运行VBoxManage以外的任何其他命令的成员将收到密码挑战和安全警告

因此,您需要确定需要运行的命令是否可以在没有密码提示的情况下运行。如果您不知道在运行脚本的系统上如何配置sudo,那么规范测试就是运行该命令。运行
sudo-nv
只会告诉您是否经过身份验证;它不会告诉您可以访问哪些命令


也就是说,如果您可以安全地依赖sudo配置,例如,在
wheel
组中,您可以通过以下方式访问所有命令:

%wheel          ALL=(ALL) ALL
然后您可以使用
sudo-nv
测试升级功能。但是您的脚本可能有一些作为root运行的东西,而有些东西不是。您可能还想考虑除代码> > SUDO < /> >特权升级以外的其他工具。

一种策略可能是,如果需要,将变量设置为preference命令,但如果已经是root用户,则将变量留空(即在sudo中运行整个脚本)

当然,如果我们已经是root用户,请取消设置以避免潜在冲突:

[ `ps -o uid= $$` -eq 0 ] && unset PM_SU_CMD
(请注意,这是对系统进程表的查询;我们不希望依赖shell的环境,因为这可能是伪造的。)

然后,可以使用以下功能更容易地使用某些系统实用程序:

# Superuser versions for commands that need root privileges
find_s         () { $PM_SU_CMD "/usr/bin/find $*"; }
mkdir_s        () { $PM_SU_CMD "/bin/mkdir -p $1"; }
rm_s           () { $PM_SU_CMD "/bin/rm $*"; }
然后在脚本中,只需使用需要以root权限运行的东西的
\s
版本


这当然不是解决这个问题的唯一方法。

我喜欢这种非常简单的sudo使用方法,但如果sudo配置了任何级别的复杂度,它都不起作用。尝试为您的用户仅为一个命令设置NOPASSWD条目<例如,code>keith ALL=(ALL)NOPASSWD:/usr/bin/whoami
sudo-nv
将返回true,但您仍然无法成功地
sudo-s
或运行任何其他命令。我对此持怀疑态度。一方面,只以root用户身份执行脚本中需要root权限的部分是个好主意,但我不喜欢使用root权限隐式执行某些操作——另一方面,用户可能没有意识到这一点。(例如,如果sudo配置为在没有密码的情况下工作)。最干净的解决方案可能是为整个脚本提供必需的根权限,并为不需要这些权限的操作删除权限。@hek2mgl。“是的,还有…”另一件事是,并非所有内容都需要使用root权限运行。Unix通过用户提供了特权分离,现在的应用程序都是由自己的用户安装的,所以它们不需要以root用户身份运行。我非常喜欢使用sudo只允许需要的东西。如果你
sudo-s
在我的一个系统上,我会收到一封电子邮件,你会得到一个严厉的聊天。
# Superuser versions for commands that need root privileges
find_s         () { $PM_SU_CMD "/usr/bin/find $*"; }
mkdir_s        () { $PM_SU_CMD "/bin/mkdir -p $1"; }
rm_s           () { $PM_SU_CMD "/bin/rm $*"; }