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

使用here找到的代码可以很好地工作,直到我们尝试停止/关闭记录器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");
}

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

dup()dup2()上使用RTFM时,如果可以“重新打开”也许freopen() stdout/stderr,我不清楚我们如何精确地实现这一目标,但是作为最后的选择,也许可以将nf指向/dev/null/,因此至少不要崩溃。

最佳答案

您必须在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);

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

关于c - 使用dup2重定向stdout/stderr,然后稍后进行resinstate,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44023742/

10-11 20:21