我正在读取另一个生成输出的进程的输出(缓慢和无限)。因为我想实时读取此数据,所以我使用“stdbuf -oL”(行缓冲,数据为文本)。我无法控制生成过程,因此无法修改源以强制刷新。
到目前为止,stdbuf可以正常工作,但是该进程使用SOCK_RAW,并且需要以root身份运行,具有setuid(0)或cap_net_raw
功能。当以非root用户身份使用setuid或功能运行时,stdbuf似乎被忽略。让我演示一下这个问题:
这是一个简单的作家:
#include <stdio.h>
#include <unistd.h>
int main(){
int i;
for ( i = 0;; i++){
fprintf(stdout, "%d\n", i);
sleep(1);
}
}
和一个简单的读者:
#include <stdio.h>
int main(){
char* line = NULL;
size_t n = 0;
while (getline(&line, &n, stdin) != -1 ) {
fputs(line, stdout);
}
}
不出所料,通过执行
./writer | ./reader
,直到缓冲区被填满,什么都不会出现。前置stdbuf -oL
启用行缓冲,然后将行输入阅读器:% stdbuf -oL ./writer | ./reader
0
1
2
...
但是,如果我添加
cap_net_raw+ep
,它将停止工作:% sudo setcap cap_net_raw+ep ./writer
% stdbuf -oL ./writer | ./reader
(no output)
使用setuid时会观察到相同的行为:
% sudo chown root:root ./writer
% sudo chmod +s ./writer
% stdbuf -oL ./writer | ./reader
(no output)
我有兴趣了解为什么会发生这种情况,以及如何在不以root用户身份运行的情况下继续使用stdbuf。我承认我不完全了解setuid在幕后所做的事情。
最佳答案
通过查看stdbuf source code,似乎可以通过设置LD_PRELOAD来工作。当然,将LD_PRELOAD与setuid可执行文件或sudo一起使用时会涉及安全性问题。
我发现的一个建议是disable the noatsecure selinux attribute作为您的可执行文件。
另一个更简单的选择是避免stdbuf,而直接从源代码中直接调用fflush(stdout)
。