<p>您的代码中有几个错误,例如,没有新行发送到子进程。在</p>
<p>主要问题是<code>openssl</code>直接从终端获得密码短语(就像Python中的<code>getpass.getpass()</code>)。请参见<a href="http://pexpect.readthedocs.org/en/latest/FAQ.html#whynotpipe" rel="nofollow">Why not just use a pipe (popen())?</a>中的第一个原因:</p>
<blockquote>
<p>First an application may bypass stdout and print directly to its
controlling TTY. Something like SSH will do this when it asks you for
a password. This is why you cannot redirect the password prompt
because it does not go through stdout or stderr.</p>
</blockquote>
<p>提供伪tty的<code>pexpect</code>在这种情况下可以正常工作:</p>
<pre><code>#!/usr/bin/env python
import sys
from pexpect import spawn, EOF
pass_phrase = "dummy pass Phr6se"
common_name = "example.com"
email = "username@example.com"
keyname, certname = 'server.key', 'server.crt'
cmd = 'openssl req -x509 -newkey rsa:2048 -rand /dev/urandom '.split()
cmd += ['-keyout', keyname, '-out', certname, '-days', '180']
child = spawn(cmd[0], cmd[1:], timeout=10)
child.logfile_read = sys.stdout # show openssl output for debugging
for _ in range(2):
child.expect('pass phrase:')
child.sendline(pass_phrase)
for _ in range(5):
child.sendline('.')
child.sendline(common_name)
child.sendline(email)
child.expect(EOF)
child.close()
sys.exit(child.status)
</code></pre>
<p>另一种方法是尝试使用<code>-passin</code>选项来指示<code>openssl</code>从不同的源(stdin、文件、管道、envvar、命令行)获取密码短语。我不知道它是否与<code>openssl req</code>命令一起工作。在</p>