Linux 日志系统完全指南:从 journalctl 到 rsyslog 与 logrotate 实战排障

在 Linux 运维的日常里,不管是 SSH 登录失败、服务莫名宕机、磁盘写满、还是内核报错,排查第一步几乎永远是”翻日志”。但很多新手面对 /var/log 下一堆文件、journalctl 一长串参数就犯难:日志到底在哪看?怎么按时间、服务、严重级别过滤?日志会不会把磁盘塞满?本文以 Ubuntu 22.04 / Debian 11 / CentOS 7-9 全系兼容的视角,系统讲清 Linux 日志的体系结构、journalctl 与 rsyslog 的分工、logrotate 轮转机制,以及常见故障的真实排查流程,把”看日志”从玄学变成肌肉记忆。

一、Linux 日志的体系结构:三个层次、三拨人

Linux 的日志不是单一进程在管,而是内核、systemd 套件、传统 syslog 共同协作。搞清楚这三者边界,排查时才不会找错地方。

  • 内核日志:由内核 ring buffer 产生,可被 dmesg 命令读取;systemd 启动后,kern.info 及以上级别会被转交给 journald 持久化。
  • systemd-journald 日志:RHEL/CentOS/Debian/Ubuntu 现代发行版的默认日志守护进程,把内核 + 所有 systemd 服务 + 早期启动阶段的 stdout/stderr 收集为结构化二进制日志(IndexedDB 风格的 journal 文件)。
  • rsyslog(或 syslog-ng)传统文本日志:兼容 RFC 5424 协议,把日志按 facility(认证、内核、邮件等)和 priority(emerg 到 debug 八级)分流到 /var/log/ 下的纯文本文件,方便 grep / awk / 第三方日志收集器(Loki、ELK)直接吃。

简单记忆:journald 是”中央仓库”(默认二进制持久化在 /run/log/journal),rsyslog 是”分发器”(写到传统文本)。两者并存不冲突,排查时按工具特性选——结构化查询走 journalctl,长文本检索 grep 走 /var/log。

二、journalctl 实战:按时间、服务、严重级别精准定位

journalctl 是 systemd 时代最常用的日志入口,几个高频组合拳记住就够用。

2.1 基础查看与过滤

# 查看本次启动以来的全部日志(按时间正序)
journalctl -b

# 查看上一次启动的日志(用于崩溃后排障)
journalctl -b -1

# 只看内核日志(等价于 dmesg 但带时间戳)
journalctl -k

# 只看某个服务(以 nginx 为例)
journalctl -u nginx --since today

# 按时间窗口过滤
journalctl --since "2026-08-23 09:00" --until "2026-08-23 10:00"

# 按严重级别过滤(0=emerg 7=debug)
journalctl -p err -b
journalctl -p warning..err -b

2.2 实时跟踪与结构化字段

# 实时跟踪某个服务的新日志,类似 tail -f
journalctl -u sshd -f

# 显示完整字段(PID、单元、进程可执行文件路径等)
journalctl -u nginx -o verbose

# 以 JSON 格式输出,适合接 jq 做二次处理
journalctl -u nginx -o json | jq '.PRIORITY, .MESSAGE'

如果 journalctl 提示 “No journal files were found”,通常是 /var/log/journal 目录没建,日志只暂存在 /run/log/journal(重启即丢),手动建一下目录并改权限即可让 journald 开始持久化:

sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

三、/var/log 目录长啥样:经典文本日志逐个拆解

很多老管理员更习惯直接 ls /var/log 看文件。不同发行版命名有差异,但本质上的”八股文件”高度相似,下面给一个跨发行版的速查表。

3.1 高频必看文件

  • /var/log/syslog(Debian/Ubuntu)或 /var/log/messages(RHEL/CentOS):系统全局日志的兜底通道,服务没有专属日志时大多汇到这里。
  • /var/log/auth.log(Debian/Ubuntu)或 /var/log/secure(RHEL/CentOS):所有 pam 认证、sudo、SSH 登录记录,排查”谁在什么时候登了/失败了”必看。
  • /var/log/kern.log:内核模块加载、网卡驱动、硬件错误、OOM Killer 触发记录。
  • /var/log/cron(Red Hat 系)或 /var/log/syslog(Debian 系)中的 cron 行:定时任务的执行结果,排查 crontab 任务为什么没跑、为什么报错非常直接。
  • /var/log/dmesg:启动阶段的 dmesg 缓冲内容,适合看开机时挂载、磁盘识别失败等。

一个真实排查例子:某台服务器 SSH 突然连不上,先 ssh -vvv 看加密协商哪一步卡住,再去 /var/log/secure 看有没有 Failed password 记录,如果大量失败通常是被 fail2ban/denyhosts 拉黑了,或 sshd_config 里 MaxAuthTries / PasswordAuthentication 配置变更了——这类问题跟 SSH 服务配置和密钥登录策略深度耦合,具体可以参考站内 《SSH 完全实战指南:从密钥免密登录到端口安全与跳板配置》 进一步对齐安全侧细节。

3.2 高效文本检索技巧

# 看最近 200 条认证日志并实时滚动
sudo tail -200f /var/log/auth.log | grep -i "fail\|invalid"

# 查某个服务最近一次报错时间
grep -n "ERROR\|FATAL" /var/log/syslog | tail -20

# 按时间窗口过滤(Debian auth 日志格式 Aug 23 09:31:22 ...)
grep "^Aug 23 09:" /var/log/auth.log

注意 grep journalctl 输出时如果遇到大量二进制字段,说明输出格式不对——journalctl 输出本身就带 -- Logs begin at ... 这种元数据行,用 --no-pager-o short 关掉后更干净。

四、logrotate:让日志不会塞爆磁盘

没人管的话,/var/log/access.log 一个 Web 服务一天就能写几十 GB,迟早把根分区撑爆。logrotate 就是 Linux 自带的”定时压缩 + 删除老日志”管家,默认由 cron(daily)触发,所有规则集中在 /etc/logrotate.conf/etc/logrotate.d/ 目录。

4.1 一个典型的自定义规则

/var/log/myapp/*.log {
    daily
    rotate 14
    missingok
    notifempty
    compress
    delaycompress
    sharedscripts
    postrotate
        systemctl reload myapp.service > /dev/null 2>&1 || true
    endscript
}

逐项拆解:

  • daily:每天轮转(还有 weekly/monthly/yearly 可选);
  • rotate 14:保留 14 份历史(.gz 压缩包 + 当前文件共 14 份);
  • missingok:日志不存在不报错;
  • notifempty:空文件不轮转;
  • compress / delaycompress:用 gzip 压缩且延后一轮再压(防止当前正在被进程写入);
  • sharedscripts + postrotate:对匹配通配符的多个文件只跑一次 reload,避免服务被反复重启。

4.2 手动测试与排查

# 强制立即轮转(debug 模式查看详细动作)
sudo logrotate -dv /etc/logrotate.conf

# 只针对某个规则跑一次真实轮转
sudo logrotate -f /etc/logrotate.d/myapp

如果发现 logrotate 没按预期生效,先看 /var/lib/logrotate/status 里这个规则上次执行的时间戳,如果一周没动,八成是 cron.daily 没跑——这又回到定时任务的话题,可以对照站内 《Linux 定时任务完全指南:从 crontab 到 systemd timer 自动化任务管理实战》 检查 cron 与 systemd timer 的实际触发情况。

五、故障排查实战:四个高频场景走一遍

5.1 场景一:服务突然挂了,systemctl status 看不出原因

先看 status 的日志末尾,再用 journalctl 拉更早的上下文:

systemctl status nginx --no-pager -l
journalctl -u nginx -n 100 --no-pager
journalctl -u nginx -p err -b

如果服务是因为 OOM 杀掉的,可以追加 -p emerg 或直接翻 /var/log/kern.log 找 Out of memory: Kill process,这种情况通常伴随系统整体资源拉满——结合进程监控一起看才高效,具体手法可以参考站内 《Linux 进程管理完全指南:从 ps/top 命令到系统资源监控实战》

5.2 场景二:磁盘被日志塞满

df -h 看到 /var 100%,先用 du -sh /var/log/* | sort -h 找最大元凶。常见是某一服务忘了配 logrotate(典型如 nginx 默认 access.log 永不轮转),临时急救可以 :> /var/log/nginx/access.log 清空(不要 rm 再建,会让进程 fd 错乱),然后补 logrotate 规则。

5.3 场景三:内核报错 / 硬件故障

dmesg -T | grep -iE "error|fail|warn" 看最近的内核事件,关键词 I/O error(磁盘坏道)、link is not ready(网卡链路)、thermal(过热)、hardware name(CPU 微码错误) 都是进一步行动的直接信号。

5.4 场景四:登录审计与入侵排查

看 /var/log/auth.log 配合 lastlastbwho 三件套,定位最近成功/失败登录的 IP 与时间。如果发现大量境外 IP 撞 SSH 22 端口,说明公网暴露的 SSH 服务正在被扫——必须立刻上密钥登录、改 22 端口、或者前面那条 SSH 实战文中提到的端口敲门/跳板配置。

六、进阶:日志集中化与远端审计

单机 /var/log 看日志适合十几台的小机房,但当主机数上到几十几百台,挨台 SSH 翻日志就是人肉低效。常见做法:

  • syslog over TLS:rsyslog 直接把日志 UDP/TCP 发送到远程收集器(ELK、 Loki、Graylog),集中存储与索引;
  • auditd:Linux 内置审计守护,记录 syscall 级行为(谁动了 /etc/passwd、谁改了文件),适合合规场景;
  • journald remote forward:通过 systemd-journal-remote + systemd-journal-upload 把客户端 journal 上传到中央节点。

至于选哪条路,取决于合规要求、流量成本和团队熟悉度——小团队起步通常一个 Loki + Grafana Agent 就能解决 80% 的痛点。

七、写在最后:排障铁律三条

第一,先定位时间窗,再定位服务,再定位日志文件,最后才看具体行——漫无目的地 cat 整个日志是最慢的;第二,生产环境任何清理 / 删除操作前先备份或确认可重建,日志再大也是事故现场证据;第三,日志习惯是一次配好的,日常运维就不再为它操心——把 logrotate、journald 持久化、关键日志外发三件事一次性配齐,后续排查效率会质变。

© 版权声明
THE END
喜欢就支持一下吧
点赞9赞赏 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容