【问题标题】:Run linux command from python which needs user input从需要用户输入的python运行linux命令
【发布时间】:2018-10-25 12:36:26
【问题描述】:

我有以下 python 代码:

import subprocess
p=subprocess.Popen(["openssl","genrsa","-aes256","-out","ise.key.pem","2048"],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
inputdata="123456"
p.communicate(input=inputata)
p.communicate(input=inputata)

以上代码的输出是:

    pan@pan:~/python-scripts$ Generating RSA private key, 2048 bit long modulus
........................+++
...................................+++
e is 65537 (0x10001)
Enter pass phrase for ise.key.pem:
User interface error
140617148802712:error:0906906F:PEM routines:PEM_ASN1_write_bio:read key:pem_lib.c:379:

我希望输入应该由 python 提供,不应该有任何用户交互:

我知道证书可以由 python pyOpenSSL 库生成,但我想使用普通的 linux 命令

我的python版本是

Python 2.7.12 (default, Dec  4 2017, 14:50:18) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "enter code here`license" for more information.

我看到了以下链接,但没有帮助

Python execute command line,sending input and reading output

如果你在 shell 中运行命令,它会运行如下:

pan@pan:~/python-scripts$ openssl genrsa -aes256 -out ise.key.pem 2048
Generating RSA private key, 2048 bit long modulus
..............................................................+++
..+++
e is 65537 (0x10001)
Enter pass phrase for ise.key.pem:
Verifying - Enter pass phrase for ise.key.pem:

【问题讨论】:

  • shell=True 允许解决错误输入您的进程:参数列表应为["openssl","genrsa","-aes256","-out","ise.key.pem","2048"]。但真正的问题是管道输入到密码输入例程并不总是有效。您必须在较低级别生成键盘事件。
  • 我建议您尝试上述方法,然后edit 您的问题删除关于 shell=True 的无用部分,这会使您的问题成倍增加。
  • 你见过这个吗? stackoverflow.com/a/165662/8765205

标签: python linux python-3.x python-2.7 openssl


【解决方案1】:

Jean-François Fabre 在他的评论中是对的:

但真正的问题是管道输入到密码输入例程并不总是有效。

但不是这个:

您必须在较低级别生成键盘事件。

虽然一般情况下确实如此,但在当前情况下,命令openssl genrsa … 提供了-passout stdinread the password from standard input 的选项:

openssl genrsa -aes256 -out ise.key.pem -passout stdin 2048

所以,这个 Python 脚本有效:

import subprocess
p=subprocess.Popen(["openssl","genrsa","-aes256","-out","ise.key.pem",
                    "-passout","stdin","2048"], stdin=subprocess.PIPE,
                                                stdout=subprocess.PIPE)
inputdata="123456"
p.communicate(input=inputdata)

请注意,不能以 timeout=None 多次调用communicate(),因为它会等待进程终止。但这也不是必须的,因为-passout stdin 命令不会要求验证,因此不需要再次输入密码。

【讨论】:

  • 如何在较低级别生成键盘事件?我试过“openssl genrsa -aes256 -out ise.key.pem -passout stdin 2048”,但没有用
  • @Pankaj Sheoran - 查看扩展答案。 在较低级别生成键盘事件会更麻烦且更不便携。
【解决方案2】:

我通常不喜欢这种任务的子流程......我更喜欢使用 pexpect 来模拟人类行为(输入数据......等等)。

这是一个完成这项工作的粗略示例

import pexpect

def main():
        inputdata="123456"
        c = pexpect.spawn("/usr/bin/openssl", ["genrsa","-aes256","-out","ise.key.pem","2048"])
        c.expect("Enter.*:")
        c.sendline(inputdata)
        c.expect("Verifying.*:")
        c.sendline(inputdata)
        c.expect(pexpect.EOF)
        c.close()
        c.kill(0)
        print "Done"

if __name__=='__main__':
        main()

【讨论】:

    猜你喜欢
    • 2016-01-03
    • 2022-10-15
    • 2014-08-31
    • 1970-01-01
    • 2020-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多