51

因此,我正在尝试使用子进程从 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 restartsudo 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 工作。

谢谢!

4

8 回答 8

29

尝试:

subprocess.call(['sudo', 'apach2ctl', 'restart'])

子进程需要访问真正的 stdin/out/err 才能提示您,并读取您的密码。如果将它们设置为管道,则需要自己将密码输入该管道。

如果你不定义它们,那么它会抓取 sys.stdout 等......

于 2009-02-19T23:11:30.500 回答
21

尝试给出 apache2ctl 的完整路径。

于 2009-02-19T22:46:38.313 回答
16

另一种方法是让您的用户无密码sudo user

在命令行中键入以下内容:

sudo visudo

然后添加以下内容并将其替换为<username>您的:

<username> ALL=(ALL) NOPASSWD: ALL

这将允许用户执行sudo命令而无需询问密码(包括由所述用户启动的应用程序。虽然这可能是一个安全风险

于 2014-07-09T00:06:59.177 回答
9

我将它用于 python 3.5。我是使用进程模块完成的。使用这样的密码是非常不安全的。

subprocess模块将命令作为字符串列表,因此可以使用 split() 预先创建一个列表,或者稍后传递整个列表。阅读文档以获取更多信息。

我们在这里所做的是回显密码,然后使用管道通过“-S”参数将其传递给 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() 
于 2018-04-05T10:34:35.960 回答
6

你必须像这样使用 Popen:

cmd = ['sudo', 'apache2ctl', 'restart']
proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

它需要一个列表。

于 2009-02-19T22:35:06.687 回答
5

最安全的方法是预先提示输入密码,然后将其输入命令。提示输入密码将避免将密码保存在代码中的任何位置,并且它也不会显示在您的 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())
于 2019-05-29T13:49:24.140 回答
3

我尝试了所有解决方案,但没有奏效。想用 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

或者安装午夜指挥官

echo $MY_SUDO_PASS | sudo -S apt-get install mc

使用 sudo 启动午夜指挥官

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)

希望能帮助到你。

于 2018-03-15T16:49:49.427 回答
3

要以 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",
)
于 2020-07-01T20:22:41.213 回答