linux 旋转日志而不重启,多进程问题

0yg35tkg  于 2023-10-16  发布在  Linux
关注(0)|答案(6)|浏览(124)

交易是这样的:我有一个多进程系统(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文件。
在我看来,这些都不是很优雅。
建议?建议?

pprl5pva

pprl5pva1#

您的解决方案看起来不错,但您应该在共享内存中存储一个带有当前日志文件inode的整数(请参阅stat(2) withstat.st_inomember)。
这样,所有进程都在打开的inode文件中保留了一个局部变量。
当只有一个进程旋转时,共享var必须更新,所有其他进程都通过检查本地inode和共享inode之间的差异来感知。它应该会导致重新开放。

thigvfpy

thigvfpy2#

1.每次在写日志条目之前按名称打开文件怎么样?
1.获取共享内存锁
1.按名称打开文件
1.写日志条目
1.关闭文件
1.释放锁
1.或者您可以创建一个日志记录进程,它从其他进程接收日志消息,并透明地处理来自它们的所有循环。

6gpjuf90

6gpjuf903#

你没有说你使用的是什么语言,但是你的进程都应该记录到一个日志进程中,日志进程对文件的写入进行抽象。

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

8aqjt8rx4#

您可以复制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.
hfwmuf9z

hfwmuf9z5#

因为你使用的是共享内存,而且你知道有多少进程在使用日志文件。您可以在共享内存中创建一个标志数组,告诉每个进程该文件已被轮换。然后,每个进程重置该标志,以便它不会连续重新打开文件。

8tntrjer

8tntrjer6#

让每个线程将日志记录到单独的文件中,并由另一个进程管理这些日志合并成一个日志,您怎么看?

client1 -> cl1.log
client2 -> cl2.log
...

logger (cl1.log, cl2.log, ...) -> cl.log

如果日志记录器死亡,日志记录的过程仍然会发生,只有合并更新功能暂时丢失。日志记录器可以以非常异步的模式重新启动,即使在各个日志记录队列中积累了大量消息之后也是如此。循环是基于单个日志的文件大小的简单的移动-然后-替换。这边走no messages are lost日志记录器进程将清理单个日志。

相关问题