运行进程发送标准输入并获取标准输出

4

我有一个可以运行的c++编译代码,称之为run_process.

为了描述run_process,它是一段无限循环/while True等待文本输入的代码,并进行文本预处理,然后在输出中打印预处理的输入:

run_process

我想知道是否可以发送命令/请求将输入/STDIN文本发送到正在运行的进程并获取输出文本,目前我想避免编辑run_process并找到一个“外部”解决方案。

我尝试使用此处提出的解决方案:https://serverfault.com/a/178470 并运行:

echo "test"  > /proc/2657677/fd/0
echo "test\n"  > /proc/2657677/fd/0
echo -ne "test\n"  > /proc/2657677/fd/0

然后得到了这个:

这里输入图片描述

我不理解输出结果,就好像它不能模拟ENTER键一样,甚至无法打印紧贴“Input string”旁边的文本,因为当我按下ENTER键时,输出中什么都没有:

这里输入图片描述

如果您有任何解决方案,即使使用Python或任何其他语言,所有解决方案都将很有趣。

更多细节,请注意代码run_process使用C++ readline函数:

char* input = readline("Input string: ");

从这里的第90行开始:https://opengrm.org/doxygen/thrax/html/rewrite-tester-utils_8cc_source.html#l00245,如果需要更多信息,您可以查看我所称的“run_process”代码实际上在第247行。
1个回答

3
readline库不仅可以读取单行文本,还有更多功能。虽然我不清楚它在何种情况下使用哪些规则,但如果告诉它存在终端,它会启用诸如行编辑和命令行历史记录等功能。
如果您启动程序run_process,它的stdinstdout流通常连接到运行shell的终端。这可能是一个实际终端或更可能是一个伪终端。这样的伪终端有一个主控端,由您正在使用的终端模拟器(例如xterm)控制,以及一个客户端,用作前台进程在该终端中运行时的stdinstdout
如果您写入/proc/.../fd/0文件,则是写入了伪终端的客户端端。这将绕过通常由伪终端驱动程序执行的所有终端功能。相反,数据会像写入一样发送到进程中。 readline库知道它连接到一个伪终端,并使用其功能来检测ENTER键按下(这使得在readline中可以使用多行“行”)。这里的关键部分是,readline不仅依赖于输入字符流进行换行,而且还依赖于(伪)终端功能。这就是为什么直接写入/proc/.../fd/0(绕过这些功能)与readline结合使用不起作用的原因。
现在我认为您有几个选项(可能还有更多,但这些是我想到的):
  • Don't use readline, but directly read from stdin and break lines on newline characters. You will lose all the cool features from readline though. If your program is designed to only be used with generated input, this might not be a problem, but if the program should also feature a good interactive input you probably don't want to do without readline.

  • Don't use a pseudo terminal for the input stream. You can instead use for example a fifo special file like this

    $ mkfifo myfifo
    $ tail -f myfifo | ./run_process 
    

    and send data to the process with

    $ echo "test" > myfifo
    

    and finally delete the fifo again using rm myfifo. The tail -f command is used to keep the fifo open between different echos.

  • use a tool like socat for creating an additional pseudo terminal for which you have control on the master side:

    $ tty
    $ socat STDIO,raw,echo=0 SYSTEM:./run_process,pty,stderr
    

    and write to the process by

    $ echo "test" > /dev/pts/<number_returned_by_the_above_tty_command>
    

    With socat you also have a lot of different options. If you change the STDIO source to a different connection option of socat, you can easily make the run_process program for example listen on tcp connections or unix domain sockets, which also can be used for two way data transfer.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接