在Ubuntu服务器上管理日志文件,最常用也最可靠的工具就是logrotate。它的核心作用就是自动压缩旧日志、删除超期日志,从而控制磁盘空间占用。具体操作方法是:编辑对应的logrotate配置文件(通常在/etc/logrotate.d/目录下),设置rotate(保留轮转次数)、compress(压缩)、delaycompress(延迟压缩)、daily/weekly/monthly(轮转周期)、maxage(最大保留天数)等参数即可。比如你想让Nginx日志每天轮转、压缩并保留30天,只需在配置中写上daily、rotate 30、compress、delaycompress、missingok、notifempty这几行关键参数,系统就会自动帮你完成所有工作。

很多运维新手第一次接触logrotate时会觉得配置文件看起来很复杂,但实际上核心参数就那么几个。今天这篇文章就从原理到实操,把Ubuntu上logrotate压缩旧日志并保留指定天数的所有细节一次性讲透。

logrotate到底是什么、为什么要用它

logrotate是Linux系统自带的日志轮转工具,Ubuntu默认就已经安装好了。它的工作原理很简单:按照你设定的时间周期(每天、每周、每月),把当前正在写入的日志文件重命名(比如access.log变成access.log.1),然后创建一个新的空日志文件继续接收数据。旧的日志文件如果超过了你设定的保留数量或天数,就会被自动删除。

如果不用logrotate会怎样?日志文件会无限增长,几个月后可能占满整个磁盘,导致服务崩溃、系统无法写入任何数据。这不是夸张,生产环境中因为日志爆满导致宕机的案例非常多。所以logrotate不是可选项,而是必选项。

Ubuntu上logrotate的配置文件在哪里

Ubuntu系统中logrotate的主配置文件是/etc/logrotate.conf,但日常运维中你几乎不需要动这个文件。真正需要修改的是/etc/logrotate.d/目录下的各个子配置文件。每个服务通常都有自己独立的配置文件,比如:

/etc/logrotate.d/nginx
/etc/logrotate.d/apache2
/etc/logrotate.d/rsyslog
/etc/logrotate.d/mysql
/etc/logrotate.d/ufw

如果你的某个服务没有自动生成配置文件,你可以手动在这个目录下创建一个,文件名随意,但要以.conf或不带后缀结尾都行,logrotate会读取该目录下所有文件。

核心参数详解:控制压缩和保留天数的关键

下面把最重要的参数逐一拆解,这些是你配置日志轮转时必须掌握的:

rotate N:保留N个轮转后的日志文件。比如rotate 30,就是保留30个旧日志。如果配合daily使用,大约就是保留30天。但注意,rotate是按文件个数算的,不是严格按天数算。

daily / weekly / monthly:定义轮转周期。daily表示每天轮转一次,weekly每周,monthly每月。这三个参数互斥,选一个就行。

maxage N:这个参数非常关键,它直接按天数删除超过N天的日志,不管rotate设了多少。比如maxage 30,就会删除30天以前的所有轮转日志。这个参数在较新版本的logrotate中才支持(Ubuntu 18.04以上基本都支持)。

compress:启用gzip压缩。开启后旧日志会被压缩成.gz格式,通常能节省70%-90%的磁盘空间。

delaycompress:延迟一个轮转周期再压缩。也就是说,最新的一个旧日志(比如access.log.1)不会被立即压缩,等到下一次轮转时才压缩成access.log.2.gz。这个参数的好处是,如果某个程序还在读取上一轮的日志,不会因为压缩而读不到。

missingok:如果日志文件不存在,不报错。这在某些服务临时停止的情况下很有用。

notifempty:如果日志文件是空的,就不轮转。避免产生一堆空的压缩文件。

create 权限 所有者 组:轮转后创建新日志文件时的权限设置。比如create 640 www-data adm,表示新文件权限640,属主www-data,属组adm。

dateext:使用日期作为轮转文件后缀,比如access.log-20240115而不是access.log.1。配合daily使用时特别方便按日期查找。

实战配置:Nginx日志压缩并保留30天

下面给出一个完整的Nginx日志轮转配置示例,这是生产环境中最常见的场景:

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

这段配置的含义是:每天对/var/log/nginx/目录下所有.log文件进行轮转,保留30个旧文件,启用压缩但延迟一轮再压,空文件不轮转,新文件权限640属主www-data。postrotate里的命令是通知Nginx重新打开日志文件,否则Nginx会继续往旧文件里写。

如果你想用maxage参数更精确地控制天数,可以这样写:

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

这里把rotate 30换成了maxage 30,效果是一样的(每天轮转的情况下),但maxage更直观,就是"超过30天的全部删掉"。如果你的轮转周期是weekly,那rotate 4和maxage 28效果接近但不完全一样,这时候maxage更准确。

自定义服务的日志轮转配置

如果你自己写的应用程序日志不在/var/log下的标准位置,比如在/opt/myapp/logs/app.log,你可以创建一个专属配置文件:

sudo nano /etc/logrotate.d/myapp

然后写入:

/opt/myapp/logs/app.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    dateext
    maxage 14
    create 0640 myappuser myappgroup
}

这个配置会让你的应用日志每天轮转、压缩、保留14天。dateext让文件名带上日期,方便排查问题时快速定位。

logrotate的执行机制和手动测试

logrotate不是实时运行的,它通过cron定时任务来执行。在Ubuntu上,默认的cron任务是/etc/cron.daily/logrotate,也就是每天凌晨执行一次。你可以用以下命令查看:

cat /etc/cron.daily/logrotate

如果你想立即测试配置是否正确,而不是等到明天,可以用调试模式运行:

sudo logrotate -d /etc/logrotate.d/nginx

-d参数是debug模式,只会打印将要执行的操作,不会真正执行。确认没问题后,再用强制执行模式测试:

sudo logrotate -f /etc/logrotate.d/nginx

-f参数会强制执行一次轮转,不管时间到没到。生产环境中建议先用-d验证,避免误操作。

常见问题排查和注意事项

第一个常见问题:日志文件权限不对导致轮转失败。确保logrotate运行时的用户(通常是root)对日志文件有读写权限,新创建的文件权限也要和你的服务进程匹配。

第二个问题:postrotate脚本没写对,服务不重新打开日志。不同服务的信号不同,Nginx是USR1,Apache是graceful或USR1,rsyslog是HUP。如果不确定,查对应服务的文档。

第三个问题:压缩后磁盘空间没有明显减少。这通常是因为delaycompress导致最新一轮没压缩,或者compress和nocompress冲突了。检查配置文件里是否同时出现了这两个参数,它们是互斥的。

第四个问题:想保留超过几十天的日志但又不想占太多空间。可以用compress配合maxage,或者用更激进的压缩方式,比如把compress改成用xz或zstd(需要logrotate支持,Ubuntu 20.04以上部分支持)。不过gzip在兼容性和速度上是最稳妥的选择。

第五个问题:多个配置文件对同一日志文件生效导致冲突。比如/etc/logrotate.d/rsyslog和你自建的配置都匹配了/var/log/syslog,就会执行两次。解决办法是确保每个日志路径只被一个配置文件管理。

进阶技巧:按日志大小轮转而非按时间

除了按时间轮转,logrotate还支持按文件大小轮转,参数是size。比如:

/var/log/myapp/app.log {
    size 100M
    rotate 10
    compress
    delaycompress
    missingok
    notifempty
}

这表示当日志文件超过100MB时才触发轮转,保留10个旧文件。这种方式适合日志写入速度不均匀的场景。但要注意,size和daily/weekly/monthly不能同时使用,它们是互斥的。

查看logrotate执行状态和日志

logrotate执行后会生成状态文件/var/lib/logrotate/status,记录了每个日志文件上次轮转的时间。你可以用以下命令查看:

sudo cat /var/lib/logrotate/status

如果你想看logrotate的执行记录,可以查看系统日志:

sudo grep logrotate /var/log/syslog

这些信息在排查轮转异常时非常有用。

总结:一套可直接复制的最佳实践

对于大多数Ubuntu服务器,我推荐的通用配置模板是:daily轮转 + compress压缩 + delaycompress延迟压缩 + maxage控制天数 + missingok容错 + notifempty避免空文件 + postrotate通知服务重新打开日志。这套组合在稳定性、磁盘节省和运维便利性之间取得了最好的平衡。把这个模板记下来,针对不同服务只需改路径和权限就行,能覆盖90%以上的场景。

最后提醒一点:配置改完后一定要用logrotate -d先验证,确认无误再-f强制执行一次。运维无小事,日志管理更是基础中的基础,把logrotate配好了,你的服务器至少在磁盘管理这一块可以高枕无忧。