所以我试图让一个进程在使用子进程的python脚本中作为超级用户运行。在ipython shell中类似于
proc = subprocess.Popen('sudo apach2ctl restart',
shell=True, stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
工作正常,但只要我将其粘贴到脚本中,我就会开始:sudo: apach2ctl: command not found
。
我猜这是由于sudo处理ubuntu环境的方式。 (我也尝试了sudo -E apche2ctl restart
和sudo env path=$PATH apache2ctl restart
无效)
所以我的问题基本上是,如果我想以超级用户身份运行apache2ctl restart
,在需要时提示用户输入超级用户密码,我应该怎么做呢?我无意在脚本中存储密码。
编辑:
我尝试将命令作为字符串传递并标记为列表。在python解释器中,使用字符串我将正确地获得密码提示(仍然不像我原来的问题那样在python脚本中工作),列表只是给出了sudo的帮助屏幕。
编辑2:
所以我收集到的是,当shell = True时,Popen将使用一些命令作为字符串,需要
proc = subprocess.Popen(['sudo','/usr/sbin/apache2ctl','restart'])
没有'shell = True'让sudo工作。
谢谢!
答案 0 :(得分:23)
尝试:
subprocess.call(['sudo', 'apach2ctl', 'restart'])
子进程需要访问真正的stdin / out / err才能提示你,并读入你的密码。如果将它们设置为管道,则需要自己将密码提供给该管道。
如果你没有定义它们,那么它会抓取sys.stdout等等......
答案 1 :(得分:14)
尝试提供apache2ctl的完整路径。
答案 2 :(得分:11)
另一种方法是让您的用户无密码sudo user
。
在命令行上键入以下内容:
sudo visudo
然后添加以下内容并用您的<username>
替换:
<username> ALL=(ALL) NOPASSWD: ALL
这将允许用户执行sudo
命令而无需询问密码(包括由该用户启动的应用程序。这可能存在安全风险
答案 3 :(得分:5)
你必须像这样使用Popen:
cmd = ['sudo', 'apache2ctl', 'restart']
proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
它需要一个列表。
答案 4 :(得分:4)
我将它用于python 3.5。我是使用 subprocess 模块完成的。使用这样的密码非常不安全。
subprocess模块将命令作为字符串列表,因此要么事先使用 split()创建列表,要么稍后传递整个列表。阅读文档以获取更多信息。
我们在这里做的是回显密码,然后使用管道,我们通过&#39; -S&#39;将其传递给sudo。参数。
#!/usr/bin/env python
import subprocess
sudo_password = 'mysecretpass'
command = 'apach2ctl restart'
command = command.split()
cmd1 = subprocess.Popen(['echo',sudo_password], stdout=subprocess.PIPE)
cmd2 = subprocess.Popen(['sudo','-S'] + command, stdin=cmd1.stdout, stdout=subprocess.PIPE)
output = cmd2.stdout.read().decode()
答案 5 :(得分:2)
我尝试了所有解决方案,但没有奏效。想要使用Celery运行长时间运行的任务,但是对于这些我需要使用subprocess.call()运行sudo chown命令。
这对我有用:
要添加安全环境变量,请在命令行中键入:
export MY_SUDO_PASS="user_password_here"
测试它是否正常工作:
echo $MY_SUDO_PASS
> user_password_here
要在系统启动时运行它,请将其添加到此文件的末尾:
nano ~/.bashrc
#.bashrc
...
existing_content:
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
...
export MY_SUDO_PASS="user_password_here"
您可以稍后在此处添加所有环境变量密码,用户名,主机等。
如果你的变量准备就绪,你可以运行:
更新:
echo $MY_SUDO_PASS | sudo -S apt-get update
或安装Midnight Commander
echo $MY_SUDO_PASS | sudo -S apt-get install mc
用sudo启动Midnight Commander
echo $MY_SUDO_PASS | sudo -S mc
或者从python shell(或Django / Celery),以递归方式更改目录所有权:
python
>> import subprocess
>> subprocess.call('echo $MY_SUDO_PASS | sudo -S chown -R username_here /home/username_here/folder_to_change_ownership_recursivley', shell=True)
希望它有所帮助。
答案 6 :(得分:1)
要以root用户身份运行命令并在命令提示符处传递密码,您可以这样做:
import subprocess
from getpass import getpass
ls = "sudo -S ls -al".split()
cmd = subprocess.run(
ls, stdout=subprocess.PIPE, input=getpass("password: "), encoding="ascii",
)
print(cmd.stdout)
例如,可能是这样的:
import subprocess
from getpass import getpass
restart_apache = "sudo /usr/sbin/apache2ctl restart".split()
proc = subprocess.run(
restart_apache,
stdout=subprocess.PIPE,
input=getpass("password: "),
encoding="ascii",
)
答案 7 :(得分:0)
最安全的方法是事先提示输入密码,然后将其输入命令。提示输入密码将避免将密码保存在代码中的任何位置,并且也不会显示在bash历史记录中。这是一个示例:
from getpass import getpass
from subprocess import Popen, PIPE
password = getpass("Please enter your password: ")
# sudo requires the flag '-S' in order to take input from stdin
proc = Popen("sudo -S apach2ctl restart".split(), stdin=PIPE, stdout=PIPE, stderr=PIPE)
# Popen only accepts byte-arrays so you must encode the string
proc.communicate(password.encode())