进程重定向可以在bash中同步吗
Can process redirection be synchronised in bash?
我有以下用gcc -lstdc++ main.cpp -o main.out
编译的C++程序。
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main(int argc, char** argv) {
cerr << "Error 1" << endl;
cout << "Ok " << endl;
cerr << "Wowza... that's bad..." << endl;
cerr << "Caused by X.";
cout << "All good in the end." << endl;
return 0;
};
我还有一个bash脚本,如下所示,它的主要目的是将STDOUT前缀为"SUCCESS:",将STDERR前缀为"ERROR:"。
./main.out > >(sed "s/^/SUCCESS: /g" >> main.log) 2> >(sed "s/^/ERROR : /g" >> main.log)
如果Icat main.log
,结果为:
ERROR : Error 1
ERROR : Wowza... that's bad...
ERROR : Caused by X.
SUCCESS: Ok
SUCCESS: All good in the end.
正如您所看到的,发送到STDERR的字符串都出现在发送到STDOUT的字符串之前。
- 为什么会出现上述情况?例如,bash是否从右到左评估所有流程替换
- 有没有任何方法可以同步这些字符串,以便字符串的顺序与C++示例程序中定义的顺序相同
在命令行中,这会影响main.out
和sed
。添加>
和2>
重定向时,main.out
的stdout和stderr将得到完全缓冲。两个sed
的stdout流被完全缓冲,因为它们被重定向到main.log
。
您可以使用stdbuf
来覆盖此行为。stdbuf
运行一个具有您选择的输入和输出缓冲的命令。它适用于大多数程序。
如果将stdbuf
覆盖添加到三个命令中的每一个,则可以使它们交错输出。这是个好消息。
$ rm main.log; stdbuf -oL -eL ./main.out > >(stdbuf -oL sed "s/^/SUCCESS: /g" >> main.log) 2> >(stdbuf -oL sed "s/^/ERROR : /g" >> main.log); cat main.log
ERROR : Error 1
ERROR : Wowza... that's bad...
SUCCESS: Ok
SUCCESS: All good in the end.
ERROR : Caused by X.
$ rm main.log; stdbuf -oL -eL ./main.out > >(stdbuf -oL sed "s/^/SUCCESS: /g" >> main.log) 2> >(stdbuf -oL sed "s/^/ERROR : /g" >> main.log); cat main.log
SUCCESS: Ok
SUCCESS: All good in the end.
ERROR : Error 1
ERROR : Wowza... that's bad...
ERROR : Caused by X.
$ rm main.log; stdbuf -oL -eL ./main.out > >(stdbuf -oL sed "s/^/SUCCESS: /g" >> main.log) 2> >(stdbuf -oL sed "s/^/ERROR : /g" >> main.log); cat main.log
SUCCESS: Ok
ERROR : Error 1
SUCCESS: All good in the end.
ERROR : Wowza... that's bad...
ERROR : Caused by X.
坏消息是,行的顺序是不可预测的。仍然不能保证输出将按照您的程序编写的顺序。
原因是从根本上讲,这里有一个比赛条件。您的程序和两个sed
命令是三个独立的进程。无法保证它们会以特定的顺序运行,即当您的程序向stdout吐出一行时,Linux会将控制切换到适当的sed
进程,然后切换回您的程序。
Linux可以允许您的程序编写其所有输出,然后将控制切换到任一sed
进程。它可以对两个CCD_ 16进程进行交织。它可以随心所欲地执行上下文切换。
更不用说,在多核或多处理器系统上,进程可以同时运行。这是一个真正的种族。无论哪个sed
运行得最快,都将首先输出。
要同步处理,您必须去掉多个sed
进程。相反,让一个进程从两个流中读取。这是一个更复杂的设计。您需要两个输入描述符,而不仅仅是一个。您需要以某种方式select()
,并且只有在有可用输入的情况下才能从中读取。这种多路复用需要一些高级的shell脚本。你最好用另一种语言来做这件事。
我相信我自己可以通过演示回答1。
正如我所假设的,过程替换从右到左发生。
例如,执行./main.out 2> >(sed "s/^/ERROR : /g" >> main.log) > >(sed "s/^/SUCCESS: /g" >> main.log) ; cat main.log
会在STDERR消息之前产生所有STDOUT消息:
SUCCESS: Ok
SUCCESS: All good in the end.
ERROR : Error 1
ERROR : Wowza... that's bad...
ERROR : Caused by X.
- 松弛原子与无同步情况下的记忆连贯性
- 将bash参数传递给c++
- 使用QQuickFramebufferObject时同步数据的最佳方式是什么
- 在C++中同步线程
- 与 stdio 同步是否使程序 I/O 非交互式?
- 如何在qt中同步应用程序和显示器的刷新率?
- Windows 进程间同步类似事件?
- 当对套接字 send() 的同步调用由于连接另一端丢失而被阻止时,如何恢复?
- 将 10 个线程与原子布尔值同步
- ofstream::close() 是否在 Linux 上调用同步?
- 与Visual Studios(c ++)同步时如何组织github存储库?
- bash脚本在使用popen()时不返回代码以调用C ++程序
- 原子获取是否与互斥锁释放同步?
- Boost (Beast) websocket:同步写入挂起
- Postgres vs MySQL:命令不同步;.
- 终端如何在 shell 提示符下以编程方式阻止退格,以便您无法在其上退格,例如 $ 表示 bash 或 C:\blah\>
- Bash 自动完成一个选项,而不运行应用程序
- 在 Windows 上运行带有 C++ 的 bash 脚本
- 线程过程中的线程同步问题
- 进程重定向可以在bash中同步吗