完全按照写入的方式读取外部进程的交错 stdout 和 stderr
Read an external process's interleaved stdout and stderr exactly as they are written
我正在使用 ProcessBuilder
启动 bash 进程。
我正在执行的命令写入 stdout 和 stderr。
到目前为止,我还没有找到按照命令打印的顺序获取 stdout 和 stderr 的方法,以及如果我在 Java.
之外执行命令时它们的显示方式
假设该过程有这样的输出:
- 一行(A)写入stdout
- 一行(B)写入stderr
- 一行(C)写入stdout
我想知道这些行的确切顺序。所以例如。 B写在C之前A之后
中提供的答案似乎适用于某些人,但可能无法保证在所有平台上都适用?
我在 Ubuntu 20.04.
上使用 OpenJDK 64 位服务器 VM AdoptOpenJDK(构建 11.0.8+10,混合模式)
到目前为止我尝试过的:
processBuilder.redirectErrorStream(true)
: process.getInputStream()
以所有 stderr 行开始,然后是 stdout,如果我将 stdout 重定向到 File
processBuilder.inheritIO()
:直接打印到父级的控制台,但仍然不是按消息写入方式的顺序(以 stdout 开始,然后是 stderr)
- 将
2>&1
添加到命令:与 redirectErrorStream(true)
相同的行为
John Kugelman 的评论为我指明了正确的方向。非常感谢!
缓冲不会发生在 Java 端,而是将 stdout 和 stderr 传送到另一个程序的结果。在本例中是 JVM。
it becomes full buffered. stderr, on the other hand, stays line buffered even when piped.
所以我们想改变外部进程调用的缓冲行为。
我选择了https://unix.stackexchange.com/a/61833/274368中描述的script
路线。
我的代码现在看起来像这样:
String command = "script -q -c \"my-command\" /dev/null";
ProcessBuilder processBuilder = fs.runInShell(command, args.toArray(new String[args.size()]));
processBuilder.directory(workingDirectory);
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
try (BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String message = input.lines().collect(Collectors.joining(System.lineSeparator()));
// ...
}
其中 message
以正确的顺序包含来自 stderr 和 stdout 的所有行。
我正在使用 ProcessBuilder
启动 bash 进程。
我正在执行的命令写入 stdout 和 stderr。
到目前为止,我还没有找到按照命令打印的顺序获取 stdout 和 stderr 的方法,以及如果我在 Java.
假设该过程有这样的输出:
- 一行(A)写入stdout
- 一行(B)写入stderr
- 一行(C)写入stdout
我想知道这些行的确切顺序。所以例如。 B写在C之前A之后
到目前为止我尝试过的:
processBuilder.redirectErrorStream(true)
:process.getInputStream()
以所有 stderr 行开始,然后是 stdout,如果我将 stdout 重定向到File
processBuilder.inheritIO()
:直接打印到父级的控制台,但仍然不是按消息写入方式的顺序(以 stdout 开始,然后是 stderr)- 将
2>&1
添加到命令:与redirectErrorStream(true)
相同的行为
John Kugelman 的评论为我指明了正确的方向。非常感谢!
缓冲不会发生在 Java 端,而是将 stdout 和 stderr 传送到另一个程序的结果。在本例中是 JVM。
it becomes full buffered. stderr, on the other hand, stays line buffered even when piped.
所以我们想改变外部进程调用的缓冲行为。
我选择了https://unix.stackexchange.com/a/61833/274368中描述的script
路线。
我的代码现在看起来像这样:
String command = "script -q -c \"my-command\" /dev/null";
ProcessBuilder processBuilder = fs.runInShell(command, args.toArray(new String[args.size()]));
processBuilder.directory(workingDirectory);
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
try (BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String message = input.lines().collect(Collectors.joining(System.lineSeparator()));
// ...
}
其中 message
以正确的顺序包含来自 stderr 和 stdout 的所有行。