技术文章2026 年 1 月 14 日约 2.5 分钟

Linux 日志管理:journalctl 与 logrotate 实践

通过 journald 和 logrotate 控制日志留存、轮转与压缩,避免日志占满系统磁盘。

日志把磁盘写满,是运维事故里最「冤」的一种:业务没挂、进程没崩,就是 / 100%,服务全瘫。这篇文章讲 journald 和 logrotate 怎么配,才能让日志既查得到、又不占死磁盘。

#journald:先确认持久化开了没有

journald 默认把日志放内存(/run/log/journal),重启就没了。要持久化,先建目录:

bash
sudo mkdir -p /var/log/journal
sudo systemctl restart systemd-journald
journalctl --disk-usage       # 现在能看到占用

然后限制体积,编辑 /etc/systemd/journald.conf:

ini
[Journal]
Storage=persistent
SystemMaxUse=2G
SystemKeepFree=4G
MaxRetentionSec=30d
Compress=yes

SystemMaxUse 是 journald 自己管的上限,满了自动删最旧的;SystemKeepFree 保证磁盘始终留 4G 给系统。改完 systemctl restart systemd-journald 生效。已经超了想立刻腾空间:

bash
journalctl --vacuum-size=1G      # 删到 1G 以下
journalctl --vacuum-time=14d     # 只留 14 天

#查日志的正确姿势

journald 全家桶是排障主力,比翻文件效率高得多:

bash
journalctl -u myapp --since "1 hour ago"
journalctl -u myapp -p warning..emerg
journalctl -k -b -1              # 上次开机的内核日志(查 panic 神器)
journalctl -f -u nginx

配合 -o json-pretty 可以导出结构化日志,接监控系统很方便。

#logrotate:管住「自己写文件」的日志

journald 只管 journal,像 nginx、tomcat 自己写文件的日志,得靠 logrotate。配置在 /etc/logrotate.d/ 下,每个服务一个文件。nginx 的典型配置:

text
/var/log/nginx/*.log {
    daily
    rotate 14
    compress
    delaycompress
    dateext
    missingok
    notifempty
    create 0640 nginx adm
    sharedscripts
    postrotate
        [ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
    endscript
}

几个字段的实际含义:

  • rotate 14:保留 14 份,加上当前文件共 15 份。
  • compress:轮转后 gzip;delaycompress 让刚轮转的那一份先不压,方便立刻查。
  • postrotate:轮转后通知进程重开日志文件句柄。nginx 用 kill -USR1;Java 应用如果自己持有文件句柄不释放,就得靠 copytruncate。
  • dateext:文件名带日期,避免覆盖同名文件。

copytruncate vs create 的选择:create 是标准做法(改名旧文件、创建新文件、通知进程);只有那些无法通过信号重开句柄的程序才用 copytruncate(先复制再清空原文件,代价是复制瞬间会丢一点点日志,而且文件大小变化对 daily 判断有影响)。

#Docker 是日志占磁盘的重灾区

容器里 stdout 默认写到宿主机的 JSON 文件,跑几天就是几十 G。别只靠 logrotate,直接在 docker daemon 配好:

json
{
  "log-driver": "json-file",
  "log-opts": { "max-size": "20m", "max-file": "5" }
}

改完 systemctl restart docker。已经吃掉的可以立刻清:

bash
du -sh /var/lib/docker/containers/*/*-json.log | sort -h | tail
truncate -s 0 /var/lib/docker/containers/<id>/<id>-json.log

#验收:模拟一次打满

给日志留 20G、业务正常、磁盘 30% 占用,用 dd if=/dev/zero 灌一个 2G 文件到日志目录,观察 journald 的 SystemMaxUse 是否触发自动清理、logrotate 是否按时轮转。验证完删掉测试文件。日志管理的验收标准只有一个:磁盘水位线恒定,服务可用性不受日志影响。

写于 2026 年 1 月 14 日

栏目
技术文章
约
2.5 分钟
字数
2K
阅读
150

本文为原创记录,转载请注明出处。如果这篇替你省了时间,欢迎留言说说你踩到的坑。

同题 · related

留言 · remarks

00 条

还没有留言,来说点什么吧。

Linux 日志管理:journalctl 与 logrotate 实践 · LXH·BLOG