我正在读取另一个生成输出的进程的输出(缓慢和无限)。因为我想实时读取此数据,所以我使用“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)

10-01 13:58