在PyCharm中使用subprocess执行sudo命令

11

我正在尝试从Python 3执行sudo命令。我通常使用subprocess在Python中运行我的终端命令。已经有许多讨论此主题的问题,但我找不到适合我的解决方案。

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

无论我如何尝试,我都不能使用subprocess输入密码。我的脚本总是在尝试输入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

尝试三:

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

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

所以我尝试使用subprocess做同样的事情:

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文件中并使用subprocess执行它,那么我就有可能成功,因为我不会直接在subprocess中输入任何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上。这也是使我的问题与这个问题不同的原因,因为他们的问题并非起源于解释器。

有没有人有建议如何使代码在PyCharm中运行,或者我应该始终从控制台运行所有脚本?


1
https://dev59.com/G2cs5IYBdhLWcg3wMxNF - Lasith Niroshan
第三次尝试似乎缺少.format(sudo_password) - ducminh
可能是使用sudo运行Python脚本的重复问题。 - user4805123
这是一个重复的问题,因为旧问题被称为“使用sudo运行Python脚本”,这正是你所问的。此外,许多答案也包括使用子进程,而不是os,这就是你忽略旧问题的原因。 - user4805123
你考虑过使用visudo修复/etc/sudoers文件以抑制密码提示吗?此外,你是否考虑过使用pexpect而不是subprocess,因为pexpect旨在处理交互式CLI(https://dev59.com/_Jvga4cB1Zd3GeqP1mkx)? - tk421
1个回答

2

如何:

# 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)**时,它永远不会被执行到。 - Yannick
我添加了一个 print('Done!'),它显示 Python 代码没有被通信停止。即使密码错误,只有实际命令(echo success)不起作用。 - user4805123
谢谢你的建议,如果你从控制台运行它们,所有我的尝试和你的建议都可以生效。我的问题似乎在于我的解释器,PyCharm。 - Yannick
有趣的是,我在PyCharm中运行了这个。 - user4805123
你以root用户身份运行PyCharm吗? - Yannick
显示剩余4条评论

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