在Ubuntu服务器运维中,logrotate配置的压缩与延时轮转是管理日志文件的关键技巧。直接点说,如果配置不当,你会遇到磁盘空间被旧日志占满、轮转时服务日志丢失或中断、以及压缩效率低下影响性能等问题。解决的核心在于精准配置logrotate的compress、delaycompress、dateext等参数,并结合postrotate脚本确保日志切割的平滑性。下面我们直接进入具体配置方法与优化策略。

logrotate基础配置结构与压缩参数详解

logrotate的配置文件通常位于/etc/logrotate.conf以及/etc/logrotate.d/目录下。一个典型的配置段针对特定日志文件,其基本结构包含日志路径、轮转周期、保留份数、压缩选项等。要实现压缩,关键参数是"compress"。启用后,轮转后的旧日志会使用gzip进行压缩。但需要注意,默认压缩是在轮转后立即进行的,这可能会与某些还在写入日志的服务冲突。

/var/log/nginx/access.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
    endscript
}

如上例,我们定义了Nginx访问日志的轮转。参数"daily"指定每日轮转,"rotate 7"保留最近7份日志。"compress"启用了压缩。而"delaycompress"则是一个重要技巧,它表示延迟压缩:本次轮转出的日志文件(如access.log.1)在下一次轮转时才进行压缩。这确保了服务在轮转后仍有可读的未压缩日志可供使用,避免了某些应用(如数据库、监控工具)读取压缩文件带来的问题。

延时轮转的核心:dateext参数与日期格式定制

默认情况下,logrotate使用序号轮转(如log.1, log.2.gz),但更清晰的方式是使用日期扩展名,这就是"dateext"参数的作用。启用后,轮转出的日志文件名会包含日期(如access.log-20231015.gz),便于直观查找。结合"dateyesterday"参数,甚至可以使用前一天的日期作为扩展名,这对于在午夜过后立即执行的轮转任务非常有用。

/var/log/syslog {
    daily
    rotate 30
    compress
    dateext
    dateformat -%Y%m%d
    delaycompress
    missingok
    postrotate
        /usr/lib/rsyslog/rsyslog-rotate
    endscript
}

这里"dateformat"参数允许你自定义日期格式。格式符与"date"命令一致,"-%Y%m%d"会生成如“-20231015”的扩展名。日期格式的轮转不仅易于管理,也避免了序号轮转可能出现的混淆(特别是在手动清理或跨月时)。延时压缩(delaycompress)与日期扩展名结合,意味着你看到的未压缩文件将是access.log-20231015,而压缩后变为access.log-20231015.gz。

高级场景:基于大小的轮转与压缩算法选择

除了按时间轮转,logrotate也支持基于日志文件大小进行轮转,使用"size"参数(如size 100M, size 1G)。这在日志量暴涨的场景下非常有效,可以防止单个日志文件过大。当与压缩结合时,需要注意轮转频率可能增加,压缩操作本身会消耗CPU资源。对于性能敏感的环境,可以考虑调整压缩级别甚至更换压缩算法。

/var/log/app/application.log {
    size 200M
    rotate 10
    compress
    compresscmd /usr/bin/xz
    compressext .xz
    compressoptions -9
    delaycompress
    create
}

在这个配置中,我们使用了更高压缩比的xz工具替代默认的gzip。"compresscmd"指定压缩程序路径,"compressext"指定压缩后扩展名,"compressoptions"传递参数(-9代表最高压缩比)。虽然xz压缩更省空间,但CPU消耗更大,需权衡取舍。延时压缩在此依然适用,确保轮转后有一个未压缩的版本可供即时分析。

确保服务连续性的postrotate脚本配置

日志轮转过程中,最大的风险是丢失正在写入的日志条目或导致服务中断。许多服务(如Nginx, Apache, MySQL, Rsyslog)需要接收信号以重新打开日志文件。这通过在logrotate配置中添加"sharedscripts"和"postrotate"脚本块实现。"sharedscripts"确保多个日志路径的配置只运行一次后处理脚本,而"postrotate"内的命令则在日志轮转后执行。

/var/log/mysql/mysql.log /var/log/mysql/slow.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    create 640 mysql adm
    sharedscripts
    postrotate
        # 向MySQL发送信号重新打开日志文件
        if [ -f /var/lib/mysql/mysqld.pid ]; then
            kill -USR1 `cat /var/lib/mysql/mysqld.pid`
        fi
    endscript
}

脚本必须准确且具有容错性(如使用"if"检查PID文件存在)。对于不支持的信号的服务,可能需要重启服务,但这会影响可用性。因此,测试postrotate脚本在沙盒环境中的执行至关重要。

排错与性能优化实战建议

配置完成后,使用"logrotate -d /etc/logrotate.d/your_config"进行调试模拟,它会显示执行步骤但不实际轮转。使用"logrotate -f"强制立即运行轮转以测试。常见的故障包括:权限错误(日志文件与create指令指定的用户/组不符)、脚本执行失败、磁盘空间不足导致压缩失败。

性能优化方面,对于高频轮转的日志,考虑禁用压缩(nocompress)或使用低压缩级别(如gzip的-1级别)。监控logrotate的cron任务(通常位于/etc/cron.daily/logrotate)执行时间,避免在系统高峰时段运行。对于海量日志,可以结合日志收集系统(如Fluentd, Logstash)进行实时外转,减轻服务器本地压力。

综合配置示例与长期维护策略

以下是一个综合了压缩、延时轮转、日期扩展名和健壮后处理脚本的范例,适用于大多数自定义应用日志:

/var/log/myapp/*.log {
    daily
    rotate 30
    maxage 90
    compress
    delaycompress
    dateext
    dateformat -%Y%m%d
    missingok
    notifempty
    copytruncate
    create 0640 appuser appgroup
    sharedscripts
    postrotate
        # 这里放置重启应用或发送信号的命令
        systemctl reload myapp 2>/dev/null || true
    endscript
}

这里引入了几个新参数:"maxage 90"会删除超过90天的轮转日志,即使数量未达rotate限制;"copytruncate"是一种替代创建新文件的方法,它先复制原日志文件再清空原文件,适用于无法通过信号通知重启日志写入的程序,但请注意复制过程中可能丢失少量日志。

长期维护时,建议定期审查/etc/logrotate.d/下的所有配置,确保没有陈旧的日志路径。利用监控工具(如Prometheus + Node Exporter)监控日志目录的磁盘使用量增长趋势。最后,将logrotate配置纳入版本控制系统(如Git),任何变更都有记录可回溯,这是专业运维的必备实践。

通过精确配置压缩与延时轮转,你不仅能有效节省服务器磁盘空间,还能确保日志切割过程的平滑与服务的连续性,为系统稳定性和问题排查提供坚实的数据基础。