我们有一个 Java 应用程序,它使用 log4j 并每天轮换自己的日志:
- 当前使用的日志文件是
/var/log/foo/foo.log
/var/log/foo/foo.log.YYYY-MM-dd
当日子改变时它就被移入
我们不想改变它的配置...
然而,我们确实希望:
- 重命名文件后对其进行压缩
- 只保留一定数量
虽然编写一个 cron-job 来同时完成这两项任务并不困难,但我们宁愿留在框架中logrotate
...
我创建了以下内容/etc/logrotate.d/foo
:
/var/log/foo/foo.log.* {
daily
rotate 2
compress
delaycompress
missingok
notifempty
}
但它什么也没做:
reading config file /etc/logrotate.d/foo
Handling 1 logs
rotating pattern: /var/log/foo/foo.log.* after 1 days (2 rotations)
empty log files are not rotated, old logs are removed
considering log /var/log/foo/foo.log.2017-06-28
log does not need rotating
considering log /var/log/foo/foo.log.2017-06-29
log does not need rotating
considering log /var/log/foo/foo.log.2017-06-30
log does not need rotating
considering log /var/log/foo/foo.log.2017-07-01
log does not need rotating
considering log /var/log/foo/foo.log.2017-07-02
log does not need rotating
considering log /var/log/foo/foo.log.2017-07-03
log does not need rotating
considering log /var/log/foo/foo.log.2017-07-04
log does not need rotating
当文件总数超过 2 时,如何让它压缩文件并删除最旧的文件?
答案1
我真的不认为你能在logrotate
没有外部命令的情况下做你想做的事情。此外,该模式/var/log/foo/foo.log.*
会将每个单独的文件视为要轮换的单独日志,而不是一组轮换文件。
man logrotate
请谨慎使用通配符。如果指定 *,logrotate 将轮转所有文件,包括之前轮转过的文件。
无论如何,也许是这样的?只需设置永远不会达到的旋转条件,因为 log4j 已经部分处理了旋转。然后将其余部分放入脚本中prerotate
?
/var/log/foo/foo.log {
size 100G # something big that will never be reached/rotated since log4j does this.
missingok
notifempty
# delete the other logs over 7 days old
prerotate
find /var/log/foo/ -name 'foo.log.*' -mtime +7 -delete
nice gzip /var/log/foo/foo.log.*
endscript
}
答案2
我需要实现此行为,因为应用程序团队希望使用 log4j 保持对日志和文件名格式以及轮换计划的控制。如果您阅读,man logrotate
您会注意到所有 pre/post/lastaction 脚本仅在至少轮换一个日志时执行。因此,设置一些无法访问的内容size 999G
不起作用。
相反,我所做的是设置copy
和extension
选项以便:
- 原始日志文件从未被触及(它由 log4j 管理)
- logrotate 轮换的日志具有不同的扩展名,我可以对其进行过滤
/var/log/<service>/<service>.log {
copy # don't touch the orig. log file, it's managed by log4j
extension .log # End rotated files in ".log" so we can find and delete them
rotate 1
hourly
missingok
prerotate
find /var/log/<service>/ -iname "*service.log.*" ! -iname "*.gz" -exec gzip {} \; && \
aws s3 sync /var/log/<service>/ s3://<bucket>/<environment>/<ec2_id>/<service>/ --exclude "*" --include "*<service>*.gz" && \
find /var/log/<service>/ -iname "*<service>.log.*" -mtime +7 -delete
endscript
lastaction
find /var/log/<service>/ -iname "*<service>.*.log" -delete
endscript
}
是的,我可以创建一个 cron 作业。我使用的理由logrotate
是,我将所有的日志轮换配置管理都放在一个 Ansible 角色中,将来,我将禁用log4j
轮换并改用,logrotate
这将是一个简单的更改。
答案3
Log4j Rolling File Appenders 与 logrotate 不兼容。log4j 轮转会干扰 logrotate。
首先,您需要找到应用程序的 log4j 配置文件,并将滚动文件附加器替换为简单文件附加器。这将阻止 log4j 轮换文件。然后,您可以使用 logrotate 根据需要轮换日志文件。
如果您无法修改应用程序的 log4j 配置,您可以创建自己的配置,并在启动应用程序时在类路径中指定它。
-Dlog4j.configurationFile=path/to/log4j2.xml
参考:https://logging.apache.org/log4j/2.0/faq.html#config_location