15_日志排查:5 分钟定位 Linux 系统故障
日志排查:5 分钟定位 Linux 系统故障
Linux 系统的 “日志” 就像 “黑匣子”—— 当服务崩溃、硬件报错、网络中断时,所有关键信息都藏在日志里。很多新手排查故障时会 “四处乱找”,浪费大量时间;其实掌握journalctl
、dmesg
等工具,结合日志分析技巧,5 分钟内就能定位大部分问题。今天这篇文章,带你从 “日志工具使用” 到 “实战故障定位”,再到 “多服务器日志收集”,形成完整的日志排查能力。
一、基础工具:搞定日志 “查看” 与 “轮转”
排查故障前,先掌握两个核心工具:journalctl
(查看 systemd 日志,覆盖系统与服务)和logrotate
(日志轮转,避免日志撑爆磁盘),这是日志排查的 “基本功”。
1. journalctl:systemd 日志的 “全能查看器”
大部分现代 Linux(Ubuntu 16.04+、CentOS 7+)用 systemd 管理服务,对应的日志统一存在journalctl
中,涵盖系统启动、服务运行、内核报错等信息,无需记住多个日志文件路径。
(1)核心用法:3 个高频场景
需求 | 命令 | 关键参数解读 |
---|---|---|
查看某服务日志(如 Nginx) | journalctl -u nginx |
-u :指定服务单元(unit),只显示该服务的日志 |
实时追踪日志(类似 tail -f) | journalctl -u nginx -f |
-f :实时跟随日志输出,新日志会自动刷新 |
按时间筛选日志(近 1 小时) | journalctl -u nginx --since "1 hour ago" |
--since /--until :按时间范围筛选,支持 “10min ago”“2024-10-25 14:00” 等格式 |
(2)进阶筛选:快速定位关键日志
排查故障时,常需要按 “错误级别”“关键字” 筛选,减少无效信息:
\# 1. 只看Nginx的错误日志(优先级err及以上:err/warning/crit/alert/emerg)
journalctl -u nginx -p err # -p:指定优先级(priority)
\# 2. 搜索包含“failed”关键词的Nginx日志(大小写不敏感)
journalctl -u nginx -i | grep "failed" # -i:grep忽略大小写
\# 3. 查看某时间段内的内核日志(内核日志用\_-kernel.service单元)
journalctl -u \_-kernel.service --since "2024-10-25 14:00" --until "2024-10-25 14:30"
(3)避坑:journalctl 日志不持久化
默认情况下,journalctl
日志只保存在内存中,重启后丢失。若需持久化(长期保存日志),需手动配置:
\# 1. 创建日志存储目录
sudo mkdir -p /var/log/journal
\# 2. 重启systemd-journald服务
sudo systemctl restart systemd-journald
\# 3. 验证:重启后 journalctl -u nginx 仍能看到之前的日志
2. logrotate:日志轮转的 “自动管家”
应用日志(如 Nginx、MySQL)会持续增长,若不处理,可能几小时就占满磁盘(比如 10GB 的访问日志)。logrotate
能自动 “切割日志、压缩归档、删除旧日志”,是日志管理的必备工具。
(1)核心配置:理解 logrotate 规则
logrotate
的配置文件分两类:
-
全局配置:
/etc/logrotate.conf
(定义默认规则,如默认保留 4 份轮转日志); -
应用配置:
/etc/logrotate.d/
目录下(针对单个应用,如/etc/logrotate.d/nginx
,优先级高于全局配置)。
(2)实战:配置 Nginx 日志轮转
以 Nginx 日志(/var/log/nginx/access.log
和error.log
)为例,编写轮转配置:
\# 1. 创建Nginx的logrotate配置文件
sudo vim /etc/logrotate.d/nginx
\# 2. 写入以下配置(逐行解读)
/var/log/nginx/\*.log { # 匹配Nginx的所有.log文件
  daily # 轮转周期:每天1次(可选weekly/monthly)
  rotate 7 # 保留7份归档日志(超过7天的自动删除)
  compress # 归档日志用gzip压缩(节省磁盘空间)
  delaycompress # 延迟压缩:只压缩前一天的日志(避免正在写的日志被压缩)
  missingok # 若日志文件不存在,不报错(避免手动删除日志后轮转失败)
  notifempty # 若日志为空,不执行轮转
  create 0640 www-data www-data # 新建日志文件的权限、所有者、所属组(匹配Nginx运行用户)
  sharedscripts # 所有日志文件轮转后,只执行一次postrotate脚本
  postrotate # 轮转后执行的脚本(Nginx需重新打开日志文件,否则继续写旧日志)
  if \[ -f /var/run/nginx.pid ]; then
  kill -USR1 \`cat /var/run/nginx.pid\` # 发送USR1信号,Nginx重新打开日志
  fi
  endscript
}
(3)验证:测试 logrotate 配置是否生效
配置后,无需等待 “每天轮转”,可手动触发测试:
\# 1. 测试配置(无报错说明配置正确)
sudo logrotate -d /etc/logrotate.d/nginx # -d:dry run,只模拟,不实际执行
\# 2. 强制执行轮转(实际切割日志)
sudo logrotate -f /etc/logrotate.d/nginx # -f:force,强制轮转
\# 3. 验证结果:查看Nginx日志目录,会生成access.log.1.gz(归档压缩的旧日志)和新的access.log
ls -l /var/log/nginx/
二、实战排障:5 分钟定位两类高频故障
掌握工具后,结合 “系统服务故障” 和 “硬件故障” 两个场景,演示如何快速定位问题。
实战 1:Nginx 服务崩溃 —— 从日志找原因
场景:执行sudo systemctl start nginx
,提示 “Job for nginx.service failed because the control process exited with error code.”,需 5 分钟内定位崩溃原因。
步骤 1:1 分钟看 systemd 日志(初步定位)
先用journalctl
查看 Nginx 服务的错误日志,获取关键线索:
journalctl -u nginx -p err --no-pager # --no-pager:不分页,直接显示所有错误日志
常见错误日志与原因:
-
日志 1:
nginx: [emerg] bind() to ``0.0.0.0:80`` failed (98: Address already in use)
→ 原因:80 端口被其他进程占用(如 Apache);
-
日志 2:
nginx: [emerg] invalid parameter "worker_processes" in /etc/nginx/nginx.conf:2
→ 原因:Nginx 配置文件语法错误(第 2 行
worker_processes
参数无效); -
日志 3:
nginx: [emerg] open() "/var/log/nginx/error.log" failed (13: Permission denied)
→ 原因:Nginx 运行用户(www-data)无日志文件写入权限。
步骤 2:2 分钟查 Nginx 专属日志(精准定位)
systemd 日志可能不够详细,需查看 Nginx 自己的错误日志(路径在/etc/nginx/nginx.conf
中定义,默认/var/log/nginx/error.log
):
\# 查看错误日志的最后20行(最新错误)
tail -n 20 /var/log/nginx/error.log
举例:若日志显示2024/10/25 14:30:00 [crit] 1234#0: *5 open() "/var/www/html/index.html" failed (2: No such file or directory)
,说明 Nginx 配置的网站根目录/var/www/html
下缺少index.html
文件,导致访问时崩溃。
步骤 3:2 分钟验证并解决问题
-
若为端口占用:用
lsof -i :80
找到占用进程(如PID=567
的apache2
),sudo kill -9 567
关闭后,重启 Nginx; -
若为配置错误:用
nginx -t
检查配置语法(sudo nginx -t
),根据提示修改/etc/nginx/nginx.conf
,再重启; -
若为权限问题:执行
sudo chown -R www-data:www-data /var/log/nginx/
,赋予 Nginx 用户权限。
验证:sudo systemctl start nginx
,sudo systemctl status nginx
显示 “active (running)”,故障解决。
实战 2:硬件报错 —— 用 dmesg 解读内核日志
场景:服务器频繁卡顿,偶尔蓝屏,怀疑硬件故障(如磁盘坏道、内存错误),需通过内核日志排查。
步骤 1:1 分钟查看 dmesg 实时内核日志
dmesg
用于查看内核日志(包括硬件初始化、驱动报错、磁盘 / 内存故障),默认输出所有日志,需按 “错误关键词” 筛选:
\# 查看包含“error”“warn”“fail”关键词的内核日志(忽略大小写)
dmesg | grep -iE "error|warn|fail"
步骤 2:3 分钟解读常见硬件故障日志
(1)磁盘坏道(最常见)
日志特征:包含 “bad sector”“I/O error”“sdX”(X 为磁盘编号,如 sda):
\[1234.567890] sd 0:0:0:0: \[sda] Add. Sense: Unrecovered read error - auto reallocate failed
\[1234.567900] sd 0:0:0:0: \[sda] CDB: Read(10): 28 00 00 12 34 56 00 00 08 00
\[1234.567910] blk\_update\_request: I/O error, dev sda, sector 123456 op 0x0:(READ) flags 0x80700 phys\_seg 1 prio class 0
→ 解读:sda
磁盘的 123456 扇区有坏道,读取失败;
→ 解决:立即备份/dev/sda
上的数据,用fsck /dev/sda1
修复坏道,若频繁报错,更换磁盘。
(2)内存错误
日志特征:包含 “memory error”“EDAC”“MC0”(内存控制器):
\[7890.123456] EDAC MC0: UE error count (addr 0x12345678): 1
\[7890.123460] EDAC MC0: CE error count: 0
\[7890.123465] EDAC MC0: UE error (synd 0x12345678, addr 0x12345678, layer Memory, gran 64B)
→ 解读:内存地址0x12345678
出现不可纠正错误(UE),可能导致程序崩溃或蓝屏;
→ 解决:用memtest86+
工具检测内存(需重启从 U 盘启动),确认故障内存插槽后,更换内存条。
步骤 3:1 分钟保存 dmesg 日志(便于后续分析)
dmesg 日志在重启后会清空,需保存到文件:
\# 保存当前dmesg日志到文件
dmesg > /var/log/dmesg\_20241025.log
\# 后续可通过该文件分析历史硬件报错
cat /var/log/dmesg\_20241025.log | grep "sda"
三、进阶方案:多服务器远程日志收集
当管理 10 台、100 台 Linux 服务器时,逐台登录看日志效率极低 —— 需搭建 “远程日志收集系统”,让所有服务器的日志统一发送到 “日志服务器”,实现 “集中查看、快速检索”。
这里推荐用rsyslog
(Linux 默认预装,配置简单)搭建基础远程日志系统,适合中小规模服务器(大规模可用 ELK 栈,后续进阶)。
1. 步骤 1:配置 “日志服务器”(接收日志)
假设日志服务器 IP 为192.168.1.100
,负责接收其他服务器的日志:
\# 1. 编辑rsyslog配置文件
sudo vim /etc/rsyslog.conf
\# 2. 开启UDP/TCP接收模块(取消以下两行注释,任选一种协议,UDP简单,TCP可靠)
module(load="imudp") # 加载UDP接收模块
input(type="imudp" port="514") # 监听514端口(rsyslog默认端口)
\# module(load="imtcp") # 加载TCP接收模块
\# input(type="imtcp" port="514")
\# 3. 配置日志存储规则(所有远程日志保存到/var/log/remote/目录,按服务器IP分类)
\$template RemoteLog,"/var/log/remote/%FROMHOST-IP%/%PROGRAMNAME%.log" # 模板:按IP和程序名存日志
\*.\* ?RemoteLog # 所有级别(\*.\*)的日志,按模板存储
\# 4. 重启rsyslog服务
sudo systemctl restart rsyslog
\# 5. 开放防火墙端口(允许514端口的UDP/TCP流量)
sudo ufw allow 514/udp # Ubuntu
\# sudo firewall-cmd --add-port=514/udp --permanent && sudo firewall-cmd --reload # CentOS
2. 步骤 2:配置 “客户端服务器”(发送日志)
假设客户端服务器 IP 为192.168.1.101
,需将日志发送到192.168.1.100
:
\# 1. 编辑rsyslog配置文件
sudo vim /etc/rsyslog.conf
\# 2. 添加日志发送规则(所有日志通过UDP发送到日志服务器)
\*.\* @192.168.1.100:514 # @表示UDP,@@表示TCP,端口514
\# 若只发送Nginx日志,可更精准:
\# :programname,isequal,"nginx" @192.168.1.100:514
\# 3. 重启rsyslog服务
sudo systemctl restart rsyslog
3. 步骤 3:验证远程日志收集
\# 1. 在客户端服务器生成测试日志(触发日志发送)
logger "test remote log from 192.168.1.101" # logger命令用于生成自定义日志
\# 2. 在日志服务器查看是否收到日志
ls -l /var/log/remote/192.168.1.101/ # 会看到logger.log文件
cat /var/log/remote/192.168.1.101/logger.log # 能看到测试日志内容,说明配置成功
进阶:大规模场景推荐 ELK 栈
若服务器超过 50 台,rsyslog
的检索能力不足,可搭建 ELK 栈(Elasticsearch+Logstash+Kibana):
-
Logstash:收集日志并格式化;
-
Elasticsearch:存储日志并支持全文检索;
-
Kibana:可视化日志(图表、仪表盘),支持按 IP、时间、关键词快速筛选。
四、避坑指南:3 个日志排查常见误区
1. 误区 1:只看 systemd 日志,忽略应用专属日志
表现:Nginx 启动失败,只看journalctl -u nginx
,没看/var/log/nginx/error.log
,错过配置文件语法错误的详细提示。
正确做法:systemd 日志看 “服务状态”,应用专属日志看 “具体错误细节”,两者结合才能快速定位。
2. 误区 2:logrotate 配置后不测试,日志撑爆磁盘
表现:配置 Nginx 日志轮转后,未手动测试,实际轮转时因 “权限不足” 失败,导致access.log
涨到 100GB 占满磁盘。
正确做法:配置后必执行sudo logrotate -d /etc/logrotate.d/nginx
(模拟测试)和sudo logrotate -f ...
(强制执行),验证轮转是否正常生成归档日志。
3. 误区 3:远程日志收集不开放防火墙端口
表现:客户端配置好 rsyslog,日志服务器却收不到日志,排查半天发现防火墙未开放 514 端口。
正确做法:配置远程日志时,先在日志服务器执行sudo netstat -tuln | grep 514
,确认 rsyslog 已监听 514 端口,再开放防火墙端口(UDP/TCP)。
总结:5 分钟日志排查核心流程
-
服务故障:
1 分钟
journalctl -u 服务名 -p err
看系统日志 → 2 分钟tail -n 20 应用日志路径
看细节 → 2 分钟验证解决; -
硬件故障:
1 分钟
dmesg | grep -i error
找报错 → 3 分钟解读日志定位硬件(磁盘 / 内存) → 1 分钟保存日志并处理; -
多服务器:
用
rsyslog
搭建远程收集,中小规模够用;大规模用 ELK 栈,实现可视化检索。
掌握这套流程,你就能从 “日志小白” 变成 “故障排查高手”,大部分 Linux 故障都能在 5 分钟内定位,不再因 “找不到原因” 而焦虑。