43 - 系统错误排查与日志分析
系统出了问题不可怕,可怕的是不知道如何找到问题所在。本章系统地讲解 Linux 错误排查方法论,从 journalctl 深度使用到启动修复,从硬件诊断到进程调试,帮助你建立从发现问题到定位根源再到实施修复的完整排查能力。
43.1 系统排查方法论
排查问题应遵循系统性的思维流程:
1. 复现问题 → 明确问题的触发条件和场景
2. 缩小范围 → 确定问题所属层级(硬件→内核→驱动→服务→应用)
3. 查看日志 → journalctl、dmesg、应用日志
4. 提出假设 → 基于已有信息推测根因
5. 尝试修复 → 从最小改动开始,一次只改一个变量
6. 验证结果 → 确认问题已解决且无副作用
7. 记录方案 → 供日后参考和团队共享
排查核心原则
| 原则 | 说明 |
|---|---|
| 最近改了什么 | 问题通常出现在最近的变更之后 |
| 二分法 | 逐步缩小范围,排除无关变量 |
| 最小复现 | 用最简单的方式复现问题 |
| 先看日志 | 日志是最重要的第一手线索 |
| 一次只改一个 | 避免同时修改多个变量导致无法归因 |
速查命令表
| 场景 | 命令 |
|---|---|
| 总览 | uptime, who, last, dmesg -H |
| 系统启动日志 | journalctl -b |
| 上次启动日志 | journalctl -b -1 |
| 只看错误 | journalctl -b -p err |
| 服务状态 | systemctl status service |
| 失败服务 | systemctl --failed |
| 磁盘空间 | df -h, du -sh /path |
| 内存使用 | free -h, vmstat 1 |
| CPU 负载 | top, htop, uptime |
| 开放端口 | ss -tulnp |
| 文件占用 | lsof /path/to/file |
| 启动耗时 | systemd-analyze blame |
43.2 journalctl 深入使用
journalctl 是 systemd 的日志查询工具,是排查问题的第一利器。
基本过滤
# 查看本次启动的所有日志
journalctl -b
# 查看上次启动的日志(排查"为什么上次关机/重启失败")
journalctl -b -1
# 列出所有可查询的启动记录
journalctl --list-boots
# 实时跟踪日志(类似 tail -f)
journalctl -f
# 按时间过滤
journalctl --since "2024-07-24 10:00:00"
journalctl --since "2024-07-24" --until "2024-07-25"
journalctl --since "1 hour ago"
journalctl --since "30 min ago"
journalctl --since yesterday按服务和优先级过滤
# 查看特定服务的日志
journalctl -u nginx
journalctl -u sshd
# 多服务合并查看
journalctl -u nginx -u php-fpm
# 实时跟踪服务日志
journalctl -u docker -f
# 按日志优先级过滤
# emerg(0) > alert(1) > crit(2) > err(3) > warning(4) > notice(5) > info(6) > debug(7)
journalctl -b -p err # 错误及以上
journalctl -b -p warning # 警告及以上
journalctl -b -p warning..err # 警告到错误范围
# 按 PID 过滤
journalctl _PID=1234
# 按 UID 过滤
journalctl _UID=1000
# 按可执行文件过滤
journalctl /usr/bin/python内核日志
# 只看内核消息(等同于 dmesg)
journalctl -k
journalctl -k -b # 本次启动的内核日志
journalctl --dmesg日志持久化配置
默认情况下,journald 日志存储在内存(/run/log/journal/)中,重启后丢失。持久化配置:
# 创建持久化目录
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
# 重启 systemd-journald 生效编辑 /etc/systemd/journald.conf:
[Journal]
Storage=persistent
Compress=yes
SystemMaxUse=500M
SystemMaxFileSize=50M
MaxRetentionSec=1month# 查看日志占用空间
journalctl --disk-usage
# 清理日志
sudo journalctl --vacuum-time=2d # 仅保留最近 2 天
sudo journalctl --vacuum-size=500M # 限制总大小 500M
sudo journalctl --vacuum-files=5 # 保留最近 5 个日志文件高级输出格式
# JSON 格式
journalctl -o json
journalctl -o json-pretty
# 只输出消息体
journalctl -o cat
# 配合 jq 精确提取
journalctl -o json | jq 'select(.PRIORITY == "3") | .MESSAGE'
# 导出日志
journalctl -b > /tmp/boot_log.txt
journalctl -u nginx -o json > /tmp/nginx_log.json43.3 dmesg 内核日志分析
dmesg 显示内核环形缓冲区的消息,主要包含硬件检测、驱动加载、内核 Oops/Panic 等信息。
# 查看内核日志
dmesg -H # 人类可读格式(时间戳 + 颜色)
dmesg -T # 显示可读时间戳
dmesg -w # 实时跟踪(类似 tail -f)
# 按级别过滤
dmesg -l err
dmesg -l err,warn
# 按设施过滤
dmesg -f kern # 内核消息
dmesg -f daemon # 守护进程消息
# 常用关键词搜索
dmesg | grep -i error
dmesg | grep -i fail
dmesg | grep -i "out of memory"
dmesg | grep -i firmware
dmesg | grep -iE "(sda|nvme|ata)" # 存储设备
dmesg | grep -iE "(drm|gpu|i915|amdgpu|nvidia)" # GPU
dmesg | grep -i usb43.4 启动故障排查
启动卡住 / Kernel Panic
# 查看上次启动的紧急级别日志
journalctl -b -1 -p emerg
journalctl -b -1 -p crit
# 常见的启动失败原因和应对:
# 1. 内核模块不兼容 → 安装并使用 LTS 内核作为后备
# 2. 文件系统损坏 → 从 Live USB 启动后执行 fsck
# 3. initramfs 缺少模块 → 重建 initramfs
# 4. fstab 配置错误 → 进入救援模式修复
# 启动时在 GRUB 中添加调试参数(按 e 编辑):
# 移除 quiet,添加 systemd.log_level=debug救援模式与紧急模式
# 救援模式(基本服务已启动,文件系统读写挂载)
# 在 GRUB 菜单按 e,在 linux 行末尾添加:
# systemd.unit=rescue.target
# 紧急模式(最小化,根文件系统只读)
# 添加:systemd.unit=emergency.target
# 在紧急模式下修复:
mount -o remount,rw / # 重新挂载为读写
mount -a # 挂载 fstab 中所有分区
# 编辑配置修复问题后:
exit # 继续启动无法进入图形界面
# 切换到 TTY(Ctrl+Alt+F2 ~ F6)
# 检查显示管理器状态
systemctl status gdm # GNOME
systemctl status sddm # KDE
systemctl status lightdm # LightDM
# 查看 Xorg 日志
cat /var/log/Xorg.0.log | grep "(EE)" # EE = 错误
# 常见原因:
# 1. 显卡驱动问题 → 重新安装驱动
# 2. 配置冲突 → 移除 /etc/X11/xorg.conf 配置文件
# 3. 权限问题 → rm ~/.Xauthority 并重新登录文件系统问题
# fstab 配置错误导致无法挂载
# 在紧急模式下修复:
mount -o remount,rw /
nano /etc/fstab
# 检查 UUID 是否正确:blkid
# 非关键分区添加 nofail 选项防止阻止启动
# 文件系统损坏
sudo umount /dev/sda1 # 先卸载
sudo e2fsck -f /dev/sda1 # ext4
sudo xfs_repair /dev/sda1 # XFS
sudo btrfs check /dev/sda1 # Btrfs使用 Live USB 修复
# 1. 从安装介质启动
# 2. 挂载系统分区
mount /dev/sda2 /mnt # 根分区
mount /dev/sda1 /mnt/boot # 启动分区
mount /dev/sda1 /mnt/boot/efi # ESP(如分开)
# 3. chroot 进入
mount -t proc /proc /mnt/proc
mount -t sysfs /sys /mnt/sys
mount --rbind /dev /mnt/dev
chroot /mnt /bin/bash
# 4. 在 chroot 中修复
# 重装内核
apt reinstall linux-image-$(uname -r) # Debian/Ubuntu
dnf reinstall kernel # Fedora
# 重建 initramfs
update-initramfs -u -k all # Debian/Ubuntu
dracut --force --kver $(uname -r) # Fedora/RHEL
mkinitcpio -P # Arch
# 修复 GRUB
grub-install --target=x86_64-efi --efi-directory=/boot/efi
grub-mkconfig -o /boot/grub/grub.cfg
# 5. 退出并重启
exit
umount -R /mnt
reboot43.5 服务故障排查
# 查看失败的服务
systemctl --failed
# 查看特定服务的详细状态
systemctl status nginx
# 关键信息:Load state, Active state, Exit code
# 查看服务的完整日志
journalctl -u nginx --no-pager
# 查看服务启动依赖链
systemctl list-dependencies nginx
systemctl list-dependencies --reverse nginx
# 查看服务的启动耗时
systemd-analyze blame | grep nginx
# 重置失败状态(清除红点标记)
sudo systemctl reset-failed nginx
# 查看服务文件
systemctl cat nginx
# 编辑服务文件的 override
sudo systemctl edit nginx43.6 硬件故障排查
磁盘 SMART 检测
# 安装
sudo apt install smartmontools
# 快速健康检查
sudo smartctl -H /dev/sda
# 完整 SMART 信息
sudo smartctl -a /dev/sda
# 关键 SMART 属性
# ID 5: Reallocated Sector Count > 0 需警惕
# ID 187: Reported Uncorrectable > 0 需警惕
# ID 197: Current Pending Sector > 0 需关注
# ID 198: Offline Uncorrectable > 0 需关注
# 短时自检(约 2 分钟)
sudo smartctl -t short /dev/sda
# 长时自检(可能数小时)
sudo smartctl -t long /dev/sda
# 查看自检结果
sudo smartctl -l selftest /dev/sda
# NVMe SMART
sudo smartctl -a /dev/nvme0
sudo nvme smart-log /dev/nvme0内存测试
# 使用 memtester(在线测试)
sudo apt install memtester
sudo memtester 1024M 2 # 测试 1GB 内存,2 次
# 使用 memtest86+(离线测试,更彻底)
# 通过发行版包或 Live USB 启动CPU 温度与性能
# 安装传感器工具
sudo apt install lm-sensors
sudo sensors-detect
sensors
# 持续监控
watch -n 1 sensors
# CPU 频率
cat /proc/cpuinfo | grep "MHz" | head
# 压力测试
sudo apt install stress
stress --cpu $(nproc) --timeout 60 &
watch -n 1 sensors43.7 网络故障排查
# 基本连通性
ping -c 4 8.8.8.8 # 测试网络可达性
ping -c 4 google.com # 测试 DNS 是否正常
# DNS 诊断
nslookup google.com
dig google.com
resolvectl status # systemd-resolved 状态
# 网络接口状态
ip addr show
ip link show
# 路由表
ip route show
# 活跃连接和端口
ss -tulnp
ss -t state established
# 端口测试
nc -zv server.com 443 # TCP 端口是否开放
# 路由追踪
traceroute google.com
mtr google.com # 可视化 + 丢包统计
# 抓包分析
sudo tcpdump -i eth0 -n port 80
sudo tcpdump -i any -w /tmp/capture.pcap
# NetworkManager 日志
journalctl -u NetworkManager -f常见网络问题速查
| 症状 | 可能原因 | 排查命令 |
|---|---|---|
| 完全无网络 | 网卡未启用 | ip link show, rfkill list |
| 能 ping IP 不能 ping 域名 | DNS 配置错误 | resolvectl status, cat /etc/resolv.conf |
| 连接被拒绝 | 防火墙 / 服务未监听 | sudo iptables -L -n, ss -tulnp |
| 间歇性断连 | 无线网卡电源管理 | iw dev wlan0 get power_save |
| 速度慢 | 链路协商问题 | ethtool eth0 | grep Speed |
43.8 包管理故障
通用问题
# 数据库锁定(确认无其他包管理进程后删除锁文件)
# Debian/Ubuntu:
sudo rm /var/lib/dpkg/lock-frontend
sudo rm /var/lib/apt/lists/lock
# Fedora:
sudo rm /var/lib/rpm/.rpm.lock
# Arch:
sudo rm /var/lib/pacman/db.lck
# 依赖问题
# Debian/Ubuntu: 修复损坏的依赖
sudo apt --fix-broken install
# Fedora:
sudo dnf distro-sync
# Arch: 部分升级导致的库不匹配
sudo pacman -Syu # 完成完整升级
# 清理缓存
# Debian/Ubuntu: sudo apt clean
# Fedora: sudo dnf clean all
# Arch: sudo pacman -Sc
# 验证已安装包的文件完整性
# Debian/Ubuntu: dpkg --verify
# Fedora: rpm -Va
# Arch: paccheck(需安装 pacutils)时间不同步导致签名验证失败
# 同步时间
sudo timedatectl set-ntp true
sudo hwclock --systohc
# 检查时间状态
timedatectl status43.9 strace 与 ltrace 调试
strace:系统调用跟踪
# 安装
sudo apt install strace # Debian/Ubuntu
sudo dnf install strace # Fedora
# 跟踪程序执行的系统调用
strace ls
# 跟踪正在运行的进程
sudo strace -p 1234
# 只跟踪特定类别的系统调用
strace -e trace=open,read,write ls # 文件 I/O
strace -e trace=network curl example.com # 网络相关
strace -e trace=file ls # 文件操作
strace -e trace=%process command # 进程管理
# 统计系统调用次数和耗时
strace -c ls
# 显示时间信息
strace -tt ls # 微秒级时间戳
strace -T ls # 每个调用的耗时(尖括号内)
# 跟踪子进程
strace -f bash -c 'ls | grep txt'
# 查找程序打开的配置文件
strace -e trace=openat program 2>&1 | grep -v ENOENT
# 定位程序启动缓慢的原因
strace -T -e trace=file program 2>&1 | sort -t= -k2 -rn | head
# 查看程序为什么失败(关注 Permission Denied)
strace -e trace=openat program 2>&1 | grep "ENOENT\|EACCES"ltrace:库函数调用跟踪
# 安装
sudo apt install ltrace
ltrace ls
ltrace -e malloc+free ls # 只跟踪内存分配
ltrace -c ls # 统计库调用
sudo ltrace -p 1234 # 跟踪运行中进程43.10 coredump 分析
当程序崩溃时,systemd-coredump 自动收集核心转储文件。
# 列出所有 coredump
coredumpctl list
# 查看最近的 coredump 详情
coredumpctl info
# 查看特定程序的 coredump
coredumpctl info firefox
# 使用 GDB 分析
coredumpctl gdb firefox
# (gdb) bt # 查看堆栈回溯
# (gdb) bt full # 完整堆栈(含局部变量)
# (gdb) info threads # 线程信息
# (gdb) thread apply all bt # 所有线程堆栈
# 导出 coredump 文件
coredumpctl dump firefox -o /tmp/firefox.core
# 配置 coredump(/etc/systemd/coredump.conf)
# [Coredump]
# Storage=external
# Compress=yes
# ProcessSizeMax=2G
# MaxUse=1G43.11 lsof 文件占用排查
# 安装
sudo apt install lsof
# 列出所有打开文件(输出通常极长)
lsof
# 特定用户打开的文件
lsof -u username
# 特定进程打开的文件
lsof -p 1234
# 哪些进程打开了特定文件
lsof /path/to/file
# 哪些进程在使用特定端口
lsof -i :80
lsof -i :443
lsof -i TCP
lsof -i TCP@192.168.1.1
# 目录下被打开的所有文件
lsof +D /var/log
# 已删除但尚未释放的文件(占用磁盘空间)
lsof | grep deletedlsof 最常见的实用场景:umount 失败时找出哪些进程仍在访问挂载点下的文件。
43.12 日志文件位置速查
| 日志位置 | 内容 |
|---|---|
journalctl 或其持久化目录 | 系统日志(systemd 系统) |
/var/log/syslog / /var/log/messages | 传统 syslog 日志 |
/var/log/auth.log / /var/log/secure | 认证和安全日志 |
/var/log/kern.log | 内核日志 |
/var/log/boot.log | 系统启动记录 |
/var/log/dpkg.log / /var/log/dnf.log | 包管理日志 |
/var/log/Xorg.0.log | Xorg 显示服务日志 |
~/.xsession-errors | 用户会话错误 |
/var/log/apache2/ / /var/log/nginx/ | Web 服务器日志 |
43.13 搜索资源的技巧
当遇到未知错误时,有效地搜索解决方案至关重要:
1. 提取关键错误信息(不是 "程序无法启动",而是精确的错误消息)
2. 搜索时用引号包裹精确错误:
"error while loading shared libraries: libssl.so.1.1"
3. 限定搜索范围:
site:wiki.archlinux.org touchpad not working
site:wiki.debian.org nvidia driver
4. 查看文档的 Troubleshooting 章节
5. 关注帖子的 [SOLVED] 标记
6. man 和 --help 是第一手文档
交叉链接:系统性能深入分析参考 39-系统调优与性能分析。服务管理参考 11-systemd服务管理。引导流程问题参考 40-引导流程与GRUB。备份与恢复策略参考 17-备份与恢复。