在脚本中使用无需密码的sudo

57

由于某些原因,作为用户,我需要运行一个名为 script.sh 的脚本而不使用sudo,但该脚本需要root权限才能正常工作。
我发现唯一的解决办法是将sudo放在script.sh内部。举例来说:

script.sh :

#!/bin/sh
sudo apt-get update

当然,如果我执行这个脚本,会弹出提示要求我输入密码。然后我将以下内容添加到我的sudoers文件中(放在最后以覆盖其他所有设置):

user ALL=(ALL:ALL) NOPASSWD:/path/to/script.sh

顺便说一下,我也尝试了这行代码:

user ALL=(ALL) NOPASSWD:/path/to/script.sh

(我觉得我没有完全理解它们的区别)

但是如果我不使用sudo来执行这个脚本,这并不能解决我的问题:

# ./script.sh
[sudo] password for user: 
# sudo ./script.sh
Starts updating...

好的,那么我就对自己说,“好的,这意味着如果像我一样在sudoers中引用了一个文件,只有在使用sudo调用它时才能无提示工作,这不是我想要的方式。”
所以,好吧,我创建另一个名为script2.sh的脚本,如下所示:

script2.sh

#!/bin/sh
sudo /path/to/script.sh
实际上它起作用了。但我并不完全满意这个解决方案,尤其是我每个命令都需要使用两个脚本的事实。这篇帖子旨在帮助遇到同样问题并正在寻找解决方法的人们(我没有找到一个好的帖子),也许你们有更好的解决方案。请随意分享你的想法!
编辑1:
我想强调一下,这个“apt-get update”只是一个例子,与我的脚本实际情况相去甚远。我的脚本有很多命令(其中一些涉及到root访问的配置文件),而解决方案不能只是“好吧,直接用apt-get做就可以了”。
一个例子的原则是为了帮助理解,而不是简化一般问题的答案的借口。

9
NOPASSWD:/path/to/script.sh 的意思是您可以无需输入密码使用 sudo /path/to/script.sh 命令。但这并不意味着脚本可以在不输入密码的情况下使用 sudo 命令。 - Barmar
@Barmar 这可能是一个答案。 - hek2mgl
@hek2mgl 我注意到他在问题中已经有类似的内容了。 - Barmar
8个回答

27

来自我的博客:IDMRockstar.com:

问题在于,有时候我需要以root身份运行命令。以下是我用简单粗暴的方式完成此操作而不泄露密码的方法:

#! /bin/bash
read -s -p "Enter Password for sudo: " sudoPW
echo $sudoPW | sudo -S yum update

这种方式会提示用户输入密码(并隐藏输入),随后将其传递到需要的命令中,因此我不必以root身份运行整个脚本 =)

如果您有更好的方法,我很乐意听听!我并不是shell脚本编写专家。

祝福!

. :Adam


1
这个答案与一年前Eaton Emmerich的答案非常相似,也许可以将read -s -p部分添加到其中作为在文件中存储密码的替代方法。 - Bob
请注意,在 Bourne shell 中不支持 read 命令的 -s 选项,只有 bash 支持。因此,请勿在脚本开头使用错误的 shebang,以免混淆。 - Russ Bateman

22
如果您想在不需要密码的情况下运行sudo /usr/bin/apt-get update,则需要具有sudoers条目:
user ALL=(ALL:ALL) NOPASSWD:/usr/bin/apt-get update

在代码中,user 应该被替换为用户的名称或ID。(在更复杂的情况下,user 可以被组或别名替换。有关详细信息,请参见 man sudoers。)

对于脚本作为整体的更大问题,有两种可能的方法:

方法1

对于脚本中需要使用 sudo 的每个命令,在 sudoers 中创建一行专门针对该命令。在这种情况下,可以正常调用脚本:

./script1.sh

方法二

sudoers中为整个脚本添加一行。这样做后,单独的命令就不需要使用sudo了。但是,必须使用sudo来启动脚本,例如:

sudo ./script.sh

2
apt-get只是一个例子。实际上,我的脚本有很多命令……我不会傻到写一个和apt-get完全一样的脚本! - Nilexys
我添加了一行 user ALL=(ALL:ALL) NOPASSWD:/path-to-script,这似乎对脚本内的 sudo sshfs ... 命令起作用。 - FreelanceConsultant
1
如果不明显的话,您必须将sudoers条目开头的user替换为实际想要能够运行命令的人的用户名,或者使用%group允许该组中的所有用户(例如,%sudo将允许任何在sudo组中的用户执行命令而无需密码)。 - Tobias J
1
@TobiasJ 很好的观点。我已经更新了答案,提到了组和别名。 - John1024

13

如果您的密码并不需要非常安全(例如公司中的某个测试服务器等),您可以通过以下命令在脚本中提升至sudo权限:

echo YourPasswordHere | sudo -S Command

即便如此,提示信息仍会输出“输入密码”文本。因此不要期望它很整洁。

请参阅Askubuntu文章


7
正如您注意到的那样,必须出现在sudoers配置中的文件是由sudo启动而不是运行sudo的文件。
话虽如此,我们经常做的是,像下面这样:
user ALL=(ALL:ALL) NOPASSWD:/path/to/script.sh

sudo配置中,script.sh包含脚本要执行的所有命令。
然后我们定义一个Bash函数或别名,使得script.sh能够实际执行。
sudo /path/to/script.sh

唯一的问题是,如果有些命令不能以root身份运行,你需要在脚本中插入一些su - user -c "command"命令。

2
在新的/etc/sudoers.d/apt-get文件中,只需放入一行:
user ALL=(ALL:ALL) NOPASSWD:/usr/bin/apt-get update

需要提供可执行文件的完整路径。
然后在脚本中使用以下内容:
sudo apt-get update

这里不需要完全指定名称。Sudo使用PATH环境变量来解析可执行文件。

在更改和检查sudoers配置时,请确保保留另一个root会话以进行错误恢复。


不要使用第二个根用户,而应该使用 visudo 命令。这就是它的作用。此外,这种方法允许任何人在不需要密码的情况下更新系统。 - Ingo Bürk

2

我建议您查看sudo环境变量 - 具体来说,您可以使用(并检查)$SUDO_USER。以sudo身份调用您的脚本(sudoers中的1个条目),然后作为SUDO_USER执行用户操作和作为root执行根操作。


1

如Basilevs所提到的,您需要将用户添加到sudoers文件中,以避免脚本中的sudo命令被卡在等待密码的状态。

在Ubuntu 16上,有一种更简单的方法:只需将用户添加到sudo组即可,像这样:

sudo usermod -aG sudo *username*

从那时起,它应该像魔术一样工作。
注意:
这仅在文件/etc/sudoers中包含以下行的条件下才有效:
%sudo ALL=NOPASSWD: ALL
(此类行在组级别上授予无需密码的sudo特权,在此情况下为sudo组)
(如果此行不存在且您想要添加它,请确保使用visudo)

1
仍然提示输入密码。 - keith
这里有两个不同的事情: (1)命令“sudo usermod -aG sudo username”将sudo权限授予用户username。 (2)但是,它本身并没有为该用户提供sudo无密码特权。为了实现这一点,在/etc/sudoers文件中必须存在以下行:“%sudo ALL =(ALL:ALL)ALL”(此行在组级别上授予无密码特权)。这是我帖子的前提条件。我希望这样可以澄清。 - Varus Septimus
谢谢您的澄清。如果您能更新您的答案,我就可以取消我的踩赞并转为点赞 :-) - keith

-1

简单地说,为了以root身份执行命令,您必须使用su(即使sudo也使用su)。 只要您成功执行sudo ./script2.sh,就可以改为: sudo su "#" //在此处作为root的命令 "#" exit //在此处使用命令 您可以将其作为名为sudo的shell函数,但我认为没有其他更好的方法,但是对于脚本inti,rc android等来说也是如此。 必须整洁;)

但是,这需要您将NOPASSWD:su放入其中,这确实非常安全。

任何方式都缺少POISX权限原则,即过滤,请勿将某些内容启用于所有用户或反之亦然,简单地调用sudo而不需要额外的东西:

chown root script.sh
chmod 0755 script.sh
chgrp sudo script.sh

"将.sh文件的所有者更改为root" "将其设置为其他人只读和可执行" "并将其放入sudo组中" 当然是在sudo下操作 就这样"


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接