让我详细描述一下这个问题:
我运行一些无人值守的脚本,这些脚本可以生成标准输出和标准错误行,我想按照终端模拟器显示的精确顺序捕获它们,然后向它们添加前缀,如“STDERR:”和“STDOUT:”。
我曾尝试对它们使用管道甚至基于 epoll 的方法,但无济于事。我认为解决方案是在 pty 使用中,尽管我不是这方面的高手。我还查看了Gnome 的 VTE的源代码,但这并没有多大成效。
理想情况下,我会使用Go而不是 Bash 来完成此操作,但我无法做到。由于缓冲,管道似乎自动禁止保持正确的行顺序。
有人能做类似的事情吗?或者这是不可能的?我认为,如果终端模拟器可以做到,那么它就不是——也许通过创建一个以不同方式处理 PTY 的小型 C 程序?
理想情况下,我会使用异步输入来读取这 2 个流(STDOUT 和 STDERR),然后根据我的需要重新打印它们,但输入顺序至关重要!
注意:我知道stderred但它不适用于 Bash 脚本,并且无法轻松编辑以添加前缀(因为它基本上包含了大量系统调用)。
更新:在两个要点下面添加
(可以在我提供的示例脚本中添加亚秒随机延迟,以证明结果一致)
更新:正如@Gilles 指出的那样,这个问题的解决方案也将解决另一个问题。但是,我得出的结论是,不可能在这里和那里做所要求的事情。当使用2>&1两个流在 pty/pipe 级别正确合并时,但要单独使用流并以正确的顺序使用,确实应该使用涉及系统调用挂钩的stderred方法,并且可以在许多方面被视为脏。
如果有人可以反驳上述内容,我将渴望更新这个问题。
根据“ Linux: The Complete Reference 6th Edition ”(第 44 页),您只能使用|&重定向符号通过管道传输 STDERR 。
我写了一个非常简单的脚本来测试这个:
#!/bin/bash
echo "Normal Text."
echo "Error Text." >&2
Run Code Online (Sandbox Code Playgroud)
我像这样运行这个脚本:
./script.sh |& sed 's:^:\t:'
Run Code Online (Sandbox Code Playgroud)
据推测,只有打印到 STDERR 的行才会缩进。但是,正如我所见,它实际上并不是这样工作的:
Normal Text.
Error Text.
Run Code Online (Sandbox Code Playgroud)
我在这里做错了什么?
假设我运行命令:
sudo ./list_members Physicians
Run Code Online (Sandbox Code Playgroud)
我想像这样为输出添加前缀:
Physicians user@domain.com
Physicians user2@domain.com
Physicians user3@domain.com
Physicians user4@domain.com
Run Code Online (Sandbox Code Playgroud)
我可以像这样为 StdOutput 添加前缀吗?