使用 dup2 重定向 stdout/stderr,稍后使用树脂状态

Joh*_*n U 4 c linux io-redirection dup

背景:我们有一个运行 Busybox 的嵌入式 Linux 系统(资源有限),我们有一个正在运行的进程,它通常会在控制台上(通过 stdout / stderr)吐出大量信息,但我们想暂时将其重定向到 syslog(使用 syslogd / logger) on command - 无需重新启动进程或重新启动。

使用此处找到的代码效果很好,直到我们尝试停止/关闭记录器 fd,此时写入 stdout/stderr 失败并且一切都中断了。下面的例子:

int main()
{

    // Got command to direct all output to syslog:

    FILE *fl;
    fl = popen("logger","w");
    if(fl == NULL)
        return 1;
    fprintf(fl,"logger test new"); // This goes to syslogd
    int nf;
    nf = fileno(fl);
    dup2(nf,STDOUT_FILENO);
    dup2(nf,STDERR_FILENO);
    fprintf(stdout,"Written in stdout\n");
    fprintf(stderr,"Written in stderr\n");

    // ...some time later when we've logged enough things:

    pclose(fl);
    fprintf(stdout,"This will fail\n");
    fprintf(stderr,"Catch fire and die\n");
}
Run Code Online (Sandbox Code Playgroud)

所以问题是,一旦我们完成了日志记录,我们(如何)可以恢复原始状态?

在具有RTFMdup()dup2()我不清除,我们究竟如何才能做到这一点,如果有可能“重新打开”也许是freopen()标准输出/标准错误,但作为最后的手段是可以接受或许点nf/dev/null/这样的事情,至少不死机.

spe*_*ras 5

您必须在 dup2 之前 dup 初始文件描述符,否则 dup2 会关闭它们并且无法恢复它们。

int stdout_copy = dup(STDOUT_FILENO);
dup2(nf, STDOUT_FILENO);

/* do something with stdout */

dup2(stdout_copy, STDOUT_FILENO);
close(stdout_copy);
Run Code Online (Sandbox Code Playgroud)

进行错误处理,添加fflush调用以确保您不会在 stdlib 缓冲区中留下未写入的数据,并且您应该很好。