交易是这样的:我有一个多进程系统(pre-fork模型,类似于apache)。所有进程都在向同一个日志文件(实际上是一个记录请求和响应的二进制日志文件,但无所谓)写入。
我通过共享内存锁来防止对日志的并发访问,当文件达到一定大小时,注意到它的进程首先通过以下方式滚动日志:
1.关闭文件。
1.重命名log.bin -> log.bin.1,log.bin.1 -> log.bin.2等等。
1.删除超出最大允许日志数的日志。(比如log.bin.10)
1.打开新的log.bin文件
问题是其他进程没有意识到,实际上继续写入旧的日志文件(重命名为log.bin.1)。
我可以想到几个解决方案:
1.某种RPC来通知其他进程重新打开日志(甚至可能是信号)。我不是特别喜欢它。
1.让进程通过打开的文件流检查文件长度,并以某种方式检测到文件在它们下面被重命名并重新打开log.bin文件。
在我看来,这些都不是很优雅。
建议?建议?
6条答案
按热度按时间pprl5pva1#
您的解决方案看起来不错,但您应该在共享内存中存储一个带有当前日志文件inode的整数(请参阅stat(2) withstat.st_inomember)。
这样,所有进程都在打开的inode文件中保留了一个局部变量。
当只有一个进程旋转时,共享var必须更新,所有其他进程都通过检查本地inode和共享inode之间的差异来感知。它应该会导致重新开放。
thigvfpy2#
1.每次在写日志条目之前按名称打开文件怎么样?
1.获取共享内存锁
1.按名称打开文件
1.写日志条目
1.关闭文件
1.释放锁
1.或者您可以创建一个日志记录进程,它从其他进程接收日志消息,并透明地处理来自它们的所有循环。
6gpjuf903#
你没有说你使用的是什么语言,但是你的进程都应该记录到一个日志进程中,日志进程对文件的写入进行抽象。
8aqjt8rx4#
您可以复制log.bin到log.bin.1,然后截断log.bin文件。因此,问题仍然可以写入旧的文件指针,该指针现在为空。
参见
man logrotate
:hfwmuf9z5#
因为你使用的是共享内存,而且你知道有多少进程在使用日志文件。您可以在共享内存中创建一个标志数组,告诉每个进程该文件已被轮换。然后,每个进程重置该标志,以便它不会连续重新打开文件。
8tntrjer6#
让每个线程将日志记录到单独的文件中,并由另一个进程管理这些日志合并成一个日志,您怎么看?
如果日志记录器死亡,日志记录的过程仍然会发生,只有合并更新功能暂时丢失。日志记录器可以以非常异步的模式重新启动,即使在各个日志记录队列中积累了大量消息之后也是如此。循环是基于单个日志的文件大小的简单的移动-然后-替换。这边走no messages are lost日志记录器进程将清理单个日志。