【发布时间】:2021-03-11 04:38:43
【问题描述】:
我正在编写一个库,它应该在子进程中执行程序,捕获输出,并以逐行(字符串向量)的方式使输出可用。 STDOUT 有一个向量,STDERR 有一个向量,“STDCOMBINED”有一个向量,即所有输出都按照程序打印的顺序。子进程通过两个管道连接到父进程。一根管子用于 STDOUT,一根管子用于 STDERR。在父进程中我从管道的读取端读取,在子进程中我dup2()'ed STDOUT/STDERR 到管道的写入端。
我的问题: 我想捕获 STDOUT、STDERR、和“STDCOMBINED”(=两者都按它们出现的顺序)。但是组合向量中的顺序与原来的顺序不同。
我的方法: 我迭代直到两个管道都显示 EOF 并且子进程退出。在每次迭代中,我从 STDOUT 中准确读取一行(或 EOF),从 STDERR 中准确读取一行(或 EOF)。到目前为止,这有效。但是当我在父进程中捕获这些行时,STDOUT 和 STDERR 的顺序不一样,就像我在 shell 中执行程序并查看输出一样。
为什么会这样,我该如何解决这个问题?这可能吗?我知道在子进程中我可以将 STDOUT 和 STDERR 都重定向到一个管道,但我需要分别使用 STDOUT 和 STDERR,以及“STDCOMBINED”。
PS:我熟悉 libc/unix 系统调用,如dup2()、pipe() 等。因此我没有发布代码。我的问题是关于一般方法,而不是特定语言的编码问题。我在 Rust 中针对原始 libc 绑定进行此操作。
PPS:我做了一个简单的测试程序,它混合了 5 个标准输出和 5 个标准错误消息。这足以重现问题。
【问题讨论】:
-
没有定义发出标准输出和标准错误的顺序。它们是独立的流。
-
有什么办法可以解决这个问题吗?例如禁用子进程的标准输出缓冲区?
-
至少,父级需要
select或poll管道来检测何时有新数据可用。您只需通过读取 “从 STDOUT 中准确地读取一行(或 EOF)和从 STDERR 中准确地读取一行(或 EOF)。”