使用 PIPE 打开的子进程仍在从终端读取输入

Subprocess opened with PIPE still reading input from terminal

Python应用程序

我的 Python 3.6.8 应用程序 运行s 在 CentOS 7.6 上,并且:

子进程

打开命令

我使用以下命令从主线程启动子进程:

launch_cmd = "{} {} {} {}".format(path_of_compiled_binary, opt1, opt2, opt3)
self.myproc = subprocess.Popen(launch_cmd.split(), shell=False,
    cwd=self.testing_dir, close_fds=True, stdin=subprocess.PIPE,
    stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env,
    bufsize=1, universal_newlines=True, preexec_fn=self.ignore_sigint)

写入命令

我尝试给子进程命令

cmd = self.generate_cmd()
cmd = cmd + "\n"
bytes_sent = self.myproc.stdin.write(cmd)
self.myproc.stdin.flush()

文件描述符

`

lr-x------. 1 demo demo 64 Jun  5 10:44 0 -> pipe:[58635]
l-wx------. 1 demo demo 64 Jun  5 10:44 1 -> pipe:[58636]
l-wx------. 1 demo demo 64 Jun  5 10:44 2 -> pipe:[58636]
lr-x------. 1 demo demo 64 Jun  5 10:44 3 -> /dev/null
lr-x------. 1 demo demo 64 Jun  5 10:44 4 -> path_of_compiled_binary
lr-x------. 1 demo demo 64 Jun  5 10:44 5 -> /dev/tty
l-wx------. 1 demo demo 64 Jun  5 10:44 6 -> /dev/tty
lrwx------. 1 demo demo 64 Jun  5 10:44 7 -> socket:[59509]
lrwx------. 1 demo demo 64 Jun  5 10:44 8 -> /dev/ttyACM0
lr-x------. 1 demo demo 64 Jun  5 10:44 9 -> /tmp/par-64656d6f/temp-15579/inc/lib/PDL/IO/Pic.pm

子进程从 tty 读取,而不是 stdin

子进程打开2个文件描述符到/dev/tty:

lr-x------. 1 demo demo 64 Jun  5 10:44 5 -> /dev/tty
l-wx------. 1 demo demo 64 Jun  5 10:44 6 -> /dev/tty
  • @that-other-guy 建议子进程从其中一个而不是标准输入中读取。
  • 好像是5,因为它的模式是只读的?

/usr/bin/script实用程序

来自@that-other-guy 的另一个建议:

  • 使用script启动子进程。
  • script 实用程序旨在将 shell 会话捕获到实时记录中。
  • -c 选项生成任何给定命令而不是 shell。
  • 为文件参数提供 /dev/null 表示忘记成绩单。

使用脚本重新编码:

launch_cmd = "{} {} {} {}".format(path_of_compiled_binary, opt1, opt2, opt3)
script_argv = ["/usr/bin/script", "-c", launch_cmd, "/dev/null"]
self.myproc = subprocess.Popen(script_argv, shell=False,
    cwd=self.testing_dir, close_fds=True, stdin=subprocess.PIPE,
    stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env,
    bufsize=1, universal_newlines=True, preexec_fn=self.ignore_sigint)

工作原理

  • script 生成子进程并在伪终端中与其交互。
  • script 从管道中读取标准输入并将其回显到其伪终端以供子进程读取。
  • 现在子进程是否在 5 上读取终端而不是在 0 上读取标准输入并不重要。

这个改动解决了这个问题。子进程现在从应用程序接收命令。