在 PyCharm 中使用子进程执行 sudo 命令

Posted

技术标签:

【中文标题】在 PyCharm 中使用子进程执行 sudo 命令【英文标题】:Execute sudo commands with subprocess in PyCharm 【发布时间】:2018-12-15 21:44:05 【问题描述】:

我正在尝试从 Python 3 执行 sudo 命令。我通常使用子进程在 Python 中运行我的终端命令。已经有很多问题在讨论这个话题,但我找不到任何适合我的解决方案。

我的操作系统是 Ubuntu 18.04,我正在使用 Python 3.6 和 PyCharm。

无论我如何尝试,我都无法使用子进程输入密码。我的脚本在尝试输入 sudo 密码时总是卡住。在第一个答案之后,我意识到问题不在于我的代码,问题在于 PyCharm。从控制台运行它们时,以下所有尝试都可以正常工作,但是当我从 PyCharm 解释器运行它们时它们会卡住。以下是我尝试过的所有版本:

尝试 1:

import subprocess
sudo_password = b"myPassword\n"

print(subprocess.check_output('sudo -S echo success', shell=True, input=sudo_password)) #stuck here

这似乎是解决问题的最简单方法,但不知何故子进程无法输入密码,它总是会卡住,直到我终止进程。

尝试 2:

import subprocess
sudo_password = b"myPassword\n"

proc = subprocess.Popen('sudo -S echo success', shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
proc.stdin.write(sudo_password)
proc.stdin.flush()
print(proc.stdout.readlines()) #stuck here

在我的第二次尝试中,我尝试自己处理流媒体,但这似乎也不起作用。程序在读取 outstream 的行时会卡住。当我中止代码时,我收到以下错误消息,表明控制台已提示输入密码,但不知何故无法输入。

Traceback (most recent call last):
  File "/home/anon/sudo.py", line 7, in <module>
[sudo] password for anon:     print(proc.stdout.readlines()) #stuck here
KeyboardInterrupt

尝试 3:

我知道我可以将密码从终端输入 sudo 命令:

anon@anon:~$ echo myPassword | sudo -S echo success
[sudo] password for anon: success

所以我尝试使用子进程做同样的事情:

import subprocess
sudo_password = "myPassword"

print(subprocess.check_output("echo  | sudo -S echo success".format(sudo_password), shell=True)) #stuck here

但这种方法又一次像所有其他方法一样陷入困境。

尝试 4:

import subprocess
import os
sudo_password = "myPassword"

with open("temp.sh", 'w') as file:
    file.write("echo  | sudo -S echo success".format(sudo_password))

print(subprocess.check_output("sh temp.sh", shell=True)) #stuck here

os.remove("temp.sh")

所以在我最后一次绝望的尝试中,我认为如果我将命令放入 shell 文件并使用子进程执行它,我可能会成功,因为我不会将任何 sudo 命令直接输入到子进程。当我自己在终端中尝试时,效果很好:

anon@anon:~$ sh temp.sh 
[sudo] password for anon: success

但是 Python 脚本和以前一样卡在了同一个地方。

有谁知道这些尝试失败的原因以及我如何才能实现我的目标?在此先感谢:)

编辑:

有人给我链接了一篇关于这个主题的旧帖子,它使用 os 而不是 subprocess。 os 已被弃用,应该使用 subprocess 代替,这就是为什么我最初没有在这个问题中展示任何这些尝试,但是在使用 os 时它也会卡住:

import os
sudo_password = "myPassword"

p = os.system('echo  | sudo -S echo success'.format(sudo_password)) #stuck here

编辑 2:

好的,现在我发现,如果您使用以下命令从终端运行脚本,我的所有尝试以及第一个答案中的建议实际上都会起作用:

anon@anon:~$ python3 checksudo.py

所以问题似乎出在我的解释器 PyCharm 上。这也是我的问题对this question 独一无二的原因,因为他们的问题不是来自他们的口译员。

是否有人对如何使代码在 PyCharm 中工作有任何建议,或者我是否应该从控制台运行我的所有脚本?感谢您抽出宝贵时间。

【问题讨论】:

***.com/questions/13045593/… 第三次尝试中似乎缺少.format(sudo_password) Using sudo with Python script的可能重复 这是重复的,因为较早的问题称为“将 sudo 与 Python 脚本一起使用”,这正是您要问的。此外,那里的许多答案还包括使用子流程,而不是操作系统,这就是您说您忽略了旧问题的原因。 您是否考虑使用visudo 修复/etc/sudoers 文件以抑制密码提示?另外,由于 pexpect 旨在处理交互式 CLI (***.com/questions/39907546/…),您是否查看过 pexpect 而不是 subprocess? 【参考方案1】:

怎么样:

# coding=utf-8

from subprocess import Popen, PIPE

sudo_password = 'mypass'
command = 'echo success'.split()

p = Popen(['sudo', '-S'] + command, stdin=PIPE, stderr=PIPE,
          universal_newlines=True)
sudo_prompt = p.communicate(sudo_password + '\n')[1]
print('Done!')

当然,请确保在代码中输入正确的密码。

【讨论】:

还是不行。即使输入正确的密码,它也会卡在最后一行。当我在最后添加 print(sudo_promt) 时,它永远不会到达。 我运行了这个精确的剪切和粘贴代码(仅更改密码)并获得了所需的“成功”输出。 你为什么要打印?阅读代码;你必须使用communicate 我添加了一个print('Done!'),显示python代码没有被通信阻止。即使密码错误,只有实际的命令(回显成功)不起作用。 谢谢,如果您从控制台运行它们,您的建议以及我所有的尝试都会真正奏效。我的问题似乎是我的解释器 PyCharm。

以上是关于在 PyCharm 中使用子进程执行 sudo 命令的主要内容,如果未能解决你的问题,请参考以下文章

linux之sudo使用技巧汇总

Windows批处理 调用程序后 不等待子进程 父进程继续执行命令

如何使用 python 子进程模块将 sqlplus 作为 sudo 连接到 oracle 用户?

linux sudo下composer command not found的问题

sudo: cd: command not found

如果使用 python 和子进程从 pycharm 调用 gsutil 不起作用,“无法导入名称 _common”