这是《Linux 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 日志是排障和审计的证据。Linux 日志涉及内核 ring buffer、systemd journal、syslog、应用文件日志、容器 stdout、日志轮转和集中采集。治理日志要同时回答:写在哪里、能留多久、是否结构化、如何脱敏、如何报警。
10.1 日志全景
Kernel
-> dmesg / journald
systemd service
-> journald
-> stdout / stderr
rsyslog / syslog-ng
-> /var/log/messages
-> /var/log/syslog
-> remote syslog
Application
-> file
-> stdout
-> collector
Container runtime
-> stdout / stderr
-> kubelet / container log driver
常见路径:
| 路径 | 内容 |
|---|---|
/var/log/messages |
RHEL 系常见通用日志 |
/var/log/syslog |
Debian 系常见通用日志 |
/var/log/auth.log |
Debian 系认证日志 |
/var/log/secure |
RHEL 系认证日志 |
/var/log/dmesg |
启动时内核日志快照 |
/var/log/nginx/ |
Nginx 日志 |
/run/log/journal/ |
运行时 journal |
/var/log/journal/ |
持久 journal |
发行版差异明显,以实际配置为准。
10.2 内核日志
实时查看:
dmesg -w
dmesg -T
dmesg -T --level=err,warn
重点关键字:
dmesg -T | grep -Ei 'oom|out of memory|killed process'
dmesg -T | grep -Ei 'error|fail|timeout|i/o'
dmesg -T | grep -Ei 'conntrack|nf_conntrack'
常见信息:
| 关键字 | 方向 |
|---|---|
| Out of memory | 内存压力和 OOM |
| I/O error | 磁盘或存储链路 |
| EXT4-fs error | 文件系统异常 |
| XFS | XFS 文件系统信息 |
| blocked for more than 120 seconds | IO 阻塞 |
| conntrack: table full | 连接跟踪表满 |
| segfault | 进程非法内存访问 |
10.3 journalctl
服务:
journalctl -u app
journalctl -u app -f
journalctl -u app -n 200 --no-pager
journalctl -u app --since '2026-08-25 10:00'
journalctl -u app --since '1 hour ago' -p warning
系统:
journalctl -b
journalctl -b -1
journalctl --since today
journalctl -p err
journalctl --disk-usage
JSON 输出:
journalctl -u app -o json-pretty -n 1
磁盘治理:
sudo journalctl --vacuum-size=2G
sudo journalctl --vacuum-time=14d
10.4 rsyslog
配置文件:
/etc/rsyslog.conf
/etc/rsyslog.d/*.conf
传统规则:
facility.priority action
auth.* /var/log/auth.log
*.info;mail.none /var/log/messages
示例:把应用 local1 日志写入独立文件:
# /etc/rsyslog.d/30-app.conf
local1.* /var/log/app/syslog.log
& stop
重启:
sudo systemctl restart rsyslog
发送远端:
*.* @@log.example.internal:6514
一个 @ 常见为 UDP,两个 @ 常见为 TCP;TLS 需要额外模块和证书配置。
10.5 应用日志设计
日志级别:
| 级别 | 用途 |
|---|---|
| TRACE | 细粒度跟踪,默认关闭 |
| DEBUG | 开发诊断,生产谨慎开启 |
| INFO | 关键业务动作和状态 |
| WARN | 可恢复异常、降级、重试 |
| ERROR | 影响请求或功能的错误 |
| FATAL | 进程即将退出 |
推荐字段:
{
"ts": "2026-08-25T10:00:00.123+08:00",
"level": "ERROR",
"service": "order",
"trace_id": "7f3a",
"span_id": "01",
"user_id": "10001",
"method": "POST",
"path": "/api/orders",
"status": 500,
"latency_ms": 120,
"error_type": "DbTimeout",
"message": "create order failed"
}
原则:
- 时间带时区;
- 输出结构化 JSON;
- 每个请求有 trace_id;
- 异常带类型和堆栈;
- 不记录明文密码、密钥、身份证号;
- ERROR 对应可行动事件;
- 避免 ERROR 洪水。
10.6 日志轮转
logrotate 配置目录:
/etc/logrotate.conf
/etc/logrotate.d/*
Nginx 示例:
/var/log/nginx/*.log {
daily
rotate 14
missingok
notifempty
compress
delaycompress
dateext
create 0640 www-data adm
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
endscript
}
测试:
sudo logrotate -d /etc/logrotate.d/nginx
sudo logrotate -f /etc/logrotate.d/nginx
-d 是 dry run,-f 是强制轮转。
应用自身有轮转能力时,避免和应用内轮转、logrotate 重复治理。
10.7 容器日志
查看:
docker logs <container>
docker logs -f --tail 100 <container>
kubectl logs <pod>
kubectl logs -f <pod> -c <container>
kubectl logs --previous <pod>
推荐容器应用输出到 stdout / stderr,由容器运行时和采集器统一处理。
不推荐:
- 容器内写无限增长文件;
- 依赖手工
docker exec看日志; - 把敏感信息打印到 stdout;
- 单行日志超过过大尺寸;
- 无日志上限的本地 JSON 文件驱动。
10.8 集中采集
常见链路:
App / journald / file
-> Fluent Bit / Filebeat / Vector
-> Kafka
-> Loki / Elasticsearch / OpenSearch
-> Grafana / Kibana
采集关注:
| 项目 | 说明 |
|---|---|
| 位置 | file offset、journal cursor |
| 解析 | JSON、多行堆栈 |
| 脱敏 | 密码、token、手机号 |
| 路由 | 按服务和环境 |
| 缓冲 | 本地缓冲和背压 |
| 丢失策略 | 崩溃、磁盘满、远端不可用 |
| 时区 | 统一时区 |
多行日志示例:
ERROR order create failed
java.lang.NullPointerException
at com.example.order.Service.create(Service.java:20)
必须把堆栈归并到同一事件,否则搜索和统计都会失真。
10.9 日志检索技巧
错误:
grep -E 'ERROR|FATAL' app.log
journalctl -u app -p err --since '1 hour ago'
时间范围:
sed -n '/2026-08-25 10:00/,/2026-08-25 10:10/p' app.log
按 trace:
grep 'trace_id=7f3a' app.log
jq 'select(.trace_id == "7f3a")' events.json
压缩日志:
zgrep ERROR app.log.2.gz
注意日志时间可能来自不同机器,需要确认 NTP 或 chronyd 状态。
10.10 日志告警
告警类型:
| 类型 | 示例 |
|---|---|
| 错误率 | 5 分钟 ERROR / 总请求 |
| 关键字 | OOM、certificate expired |
| 缺失 | 心跳日志超过阈值未出现 |
| 延迟 | 日志时间与采集时间差距大 |
| 容量 | 采集器队列积压 |
| 审计 | root 登录、sudo 失败 |
告警要能行动:
告警名称
-> 影响什么
-> 可能原因
-> 排查入口
-> 处理手册链接
不要把所有 ERROR 都设为电话告警,先按业务影响分级。
10.11 生产案例
案例一:磁盘被日志占满
df -hT
du -sh /var/log/*
ls -lh /var/log/app
cat /etc/logrotate.d/app
处理:
- 紧急清理已轮转压缩文件;
- 修复轮转配置;
- 降低 DEBUG 输出;
- 增加容量告警;
- 接入集中日志后缩短本地留存。
案例二:看不到服务日志
systemctl status app
journalctl -u app -n 100
systemctl cat app
ls -l /proc/$(systemctl show -p MainPID --value app)/fd
可能原因:
- StandardOutput 被丢弃;
- 应用写到文件;
- 日志级别配置错误;
- 服务实际没有起来;
- journald 限制或采集器失败。
案例三:多行堆栈被拆散
检查采集器 multiline 配置:
以非 ERROR/WARN//INFO 开头的行
-> 归并到上一条日志
同时设置最大归并时长和最大行数,防止异常日志无限合并。
本章小结
Linux 日志由内核、journal、syslog、应用和容器多个来源组成。生产日志要结构化、带链路 ID、可轮转、可采集、可脱敏、可告警。排障时先按时间和服务缩小范围,再从系统日志进入应用日志,最终形成完整证据链。
思考题
dmesg和journalctl分别适合看什么?- 日志轮转后为什么需要通知应用或 Nginx?
- 容器应用为什么推荐输出 stdout?
- 如何设计敏感信息脱敏?
- 设计一个服务错误率告警,包含排查入口和处理手册。