以root用户身份运行Python脚本

7
我有以下脚本:
#!/usr/bin/env python                                                           

import sys                                                                      
import pyttsx                                                                   

def main():                                                                     
        print 'running speech-text.py...'                                       
        engine = pyttsx.init()                                                  
        str = "Hi..."                                    
        if len(sys.argv) > 1:                                                   
                str = sys.argv[1]                                               
        engine.say(str)                                                         
        engine.runAndWait()                                                     

if __name__ == '__main__':                                                      
        main() 

我将其放置在 /usr/bin/speech-test.py 中。
我还赋予了它可执行权限并将其所有权分配给 root 用户:
sudo chown root:root /usr/bin/speech-test.py
sudo chmod 4755 /usr/bin/speech-test.py

然而,如果我只运行speech-test.py,这个脚本只能以sudo speec-test.py的方式正确运行。否则它会抱怨找不到一堆ALSA库文件。

我是否缺少某些东西以使我的脚本具有root权限运行?


问题可能出在哈希bang中的env,但我需要测试一下。你是用./speech-test.py这样的方式调用它,而不是用python speech-test.py吗?因为后者会以用户权限运行Python。 - m.wasowski
just speech-test.py no ./ - moesef
3
在Linux上无法对脚本设置SUID权限。如果需要,可以编写一个二进制启动器或使用nopasswd sudo。任何以hashbang开头的可执行文件都是脚本。 - x3al
1
TIL:https://dev59.com/questions/wGMl5IYBdhLWcg3wFjkC + http://www.faqs.org/faqs/unix-faq/faq/part4/section-7.html 感谢 @x3al - m.wasowski
1
如果您不想使用nopasswd sudo,则可以使用类似cx_Freeze的工具从Python脚本创建二进制可执行文件。 - jfs
显示剩余3条评论
5个回答

13

你想让脚本以root身份运行,即使没有使用sudo命令也能够运行吗?为此,您需要在脚本上设置setuid位,可以使用以下命令:sudo chmod u+s program。但是,出于安全原因,大多数Unix发行版仅允许对二进制文件执行此操作,而不是脚本。总的来说,这确实不是一个好主意。

如果您想要以root身份运行此脚本,则必须以sudo方式运行。或者,您可以创建一个运行您的脚本的二进制文件,以便可以在该二进制包装器上设置setuid位。这个相关问题解释得更加详细。

还有一个好的主意是检查有效用户ID,如果不是root,则停止运行。为此,请将以下内容添加到顶部(感谢@efirvida提供的提示!)

if not os.geteuid() == 0:
    sys.exit("\nOnly root can run this script\n")
也许你的用户和root使用不同版本的Python,具有不同的Python路径和不同的库集。
尝试这个:
command -v python
sudo command -v python

如果这两个命令的结果不一致,那么您需要更改用户设置以使用相同版本的 python(具有ALSA库的版本),或在脚本的第一行硬编码Python版本。

还可以尝试在脚本中添加print sys.path行,并使用您的用户和sudo运行并比较。可能会得到不同的结果。您可能需要调整用户的PYTHONPATH变量。

没有必要将脚本所有者设置为root,并使用sudo运行它。您只需要正确配置pythonPYTHONPATH即可。


1
which 更改为 command -v。使用 command -v 而不是 which 有几个原因。如果您不想更改,请还原。另请参见 如何在 shell 脚本中检查命令是否存在?如何从 Bash 脚本中检查程序是否存在? - jww
除非软件包是全局安装的(可由sudo访问),否则这将无法工作,并且有一种趋势是将软件包保留在本地。 - PeterT

0

我不知道,但是用#!/bin/python替换#!/usr/bin/env python对我有效。


1
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community
(Ubuntu 22.04)这对我没用。我得到了相同的“权限被拒绝”错误。 - lonelyjoe
你是否有多个Python解释器?如果是的话,你可能需要指定版本,例如 python3 - hDmtP

0

我不太确定这是否是一个好的方法。我在arch linux上尝试过它,它可以正常工作。告诉我你的想法。 如果您编写一个脚本以不同的系统组身份执行.py文件,则该组可以拥有python解释器并具有指定的root权限。

mkdir roottest && cd roottest
sudo cp /usr/bin/python<ver> ./
sudo groupadd -r rootpython
sudo usermod -a -G rootpython <user>
newgrp rootpython
sudo chown root:rootpython python<ver>
sudo chmod 750 $bin                       #that way a normal user can't rwx the python interpreter and the rootpython group cant write.
sudo setcap <caps> ./python<ver>              #now the group has specify caps allowing it to act like root
sudo getcap ./python<ver>
sudo sh
touch rootfile && echo "original text" > rootfile

以普通用户身份打开新提示符

newgroup rootpython
cd roottest && ./python<ver>
>> open('rootfile', 'w').write("different text")
sudo cat rootfile

如果使用得当,此方法比sudo更安全,因为Python只能执行您允许的操作,而不能完全控制系统。缺点是必须要么复制解释器,要么不允许常规用户组使用它。请勿像这样运行所有Python代码,如果不需要,这是一个很大的漏洞。cap_net_admin+ep将允许您更改内核变量ip_forward,对于上面的示例,您需要cap_dac_override+ep。您还可以创建一个属于rootpython组的新用户,这样您就不能仅通过newgrp rootpython来进入该组,而需要输入新用户的密码。


0
你应该以root身份运行 sudo -i 或者 su

欢迎来到Stack Overflow!这里的问题是为什么在不以root身份执行时,相关程序无法正常工作。仅仅说“以root身份执行”并不能解决这个问题。 - undefined

-4

它的运行权限与运行它的人相同。因此,如果您将其作为自己运行,则它不会具有 su 权限。您必须使用sudo进行操作。


如果您设置了粘着位(sticky bit),那就不是这样的,正如 OP 所尝试的那样。 - m.wasowski
哦,是的,我忘了那件事...对不起。 - Hot.PxL

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