copytruncate 如何实际工作?

ove*_*nge 7 linux logrotate large-files syslog-ng file-descriptors

我们想copytruncate在使用logrotate以下配置旋转文件之前 了解:

/app/syslog-ng/custom/output/all_devices.log { 
size 200M 
copytruncate
dateext 
dateformat -%Y%m%d-%s 
rotate 365 
sharedscripts 
compress
postrotate 
    /app/syslog-ng/sbin/syslog-ng-ctl reload 
endscript 
}
Run Code Online (Sandbox Code Playgroud)

RHEL 7.x,8GB 内存,4 VCpu

题:

logrotate当 syslog-NG 已经打开文件进行日志记录时,如何截断文件?不是资源的争用吗?当文件没有任何记录时,syslog-NG 是否会立即关闭文件?

fil*_*den 7

截断日志文件实际上有效,因为作者使用 O_APPEND 打开文件进行写入。

open(2)手册页:

O_APPEND:文件以追加模式打开。在每次 write(2) 之前,文件偏移量位于文件末尾,就像使用 lseek(2) 一样。文件偏移的修改和写入操作作为单个原子步骤执行。

如前所述,该操作是原子的,因此无论何时发出写入,它都会附加到与文件末尾匹配的当前偏移量,而不是在前一个写入操作完成之前保存的偏移量。

这使得在截断操作后追加工作,将下一个日志行再次写入文件的开头,而无需重新打开文件。

( O_APPEND 的相同功能还可以将多个编写器附加到同一个文件,而不会破坏彼此的更新。)

记录器还使用单个 write(2) 操作写入日志行,以防止在截断或并发写入操作期间将日志行分成两部分。

请注意,像 syslog、syslog-ng 或 rsyslog 这样的记录器通常不需要使用,copytruncate因为它们支持重新打开日志文件,通常是通过向它们发送 SIGHUP。logrotate 对copytruncate存在的支持是为了迎合其他记录器,这些记录器通常附加到日志文件,但不一定有重新打开日志文件的好方法(因此,在这些情况下,通过重命名进行轮换不起作用。)

另请注意,它copyrotate具有固有的竞争条件,因为作者可能会在 logrotate 完成复制之后和发出截断操作之前将一行附加到日志文件中。这种竞争条件会导致它永远丢失那些日志行。这就是为什么copytruncate通常不推荐使用轮换日志的原因,除非这是唯一可行的方法。