68

所以我有一个在 Linux 系统上运行的守护进程,我想记录它的活动:日志。问题是,实现这一目标的“最佳”方法是什么?

我的第一个想法是简单地打开一个文件并写入它。

FILE* log = fopen("logfile.log", "w");
/* daemon works...needs to write to log */
fprintf(log, "foo%s\n", (char*)bar);
/* ...all done, close the file */
fclose(log);

以这种方式记录有什么本质上的错误吗?有没有更好的办法,比如Linux内置一些框架?

4

10 回答 10

104

Unix 长期以来一直有一个名为syslog的特殊日志记录框架。输入你的外壳

man 3 syslog

您将获得 C 接口的帮助。

一些 例子

#include <stdio.h>
#include <unistd.h>
#include <syslog.h>

int main(void) {

 openlog("slog", LOG_PID|LOG_CONS, LOG_USER);
 syslog(LOG_INFO, "A different kind of Hello world ... ");
 closelog();

 return 0;
}
于 2008-10-01T16:21:47.410 回答
24

可能会是一场赛马,但是是的,存在于大多数(如果不是所有)Un*x 衍生产品中的 syslog 设施是首选的方式。记录到文件并没有错,但它确实会给您留下许多任务:

  • 您的日志记录位置是否有文件系统来保存文件
  • 缓冲(用于性能)与刷新(在系统崩溃之前写入日志)呢?
  • 如果您的守护程序运行了很长时间,您会如何处理不断增长的日志文件。

Syslog 会为您处理所有这些,甚至更多。API 类似于 printf 部落,因此您在调整代码时应该没有问题。

于 2008-10-01T16:27:18.707 回答
12

syslog 在更大(或更注重安全性)的安装中的另一个优点:可以将 syslog 守护进程配置为将日志发送到另一台服务器以进行记录,而不是(或附加于)本地文件系统。

将服务器场的所有日志放在一个地方会方便得多,而不必在每台机器上单独读取它们,尤其是当您尝试将一台服务器上的事件与另一台服务器上的事件相关联时。当一个被破解时,你就不能再信任它的日志了……但是如果日志服务器保持安全,你就知道它的日志中不会删除任何东西,所以任何入侵记录都将是完整的。

于 2008-10-01T17:30:28.947 回答
8

当我进行单元测试时,我会向 daemon.info 和 daemon.debug 吐出很多守护进程消息。syslog.conf 中的一行可以将这些消息粘贴到您想要的任何文件中。

http://www.linuxjournal.com/files/linuxjournal.com/linuxjournal/articles/040/4036/4036s1.html对 C API 的解释比手册页 imo 更好。

于 2008-10-01T16:27:28.427 回答
2

如上所述,您应该查看 syslog。但是,如果您想编写自己的日志记录代码,我建议您使用 fopen 的“a”(写入附加)模式。

编写自己的日志代码的一些缺点是:日志轮换处理、锁定(如果您有多个线程)、同步(您要等待日志写入磁盘吗?)。syslog 的缺点之一是应用程序不知道日志是否已写入磁盘(它们可能已丢失)。

于 2008-10-01T16:33:33.060 回答
2

Syslog 是一个不错的选择,但您可能希望考虑查看 log4c。log4[something] 框架在其 Java 和 Perl 实现中运行良好,并允许您 - 从配置文件 - 选择记录到 syslog、控制台、平面文件或用户定义的日志编写器。您可以为每个模块定义特定的日志上下文,并将每个上下文日志置于您的配置所定义的不同级别。(跟踪、调试、信息、警告、错误、关键),并让您的守护程序通过捕获信号即时重新读取该配置文件,从而允许您在正在运行的服务器上操作日志级别。

于 2008-10-01T16:41:43.603 回答
2

如果您使用线程并将日志记录用作调试工具,您将需要寻找使用某种线程安全但未锁定的环形缓冲区的日志记录库。每个线程一个缓冲区,仅在严格需要时使用全局锁。

这可以避免日志记录导致您的软件严重变慢,并避免创建在您添加调试日志记录时会发生变化的 heisenbugs。

如果它有一个高速压缩的二进制日志格式,在记录过程中不会浪费时间进行格式操作,并且有一些不错的日志解析和显示工具,那是一个奖励。

我会为此提供一些好的代码参考,但我自己没有。我只想要一个。:)

于 2008-10-01T17:32:20.330 回答
1

我们的嵌入式系统没有系统日志,因此我编写的守护进程使用“a”打开模式对文件进行调试,类似于您描述的方式。我有一个打开日志文件的函数,吐出消息然后关闭文件(我只在发生意外情况时才这样做)。但是,我还必须编写代码来处理日志轮换,正如其他评论者提到的那样,它由“tail -c 65536 logfile > logfiletmp && mv logfiletmp logfile”组成。它非常粗糙,可能应该被称为“日志正面截断”,但它会阻止我们基于 RAM 磁盘的小型文件系统填满日志文件。

于 2008-10-02T00:41:06.587 回答
0

有很多潜在的问题:例如,如果磁盘已满,您是否希望您的守护进程失败?此外,您每次都将覆盖您的文件。通常使用循环文件,以便您在机器上为文件分配空间,但您可以保留足够的历史记录以供使用,而不会占用太多空间。有像 log4c 这样的工具可以帮助你。如果您的代码是 C++,那么您可能会考虑在 Apache 项目中使用 log4cxx(apt-get install liblog4cxx9-dev on ubuntu/debian),但看起来您使用的是 C。

于 2008-10-01T16:26:40.580 回答
0

So far nobody mentioned boost log library which has nice and easy way to redirect your log messages to files or syslog sink or even Windows event log.

于 2013-09-25T22:23:13.703 回答