【问题标题】:Redirect stdout/stderr using dup2, then resinstate later使用 dup2 重定向 stdout/stderr,然后再使用resinstate
【发布时间】:2017-05-17 11:36:08
【问题描述】:

背景:我们有一个运行 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 之前复制初始文件描述符,否则 dup2 会关闭它们并且无法恢复它们。
  • 类似:old_out=dup(STDOUT_FILENO); old_err=dup(STDERR_FILENO); 复制,然后完成后:dup2(old_out,STDOUT_FILENO); dup2(old_err,STDERR_FILENO); 是吗?

标签: c linux io-redirection dup


【解决方案1】:

您必须在 dup2 之前复制初始文件描述符,否则 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 缓冲区中,您应该会很好。

【讨论】:

  • 猜猜你在我打字的时候回答了我的评论,谢谢!
  • 我是:)。当然,如果中间的任何东西都能够接受要写入的文件描述符会更好,从而消除了重定向的需要,但是当使用第三方代码时,你只能勉强凑合。
  • 是的,中间的代码太多了,无法用其他东西替换所有打印语句。
【解决方案2】:

Linux 手册页清楚地表明 dup2 不会关闭 oldfd。不要忘记关闭nf

【讨论】:

    猜你喜欢
    • 2019-10-17
    • 1970-01-01
    • 1970-01-01
    • 2018-01-25
    • 1970-01-01
    • 2014-07-22
    • 2010-10-10
    • 1970-01-01
    • 2022-01-18
    相关资源
    最近更新 更多