【问题标题】:Interact with `/dev/tty` opened by subprocess in python与python中子进程打开的`/dev/tty`交互
【发布时间】:2020-06-10 15:41:55
【问题描述】:

我有一个 python 脚本,它使用subprocess.Popen 来启动一个目标程序:一个网络服务器。我想与目标进行交互,所以我将stdinstdoutstderr 分配给管道,现在我可以对这些管道进行读写了。

现在,网络服务器链接 OpenSSL 库以进行 TLS 处理。作为 TLS 处理的一部分,它会打开一个证书并提示输入密码。通常,在输入密码并按回车后,网络服务器开始提供服务。现在,您可能已经猜到了,我想从 python 脚本中输入这个密码。通常,我需要做的是写入服务器的stdin。但是,有一个问题。 OpenSSL在提示和读取密码时,不使用stdin/stdout。它会打开 /dev/tty 并使用它。结果,我必须输入密码并手动输入。

下图说明情况。

在下面,您可以看到服务器的lsof 输出的sn-p:

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

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

【问题讨论】:

    标签: python openssl subprocess tty


    【解决方案1】:

    使用 pty(伪终端)实现您所描述的内容的标准方法。 pty 看起来和普通的 tty 完全一样,除了它是由软件而不是实际终端或终端仿真器控制的。

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

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

    示例用法:

    import subprocess, sys
    
    openssl_cmd = ['openssl', 'foo', 'bar']
    p = subprocess.Popen([sys.executable, '-c', 'import pty, sys; pty.spawn(sys.argv[1:])', *openssl_cmd])
    p.stdin.write('password\n')
    print(p.wait())
    

    在本例中,我们不是直接运行 openssl,而是使用spawn 运行它,这意味着我们写入进程的标准输入的任何内容都将被 openssl 从其/dev/tty 读取。

    【讨论】:

    • 甜蜜!我从没想过会得到答案,尽管我确信一定有一些模块/软件可以做到这一点!我将对此进行测试并回复您。谢谢
    • 太棒了!运气好吗?
    • 我想是的。
    猜你喜欢
    • 2012-07-26
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 2021-01-03
    • 1970-01-01
    • 2017-07-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多