Ubuntu 系统系列 | 第 28 天:故障排查实战——系统救援、启动修复、日志分析、崩溃排查

第 28/30 天

引言

服务器宕机了怎么办?系统无法启动了?某个服务莫名其妙挂了?——作为 Ubuntu 管理员,故障排查是必备的核心技能。即使配置再完善,系统也难免会遇到意外情况:内核崩溃、磁盘故障、配置错误导致服务无法启动、启动引导损坏等。

本周(第 4 周)我们从前 22 天的安全加固开始,经历了性能调优、虚拟化、容器编排、高可用集群和自动部署。今天,我们来学习故障发生时如何冷静、系统化地定位问题并恢复系统。掌握这些技能,你就能在关键时刻成为团队最信赖的人。

本文将覆盖:应急响应流程、系统救援与启动修复、日志分析技巧、崩溃排查方法,以及常见故障的实战案例。


一、故障排查的核心方法论

1.1 故障排查四步法

无论遇到什么问题,遵循以下步骤可以避免慌乱和遗漏:

步骤 操作 目的
① 收集信息 查看日志、错误信息、系统状态 确定故障范围和影响
② 分析定位 对比正常状态、缩小范围 找出根本原因
③ 制定方案 根据 root cause 确定修复步骤 确保修复有效
④ 实施验证 执行修复、验证恢复、监控稳定 确认问题解决

1.2 诊断工具箱

在排查问题前,先确认手头有哪些工具可用:

# 系统信息收集(无需安装)
uname -a                    # 内核版本
lsb_release -a              # Ubuntu 版本
cat /etc/os-release         # 发行版信息
dmesg | tail -50            # 内核环形缓冲区信息
uptime                      # 运行时间 + 负载
free -h                     # 内存使用
df -h                       # 磁盘使用
mount | grep " / "         # 根分区挂载情况

# 进程信息
ps auxf                     # 进程树
top -bn1                    # 一次性 top 输出
systemctl list-units --failed  # 列出失败的服务

二、系统救援与启动修复

2.1 GRUB 引导修复

场景: 系统启动到 GRUB 提示符或黑屏。这是最常见也最令人恐慌的故障之一。

现象: 开机后显示 grub rescue>error: no such partition

修复方法:

# 第一步:查找 GRUB 所在的正确分区
grub rescue> ls
(hd0) (hd0,msdos1) (hd0,msdos2)

# 第二步:尝试找到 /boot/grub 目录
grub rescue> ls (hd0,msdos1)/boot/grub
# 如果找不到,试其他分区

# 第三步:手动加载 GRUB 模块
grub rescue> set prefix=(hd0,msdos1)/boot/grub
grub rescue> insmod normal
grub rescue> normal

# 进入 GRUB 菜单后,先启动系统
# 然后在系统内修复
sudo update-grub
sudo grub-install /dev/sda

预防措施: 安装 GRUB 到备用分区,保存 GRUB 配置文件备份:

# 备份 GRUB 配置
sudo cp /boot/grub/grub.cfg /boot/grub/grub.cfg.bak
# 检查 GRUB 安装状态
sudo grub-install --recheck /dev/sda

2.2 使用 Live USB 进行系统救援

当系统完全无法启动时,Live USB 是最强大的救援工具。以下是典型救援流程:

# 1. 用 Ubuntu Live USB 启动,选择 "Try Ubuntu"
# 2. 挂载受损系统的根分区
sudo mkdir -p /mnt/rescue
sudo mount /dev/sda2 /mnt/rescue   # 假设根分区是 sda2
sudo mount /dev/sda1 /mnt/rescue/boot  # 如果有独立 boot 分区

# 3. 挂载必要的虚拟文件系统
sudo mount --bind /dev /mnt/rescue/dev
sudo mount --bind /proc /mnt/rescue/proc
sudo mount --bind /sys /mnt/rescue/sys

# 4. chroot 进入受损系统
sudo chroot /mnt/rescue

# 5. 在 chroot 环境中修复
# 例如:修复 GRUB
grub-install /dev/sda
update-grub

# 修复包管理器
dpkg --configure -a
apt-get install -f

# 修复文件系统
fsck /dev/sda2

# 6. 退出 chroot 并重启
exit
sudo umount -R /mnt/rescue
sudo reboot

2.3 恢复模式(Recovery Mode)

Ubuntu 内置了恢复模式,无需 Live USB 即可修复部分问题:

# 启动时按住 Shift(BIOS)或 Esc(UEFI)
# 选择 "Advanced options for Ubuntu" → "recovery mode"

# 恢复菜单提供以下选项:
# - clean: 清理磁盘空间
# - dpkg: 修复损坏的软件包
# - fsck: 检查文件系统
# - grub: 更新 GRUB 引导
# - network: 启用网络连接
# - root: 进入 root shell

实战案例:修复因错误配置导致的启动失败:

# 在 recovery mode 的 root shell 中:
# 假设是 /etc/fstab 配置错误导致无法挂载分区
mount -o remount,rw /
nano /etc/fstab
# 注释掉或修正错误的分区条目
# 如果是因为显卡驱动问题,卸载驱动
apt-get purge nvidia-*
# 重新生成 initramfs
update-initramfs -u

三、日志分析:定位问题的第一把钥匙

3.1 journalctl — systemd 日志系统

现代 Ubuntu 使用 systemd-journald 管理日志,journalctl 是你的首要分析工具:

# 查看所有日志(分页,可搜索)
journalctl

# 查看本次启动的日志
journalctl -b

# 查看上一次启动的日志(内核崩溃后特别有用)
journalctl -b -1

# 实时跟踪日志(类似 tail -f)
journalctl -f

# 按时间范围过滤
journalctl --since "2026-08-06 10:00:00" --until "2026-08-06 11:00:00"

# 按服务过滤
journalctl -u nginx.service
journalctl -u ssh.service

# 按优先级过滤(0=emerg, 1=alert, 2=crit, 3=err, 4=warning, 5=notice, 6=info, 7=debug)
journalctl -p err -b    # 本次启动的错误日志
journalctl -p 3 -b      # 同上(数字形式)

# 输出 JSON 格式便于分析
journalctl -b -o json-pretty

3.2 传统日志文件

日志文件 用途 查看命令
/var/log/syslog 系统全局日志 less /var/log/syslog
/var/log/auth.log 认证日志(SSH、sudo) sudo less /var/log/auth.log
/var/log/kern.log 内核日志 sudo less /var/log/kern.log
/var/log/dmesg 内核环形缓冲 dmesg -T
/var/log/apt/history.log 包管理历史 less /var/log/apt/history.log
/var/log/nginx/error.log Nginx 错误日志 less /var/log/nginx/error.log
/var/log/mysql/error.log MySQL 错误日志 sudo less /var/log/mysql/error.log

3.3 日志分析实战技巧

技巧一:快速定位异常:

# 查看系统最近的错误(排除重复行,按频率排序)
journalctl -p err -b --no-pager | 
  sed 's/^.*[A-Za-z0-9_.-]*[[0-9]*]: //' | 
  sort | uniq -c | sort -rn | head -20

技巧二:分析 SSH 暴力破解尝试:

# 统计失败的 SSH 登录尝试
sudo grep "Failed password" /var/log/auth.log | 
  awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -10

# 统计成功的 SSH 登录
sudo grep "Accepted password" /var/log/auth.log | 
  awk '{print $9, $11}' | sort | uniq -c | sort -rn

技巧三:磁盘空间突然用满的排查:

# 查找大文件
du -sh /* 2>/dev/null | sort -rh | head -10
# 查找被删除但仍在被占用的文件(释放空间需重启进程)
lsof | grep '(deleted)'
# 检查日志文件大小
ls -lhS /var/log/*.log | head -10
# 用 ncdu 交互式分析(需要安装)
sudo apt install ncdu -y && sudo ncdu /

四、崩溃排查:从内核 Panic 到应用崩溃

4.1 内核恐慌(Kernel Panic)

症状: 屏幕显示 Kernel panic - not syncing 并冻结。

排查步骤:

# 1. 查看崩溃时的内核消息
journalctl -b -1 -k --no-pager | grep -i "panic|oops|error|fault"

# 2. 检查 kdump/crashdump(如果配置了)
ls -la /var/crash/
# 使用 crash 工具分析 vmcore
sudo apt install linux-crashdump -y
# 配置后在 /etc/default/kdump-tools 中启用

# 3. 查看硬件错误
dmesg | grep -i "hardware error|mce|memory|ECC"
# 检查内存错误
sudo apt install mcelog -y
sudo mcelog --client

常见原因及解决方案:

原因 特征 解决
内存故障 随机崩溃,MCE 日志 运行 memtest86+ 测试
磁盘故障 I/O 错误,SCSI 错误 检查 smartctl -a /dev/sda
驱动冲突 安装新驱动后崩溃 进入 recovery mode 卸载驱动
内核 bug 特定内核版本稳定触发 降级/升级内核版本

4.2 OOM Killer(内存不足)

症状: 进程被突然杀死,日志中出现 Out of memory: Kill process

# 查看 OOM 记录
journalctl -b | grep -i "oom|out of memory"

# 查看当前内存压力
cat /proc/pressure/memory
# 输出示例:
# some avg10=2.35 avg60=1.20 avg300=0.50 total=1234567
# full avg10=0.89 avg60=0.45 avg300=0.20 total=567890

# 查看进程内存排行
ps aux --sort=-%mem | head -10

# 调整 OOM 评分(让关键进程不被优先杀死)
# 值范围 -1000(禁止杀死)到 1000(优先杀死)
sudo echo -500 > /proc/$(pgrep -f mysqld)/oom_score_adj

永久解决方案: 配置 swap 或调整系统内存策略:

# 创建 swap 文件(如果还没有)
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 在 /etc/fstab 中添加:
# /swapfile none swap sw 0 0

# 调整 vm.swappiness(默认 60,越低越不倾向用 swap)
sudo sysctl -w vm.swappiness=10
# 永久生效
echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.conf

4.3 服务崩溃与自动恢复

# 查看服务崩溃历史
journalctl -u nginx.service -p err --since "1 week ago"

# 配置 systemd 自动重启(编辑 service 单元文件)
sudo systemctl edit nginx.service

添加以下内容:

[Service]
Restart=on-failure
RestartSec=5s
StartLimitIntervalSec=0
StartLimitBurst=10

应用更改:

sudo systemctl daemon-reload
sudo systemctl restart nginx.service

4.4 系统挂起时的手动排查

当系统响应缓慢但不完全崩溃时:

# 1. 检查负载和 CPU 状态
uptime
mpstat -P ALL 1 5    # 需要安装 sysstat

# 2. 查看 I/O 瓶颈
iostat -x 1 5        # 需要安装 sysstat
iotop -o             # 需要安装 iotop(需 root)

# 3. 查看 D 状态进程(不可中断睡眠,通常代表 I/O 问题)
ps aux | grep " D"

# 4. 查看网络连接状态
ss -tupn
netstat -i

# 5. 使用 strace 跟踪进程系统调用
sudo strace -p <PID> -e trace=network,file -c -S time

五、实战案例:完整故障排查演示

案例:Nginx 服务突然停止,网站无法访问

阶段 1 — 收集信息:

# 检查服务状态
systemctl status nginx.service
# 输出:Active: failed (Result: exit-code)

# 查看错误日志
journalctl -u nginx.service -n 50 --no-pager
# 发现:bind() to 0.0.0.0:80 failed (98: Address already in use)

# 确认端口占用
ss -tlnp | grep :80
# 发现另一个进程已经占用了 80 端口

阶段 2 — 分析定位:

# 查看哪个进程占用了端口
ss -tlnp | grep :80
# 输出:LISTEN 0 100 0.0.0.0:80 *:* users:(("apache2",pid=1234,fd=4))

# 确认 Apache 未正确关闭,导致端口冲突
# 根本原因:之前安装过 Apache,未彻底卸载

阶段 3 — 制定方案:

# 方案 A:停止 Apache 并重启 Nginx
sudo systemctl stop apache2
sudo systemctl disable apache2

# 方案 B:或修改 Nginx 监听端口(临时方案)
# 编辑 /etc/nginx/sites-enabled/default,将 listen 80 改为 listen 8080

阶段 4 — 实施验证:

# 执行方案 A
sudo systemctl stop apache2
sudo systemctl restart nginx
systemctl status nginx.service
# 确认 active (running)

# 验证网站访问
curl -s -o /dev/null -w "HTTP %{http_code}" http://localhost/
# 输出:HTTP 200

# 设置 Nginx 在 Apache 后启动(如果 Apache 必须保留)
sudo systemctl edit nginx.service
# 添加:
# [Unit]
# After=network.target apache2.service

六、故障排查预防措施

6.1 建立系统基线

在系统正常运行时记录关键指标,故障时对比:

# 创建系统基线脚本
cat > /usr/local/bin/system-baseline.sh << 'EOF'
#!/bin/bash
DATE=$(date +%Y%m%d)
BASEDIR="/var/log/baseline"
mkdir -p $BASEDIR

# 记录关键指标
dmesg -T > $BASEDIR/dmesg_$DATE.txt
ss -tlnp > $BASEDIR/ports_$DATE.txt
ps auxf > $BASEDIR/processes_$DATE.txt
df -h > $BASEDIR/disk_$DATE.txt
free -h > $BASEDIR/memory_$DATE.txt
cat /proc/cpuinfo | grep "model name" | head -1 > $BASEDIR/cpu_$DATE.txt
uptime > $BASEDIR/uptime_$DATE.txt
journalctl --list-boots > $BASEDIR/boots_$DATE.txt

# 保留最近 30 天
find $BASEDIR -name "*.txt" -mtime +30 -delete
EOF

chmod +x /usr/local/bin/system-baseline.sh

# 添加到每日 cron
(crontab -l 2>/dev/null; echo "0 6 * * * /usr/local/bin/system-baseline.sh") | crontab -

6.2 配置持久化日志

默认情况下 journald 日志存在内存中,重启后丢失:

# 启用持久化日志
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
# 查看当前日志使用量
journalctl --disk-usage

# 限制日志大小(编辑 /etc/systemd/journald.conf)
sudo sed -i 's/#SystemMaxUse=/SystemMaxUse=500M/' /etc/systemd/journald.conf
sudo sed -i 's/#MaxRetentionSec=/MaxRetentionSec=2weeks/' /etc/systemd/journald.conf
sudo systemctl restart systemd-journald

6.3 关键配置备份

# 备份最重要的系统配置
sudo tar czf /root/system-config-backup-$(date +%Y%m%d).tar.gz 
  /etc/fstab 
  /etc/default/grub 
  /etc/netplan/ 
  /etc/ssh/sshd_config 
  /etc/sysctl.conf 
  /etc/nginx/ 
  /etc/systemd/

七、故障排查速查表

问题类型 症状 快速诊断命令 典型修复
无法启动 GRUB rescue> ls (hd0,msdos1) grub-install + update-grub
内核 Panic 屏幕冻结 journalctl -b -1 -k 检查硬件/驱动
磁盘满 写入失败 df -h + du -sh /* 清理日志/扩容
OOM 进程被杀 dmesg | grep oom 加 swap/调优内存
端口冲突 服务启动失败 ss -tlnp 停冲突进程/改端口
DNS 问题 域名解析慢/失败 dig @8.8.8.8 example.com 检查 /etc/resolv.conf
文件系统损坏 I/O 错误 dmesg | grep -i error fsck -y /dev/sdaX
网络不通 ping 失败 ip route + traceroute 检查路由/防火墙
SSH 拒绝 Connection refused ss -tlnp | grep :22 检查 SSH 配置/防火墙
服务死循环 CPU 100% top -c strace -p <PID> 定位

总结

今天你学习了 Ubuntu 故障排查的完整方法论:

  1. 系统救援:GRUB 修复、Live USB 救援、恢复模式三大启动修复手段
  2. 日志分析:journalctl 的 20+ 种用法,传统日志文件定位技巧
  3. 崩溃排查:内核 Panic、OOM Killer、服务崩溃、系统挂起四大场景
  4. 实战案例:Nginx 端口冲突的完整排查四步法
  5. 预防措施:系统基线、持久化日志、配置备份

核心原则: 故障排查不是碰运气,而是系统化的信息收集 → 分析定位 → 制定方案 → 实施验证的过程。记录基线和保存日志是故障排查的”安全网”——没有它们,你就在黑暗中摸索。

下期预告

明天(第 29 天)我们将聊一个轻松但重要的话题:Ubuntu 社区与文档——如何获取帮助、Bug 报告流程、贡献指南。无论你是初学者还是老手,知道在哪里找到答案和如何回馈社区,都是成为 Ubuntu 精通者的重要一步。

系列目录

天数 主题 状态
第 1 天 Ubuntu 简介与版本选择
第 2 天 手把手安装 Ubuntu
第 3 天 GNOME 桌面与软件中心
第 4 天 终端基础与文件系统
第 5 天 用户与权限管理
第 6 天 软件包管理全面对比
第 7 天 文件与文本操作实战
第 8 天 systemd 与 systemctl 完全指南
第 9 天 磁盘与文件系统管理
第 10 天 网络配置与防火墙
第 11 天 进程管理与监控
第 12 天 计划任务与自动化
第 13 天 备份与恢复策略
第 14 天 系统更新与升级管理
第 15 天 SSH 远程管理与安全加固
第 16 天 Web 服务器搭建
第 17 天 数据库服务器部署
第 18 天 Docker 容器化管理
第 19 天 文件共享服务
第 20 天 监控与告警系统
第 21 天 邮件服务器基础
第 22 天 系统安全加固
第 23 天 性能调优与内核参数
第 24 天 虚拟化技术
第 25 天 容器编排入门
第 26 天 高可用与负载均衡
第 27 天 Ubuntu 自动部署
第 28 天 故障排查实战 🟢 今日
第 29 天 Ubuntu 社区与文档
第 30 天 30 天回顾总结
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容