主题
日志与排故
日志是服务器运行的"黑匣子"。没看日志就动手修 = 蒙眼做手术。本篇覆盖日志体系、journalctl 进阶和一套经过验证的排故方法论。
日志文件位置
bash
# Debian/Ubuntu
/var/log/syslog # 系统主日志(非内核)
/var/log/auth.log # 认证日志(sudo、ssh 登录)
/var/log/kern.log # 内核日志
/var/log/dpkg.log # 包管理日志
/var/log/apt/ # APT 详细日志
/var/log/nginx/ # Nginx 日志(需单独安装)
# RHEL/Rocky/Alma
/var/log/messages # 系统主日志
/var/log/secure # 认证日志
/var/log/cron # 定时任务日志
/var/log/yum.log # 包管理日志
# 通用
/var/log/boot.log # 启动日志
/var/log/dmesg # 内核环缓冲日志
dmesg # 查看内核消息(实时)
dmesg -T # 带人类可读时间戳
dmesg | tail -50 # 最新 50 条journalctl 进阶
按时间段
bash
journalctl --since "2026-07-26 10:00:00"
journalctl --since "2026-07-26 10:00" --until "2026-07-26 12:00"
journalctl --since "1 hour ago"
journalctl --since "2 days ago"
journalctl --since today按服务
bash
journalctl -u nginx
journalctl -u nginx -u postgresql # 同时查看多个
journalctl _SYSTEMD_UNIT=nginx.service # 等价 -u nginx按优先级
优先级从低到高:debug(7) → info(6) → notice(5) → warning(4) → err(3) → crit(2) → alert(1) → emerg(0)
bash
journalctl -p err # emerg, alert, crit, err
journalctl -p warning # 包括 warning 及以上的
journalctl -p 3 # 数字等价 err高级过滤
bash
# 按用户
journalctl _UID=1000
# 按可执行文件
journalctl _EXE=/usr/bin/sshd
# 按内核设备
journalctl _KERNEL_DEVICE=+usb
# 组合 + JSON 输出(方便程序处理)
journalctl -u nginx -p err --since "1 hour ago" -o json-pretty
# 查看磁盘用量
journalctl --disk-usage日志持久化
默认 journald 只把日志存内存(/run/log/journal),重启就没了。改为持久化:
bash
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald排故方法论
核心原则
- 一条链路查到底:从用户请求 → 网络 → 服务 → 数据库,按数据流方向排查
- 一次只改一处:改完验证,确认有效再改下一个。别一次改三个配置,然后不知道哪个起作用了
- 先看日志再操作:出问题时第一反应不是重启,而是
tail -100看日志 - 记录变更:改了什么、为什么改。自己能回溯,别人能接手
排故流程
1. 明确症状 → "哪个服务/功能的什么表现不正常?"
2. 缩小范围 → 最近改过什么?什么时间开始的?
3. 检查日志 → journalctl -u xxx -p err --since "当时"
4. 复现问题 → 能稳定复现才说明找到了根因
5. 验证修复 → 修完测试,确认症状消失且没引入新问题
6. 复盘记录 → 写原因+排查过程+修复方案,下次更快定位实战案例
logrotate 日志轮转
日志不轮转会撑爆磁盘。logrotate 是标准方案:
bash
# 查看系统级 logrotate 配置
cat /etc/logrotate.conf
# 各应用独立的轮转规则
ls /etc/logrotate.d/
cat /etc/logrotate.d/nginx自定义轮转规则 /etc/logrotate.d/myapp:
/var/log/myapp/*.log {
daily # 每天轮转
rotate 30 # 保留 30 个副本
compress # 压缩旧日志
delaycompress # 延迟一天压缩(当前轮出的不压,方便查看)
missingok # 日志文件不存在不报错
notifempty # 空文件不轮转
create 640 myapp myapp # 轮转后创建新文件,设权限
sharedscripts
postrotate
systemctl reload myapp > /dev/null 2>&1 || true
endscript
}bash
# 手动测试轮转(-f 强制执行)
sudo logrotate -f /etc/logrotate.d/myapp
# 测试但不执行(-d debug 模式)
sudo logrotate -d /etc/logrotate.d/myapp案例 1:服务起不来怎么查
bash
# 症状:systemctl start myapp 失败
# 1. 看状态 + 最近日志
systemctl status myapp
# 输出通常包含退出码和最后几行日志
# 2. 查完整启动日志
journalctl -u myapp --since "2 min ago" -e
# -e 跳到末尾
# 3. 手动运行启动命令(模拟 systemd 环境)
# 注意:用服务的 User 身份运行
sudo -u myapp /opt/myapp/venv/bin/gunicorn app:app
# 这一步通常能直接看到错误信息
# 4. 常见原因排行榜:
# 第1名:配置文件路径不对/文件不存在(Permission denied/No such file)
# 第2名:端口已被占用(Address already in use)
# 第3名:环境变量缺失(数据库连接失败)
# 第4名:依赖服务没启动(Redis/PostgreSQL 连接超时)案例 2:磁盘满了定位
bash
# 1. 确认哪个分区满了
df -h
# 2. 找大目录(从根开始)
sudo du -sh /* 2>/dev/null | sort -hr | head -10
# 3. 通常是这几个地方:
# /var/log → 日志没轮转
sudo du -sh /var/log/* | sort -hr | head -5
# /tmp → 临时文件堆积
sudo du -sh /tmp/* | sort -hr | head -5
# Docker overlay → 镜像/容器/volumes 太多
docker system df
docker system prune -a # 清理无用镜像和容器
# 4. 找大文件
sudo find / -type f -size +500M -exec ls -lh {} \; 2>/dev/null | awk '{print $NF": "$5}' | sort -k2 -hr
# 5. 如果删除了文件但磁盘没释放
# 原因:进程还持有文件句柄
sudo lsof | grep deleted
# 重启对应的进程即可释放案例 3:网站 502 Bad Gateway 排查
bash
# 502 = 上游服务(应用/PHP-FPM)没响应
# 1. 查 Nginx 错误日志
tail -100 /var/log/nginx/error.log
# 2. 检查上游服务是否在运行
systemctl status php8.1-fpm # 或你的应用服务
# 3. 检查上游端口是否监听
ss -tlnp | grep :9000 # PHP-FPM 默认端口
ss -tlnp | grep :8000 # Gunicorn/Node 常用端口
# 4. 查看上游错误日志
journalctl -u php8.1-fpm -f
# 或应用日志
# 5. 检查系统资源(OOM 导致进程被杀?)
dmesg | grep -i "out of memory"
journalctl -k | grep -i oom
# 6. 确认连接数没打满
ss -tan | grep :80 | awk '{print $1}' | sort | uniq -c
# 大量 SYN_RECV → 可能被 SYN flood
# 大量 TIME_WAIT → 短连接太多生产环境经验
- 集中日志:生产服务器不要各看各的,上 ELK/Loki/Graylog
- 日志轮转:用 logrotate 定期压缩/删除旧日志,别让日志撑爆磁盘
- 时间同步:所有服务器 NTP 同步,否则跨服务器日志时间线对不上
- 关键日志告警:error 日志出现关键词(OOM、segfault、connection refused)自动告警
- 排故心态:不要猜,用数据和日志说话。不要慌,越急越容易误操作
🎯 本章要点
journalctl --since "2 days ago"按时间筛选系统日志- 认证日志在
/var/log/auth.log(sudo、SSH 登录记录) - 排故原则:先看日志、逐层排查、一次只改一处
加载练习题中...