微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何将stderr输出使用fprintf重定向到日志文件?

如何解决如何将stderr输出使用fprintf重定向到日志文件?

我正在做一些调试,想将标准错误消息重定向文件;因此,它可以在调试日志文件中查看。 我确实需要通过C代码完成此操作,而不是通过UNIX shell重定向完成。

我需要调试一些这样的模块。 我有一组调试工具,可写入strerr(console)。它很容易包含在源代码中,并提供了一组舒适的宏和函数,用于调试源代码

下面是头文件中的代码

#include <stdio.h>

#define LOGWRAPPER(tag,fmt,args...) \
  fprintf(stderr,"%s: " fmt "\n",tag,##args)   

#define LOG_DEBUG(...) LOGWRAPPER(__VA_ARGS__)

...

...

#define LOG_DEBUG(tag,args...)                 \
  do {                                               \
    (true) ? ALOG(LOG_DEBUG,##args)       \
           : fprintf(stderr,"%s" fmt,##args); \
  } while (0)
....

最终所有打印都将返回到此处,即头文件。所以我想我必须做些改变

#define LOGWRAPPER(tag,##args)

有什么主意吗?还是我应该创建一个文件路径并插入fprintf中?

解决方法

在C代码中重定向stderr的典型方法是使用dup2()(实质上)将文件描述符映射到新文件。例如,类似:

int f =打开(“ mylog.txt”,O_CREAT | O_RDWR | O_APPEND,0644); dup2(f,STDERR_FILENO);

还有其他方法-例如,您可以在freopen()上使用stderr

但是...

如果使用定义的宏进行所有日志记录,为什么不简单地定义宏以执行完全不同的操作?也就是说,定义LOG_DEBUG来调用您提供的函数,而不是完全fprintf()吗?

我确定对此还有其他意见,但是我不喜欢将stderr用于常规日志记录。我只希望stderr收到严重的程序错误消息。 (也许)您的代码不是唯一可以写入stderr的代码-库也可能这样做。收集它们的输出并将其发送到常规调试日志可能是合适的,但是再次,它可能不合适。我总是使用专门用于此目的的功能进行常规日志记录。

,

我确实需要通过C代码完成此操作,而不是通过UNIX shell重定向。

了解shell如何实现重定向将为您提供有关如何在自己的程序中执行此操作的必要见解。

POSIX定义了三个标准文件描述符,可在每个进程开始时使用它们:0 = stdin,1 = stdout,2 = stderr

C标准库还定义了三个FILE*流,它们通过全局可用符号暴露,它们分别名为stdinstdoutstderr,并且直接对应于数字文件描述符; POSIX标准定义了在filenoFILE*流上运行的附加功能。

最终,一切都归结为文件描述符。

尽管可以将现有流freopen移到新目的地,但这通常会导致新的不同文件描述符。然后,您响应的FILE*流(可能通过诸如stderr之类的全局符号)将转到该新位置,但它不会影响程序的某些部分,而绕过C标准库函数。 因此,建议的方法是替换filedescriptor本身,这是系统调用dup2的作用。

使用dup2,您可以获取一个现有文件描述符,然后将其复制覆盖到另一个现有文件描述符上。因此,如果您打开一个日志文件,并在文件描述符2(= stderr)上进行复制,则其输出将被重定向到那里。

这是shell重定向的方式,您也可以在程序中使用它:

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc,char *argv[])
{
    /* replace fd=2,i.e. stderr,with a file of our choosing: */
    int fd_logfile = open("logfile.txt",O_RDWR | O_CREAT | O_APPEND,0644);
    if( 0 <= fd_logfile ){
        dup2(fd_logfile,2);
        close(fd_logfile);
    }
    
    /* ... */
    fprintf(stderr,"This should go to logfile.txt\n");
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。