与Python中子进程打开的`/dev/tty`进行交互

TSG*_*TSG 4 python openssl subprocess tty

我有一个 python 脚本,用于subprocess.Popen启动目标程序:网络服务器。我想与目标进行交互,因此我将stdin,stdoutstderr分配给管道,现在我可以读取和写入这些管道。

现在,网络服务器链接 OpenSSL 库以进行 TLS 处理。作为 TLS 处理的一部分,它会打开证书并提示输入密码。一般来说,输入密码并按 Enter 键后,网络服务器就会开始提供服务。现在,正如您可能已经猜到的那样,我想从 python 脚本输入此密码。通常,我需要做的就是写入服务器的stdin. 然而,有一个问题。当 OpenSSL 提示输入并读取密码时,它不使用stdin/ stdout。它会打开/dev/tty并使用它。结果我必须输入密码并手动输入。

下图展示了这种情况。

程序设置

lsof下面,您可以看到服务器输出的片段:

memcached 25279 USER    0r  FIFO   0,13      0t0  7771739 pipe
memcached 25279 USER    1w  FIFO   0,13      0t0  7771740 pipe
memcached 25279 USER    2w  FIFO   0,13      0t0  7771740 pipe
memcached 25279 USER    3r   REG    8,1     3414  3414276 ....key.pem
memcached 25279 USER    4r   CHR    5,0      0t0       13 /dev/tty
memcached 25279 USER    5w   CHR    5,0      0t0       13 /dev/tty
Run Code Online (Sandbox Code Playgroud)

有没有办法拦截/dev/tty对服务器的调用,以便我可以直接从脚本写入它?

kma*_*ork 5

通过使用 pty - 伪终端来实现您所描述的内容的标准方法。pty 看起来与普通 tty 完全相同,不同之处在于它是由软件而不是实际终端或终端仿真器控制的。

\n

在您的情况下,您可以轻松使用ptypython 标准库中的模块,它提供了一些使用 pty 的实用程序。具体看pty.spawn()函数:

\n
\n

生成一个进程,并将其控制终端与当前进程\xe2\x80\x99s标准io连接。这通常用于阻止那些坚持从控制终端读取数据的程序。预计 pty 后面生成的进程最终将终止,并且当它生成时将返回。

\n
\n

用法示例:

\n
import subprocess, sys\n\nopenssl_cmd = [\'openssl\', \'foo\', \'bar\']\np = subprocess.Popen([sys.executable, \'-c\', \'import pty, sys; pty.spawn(sys.argv[1:])\', *openssl_cmd])\np.stdin.write(\'password\\n\')\nprint(p.wait())\n
Run Code Online (Sandbox Code Playgroud)\n

在此示例中,我们不是直接运行 openssl,而是使用 运行它spawn,这意味着我们写入进程的 stdin 的任何内容都将由 openssl 从其/dev/tty.

\n