旋转日志无需重启,多个进程问题

时间:2010-07-22 08:50:23

标签: c++ linux logging

这是交易: 我有一个多进程系统(pre-fork模型,类似于apache)。所有进程都写入同一个日志文件(事实上是一个记录请求和响应的二进制日志文件,但无论如何)。

我通过共享内存锁防止并发访问日志,当文件达到一定大小时,通知它的进程首先滚动日志:

  1. 关闭文件。
  2. 重命名log.bin - > log.bin.1,log.bin.1 - > log.bin.2等等。
  3. 删除超出允许的最大日志数的日志。 (比方说,log.bin.10)
  4. 打开新的log.bin文件
  5. 问题是其他进程没有意识到,并且实际上继续写入旧的日志文件(已重命名为log.bin.1)。

    我可以想到几个解决方案:

    1. 某种rpc通知其他进程重新打开日志(甚至可能是一个单一的)。我不是特别喜欢它。
    2. 让进程通过打开的文件流检查文件长度,并以某种方式检测文件是否在其下重命名并重新打开log.bin文件。
    3. 在我看来,这些都不是很优雅。

      想法?建议?

5 个答案:

答案 0 :(得分:3)

您的解决方案似乎很好,但您应该在共享内存中存储一​​个带有当前日志文件inode的整数(请参阅stat(2) stat.st_ino 成员)。

这样,所有进程都使用打开的inode文件保存了一个局部变量。

只有一个进程轮换时必须更新共享var,并且通过检查本地inode和共享inode之间的差异来了解所有其他进程。它应该导致重新开放。

答案 1 :(得分:1)

  1. 每次在写日志条目之前按名称打开文件怎么样?

    1. 获取共享内存锁
    2. 按名称打开文件
    3. 写日志条目
    4. 关闭文件
    5. 释放锁定
  2. 或者你可以创建一个日志记录过程,它接收来自其他进程的日志消息,并从它们透明地处理所有旋转。

答案 2 :(得分:1)

您没有说出您正在使用的语言,但您的进程应该全部登录到日志进程,并且日志进程会抽象写入文件。

Logging client1 ->  |
Logging client2 ->  |
Logging client3 ->  | Logging queue (with process lock) -> logging writer -> file roller
Logging client4 ->  |

答案 3 :(得分:1)

您可以 log.bin复制到log.bin.1,然后然后截断 log.bin文件。 所以问题仍然可以写入旧的文件指针,现在是空的。

另见man logrotate

   copytruncate
          Truncate  the original log file to zero size in place after cre‐
          ating a copy, instead of moving the old log file and  optionally
          creating  a new one.  It can be used when some program cannot be
          told to close  its  logfile  and  thus  might  continue  writing
          (appending)  to  the previous log file forever.  Note that there
          is a very small time slice between copying the file and truncat‐
          ing it, so some logging data might be lost.  When this option is
          used, the create option will have no effect, as the old log file
          stays in place.

答案 4 :(得分:1)

由于您正在使用共享内存,并且您知道有多少进程正在使用该日志文件。 您可以在共享内存中创建一个标志数组,告诉每个进程该文件已被旋转。然后,每个进程都会重置标志,以便它不会连续重新打开文件。