深夜三点,手机突然震动,监控报警红得刺眼:核心业务服务器不可达。心跳瞬间漏拍,手心冒汗,屏幕上的SSH连接图标一直在转圈。别急,深呼吸。这种情况,几乎每个运维、每个后端开发者都经历过。服务器宕机、启动失败、服务假死,焦虑解决不了问题,但系统化的排查思路可以。
作为一位在Linux坑里摸爬滚打多年的“老兵”,我见过太多因为慌乱而误操作导致情况恶化的案例。今天,我就手把手带你梳理一套针对 AlmaLinux(以及其上游 RHEL、Rocky Linux 等)系统的故障排查实战指南。这套方法不玩虚的,全是能救命的干货,逻辑清晰,代码可复现,哪怕你是刚入行的小白,也能跟着步骤一步步把服务器“救活”。
一、 第一时间:保持冷静,先诊断,再动手
很多新手一看到服务器挂了,第一反应是狂按重启键,或者SSH连上去就开始瞎装软件、改配置。停!在原因不明的情况下,任何写入操作都可能破坏现场,甚至彻底丢失数据。
1.1 确认故障现象:是真的挂了,还是只是慢?
在网络环境复杂时,有时候不是服务器挂了,而是网络抖动、DNS解析失败,或者你被防火墙挡住了。
先做几个最基础的连通性测试:
# 1. 检查网络连通性(如果能从本地访问)
ping -c 4 <服务器IP>
# 2. 检查SSH端口是否开放
nc -zv <服务器IP> 22
# 或者用 telnet 试试
telnet <服务器IP> 22
# 3. 如果SSH超时,尝试HTTP/HTTPS端口,看Web服务是否在响应
curl -I http://<服务器IP>
curl -I https://<服务器IP>
如果 ping 不通,nc 也连不上,说明服务器可能真的宕机了,或者网络层出了问题。如果 SSH 能连上但很卡,那可能是负载过高,这时候重启往往会让情况更糟,应该先检查资源占用。
1.2 利用带外管理(Out-of-Band Management)
如果你的服务器是物理机,或者有云平台(如阿里云、AWS、腾讯云、华为云等)提供的 VNC / 控制台 / KVM over IP 功能,请立即使用它!
为什么?因为SSH依赖网络栈,当网络栈崩溃或内核panic时,SSH可能完全无响应。但VNC是直接连接显示输出的,你能看到屏幕上的报错信息——比如内核崩溃的 kernel panic 日志、grub引导界面、或者单用户模式的提示。这是排查故障的金钥匙。
如果没有VNC,只能靠SSH了,那接下来我们进入核心排查阶段。
二、 启动失败?GRUB和Bootloader是你的第一战场
服务器重启后起不来,或者卡在启动界面,这是最常见的问题之一。AlmaLinux 使用 GRUB2 作为引导加载器。
2.1 常见启动故障现象
- 黑屏,只有光标闪烁:GRUB没找到内核。
- 卡在
Dracut提示符:无法挂载根文件系统。 - 进入
emergency mode或rescue mode:文件系统错误,需要手动修复。 - 循环重启:系统启动中途崩溃,又重启。
2.2 排查步骤
情况一:卡在 dracut:# 提示符
这通常意味着 initramfs 找不到根文件系统。最常见的原因是:
- 磁盘UUID变化(比如换了硬盘、RAID配置变更)。
grub.conf或grub.cfg里的 root 参数错误。- 驱动缺失(比如LVM、mdadm、iSCSI驱动没打进initramfs)。
解决方法:
在 dracut:# 提示符下,输入以下命令检查磁盘和分区:
# 查看识别到的块设备
lsblk
# 查看磁盘UUID,确认根分区是否正确
blkid
# 如果用的是LVM,激活卷组
lvm vgchange -ay
# 手动挂载根分区,测试是否能读
mkdir /testroot
mount /dev/mapper/<vg-name>-<lv-name> /testroot
ls /testroot
如果手动挂载成功,说明硬件和驱动没问题,可能是GRUB配置错误。退出挂载,重启:
exit
情况二:卡在GRUB菜单
如果服务器卡在GRUB选择界面,选择 Advanced options for AlmaLinux,然后选择一个 旧的内核版本 启动。这能帮你判断是不是最新内核有问题。
如果旧内核能启动,进入系统后,你需要检查并修复最新内核:
# 查看当前运行内核
uname -r
# 查看已安装的内核
rpm -q kernel
# 或
dnf list installed kernel
# 重新生成grub配置(假设你是BIOS引导)
grub2-mkconfig -o /boot/grub2/grub.cfg
# 如果是UEFI引导:
grub2-mkconfig -o /boot/efi/EFI/alma/grub.cfg
# 重新生成initramfs(针对最新内核)
dracut -f --kver $(uname -r)
情况三:进入emergency mode
这通常是因为 /etc/fstab 里的某个文件系统挂载失败,导致系统无法完成启动。
在emergency mode下,你需要:
# 以只读方式重新挂载根文件系统(默认可能是只读的)
mount -o remount,rw /
# 检查fstab
cat /etc/fstab
# 查看哪个挂载点失败了(看启动日志)
journalctl -xb | grep -i fail
# 如果是某个分区UUID错误,编辑fstab
vi /etc/fstab
# 修改错误的UUID,或者注释掉暂时不需要的挂载项
# 修复文件系统(如果是ext4/xfs)
# 注意:只对其他分区操作,不要对根分区在线修复
fsck -y /dev/sdb1
# 修复后重启
reboot
三、 系统能启动,但服务异常:日志是侦探的放大镜
服务器能进系统,但业务跑不起来,或者某个关键服务(如Nginx、MySQL、K8s)挂了。这时候,日志是你最忠实的朋友。AlmaLinux使用 systemd 管理服务,日志通过 journalctl 统一管理。
3.1 核心命令:journalctl
不要再用 tail -f /var/log/messages 了,那是老黄历。journalctl 功能强大得多。
# 查看系统启动以来的所有日志(分页浏览,按q退出)
journalctl
# 查看本次启动以来的日志
journalctl -b
# 查看上一次启动的日志(如果系统重启过)
journalctl -b -1
# 查看某个服务的日志(比如nginx)
journalctl -u nginx --since "10 minutes ago"
# 按级别筛选(只看不好)
journalctl -p err -b
# 实时跟踪日志(类似tail -f)
journalctl -f -u sshd
# 查看内核日志
journalctl -k
# 导出日志为可读格式
journalctl -b > /tmp/boot.log
3.2 常见服务故障排查
场景A:Web服务(Nginx/Apache)无法启动或返回502/504
步骤1:检查服务状态
systemctl status nginx
# 看红色报错信息,通常会指向配置文件错误或端口占用
步骤2:测试配置文件语法
nginx -t
# 输出 syntax is ok 和 test is successful 才是对的
步骤3:检查端口占用
ss -tlnp | grep :80
# 或者
netstat -tlnp | grep :80
如果端口被占用,可能是之前进程没杀干净,或者另一个服务占了80端口。用 kill 或 systemctl stop 干掉冲突进程。
步骤4:检查后端服务(如果是反向代理)
如果Nginx是反向代理到后端(如PHP-FPM、Node.js、Go服务),检查后端服务是否存活:
systemctl status php-fpm
# 检查后端服务的日志
journalctl -u php-fpm -n 50
场景B:数据库(MySQL/MariaDB/PostgreSQL)连接失败
步骤1:检查数据库服务状态
systemctl status mariadb
# 或
systemctl status mysqld
步骤2:查看数据库错误日志
数据库的错误日志通常在 /var/log/mariadb/mariadb.log 或 /var/log/mysql/error.log,也可以用journalctl:
journalctl -u mariadb -n 100 --no-pager
常见原因:
- 磁盘满了,数据库写不进去,直接崩了。检查磁盘:
df -h - 配置文件错误(如
innodb_buffer_pool_size设置过大,内存不足) - 数据文件损坏
步骤3:检查连接数和权限
# 登录数据库查看当前连接
mysql -u root -p -e "SHOW PROCESSLIST;"
# 检查数据库账号密码是否过期或被锁
mysql -u root -p -e "SELECT User, Host, plugin, authentication_string FROM mysql.user;"
场景C:系统负载高,CPU/内存飙升
# 查看整体负载
top
# 或更友好的 htop(如果已安装)
htop
# 查看内存和Swap使用情况
free -h
# 查看磁盘IO压力
iostat -x 1 5
# 查看哪个进程占用CPU最高
ps aux --sort=-%cpu | head -10
# 查看哪个进程占用内存最高
ps aux --sort=-%mem | head -10
案例分析:
假设你发现一个 java 进程占了90%的CPU。你需要深入查看:
# 查看该Java进程的线程栈,定位卡死的代码
top -H -p <PID>
# 或者用 jstack 导出线程栈
jstack <PID> > /tmp/thread_dump.txt
通过线程栈,你可以看到Java程序卡在哪个类、哪一行代码,从而定位是死循环、锁竞争还是其他问题。
四、 文件系统与磁盘问题:系统的基石
磁盘问题是最隐蔽也最致命的故障源。
4.1 磁盘空间满了
这是新手最容易踩的坑。当根分区满时,系统会表现得很怪异:服务无法启动、日志写不进去、数据库崩溃。
# 查看磁盘使用情况,找到占用最大的目录
df -h
du -sh /var/log/* | sort -hr | head -10
du -sh /var/lib/* | sort -hr | head -10
常见“吞”磁盘的大户:
/var/log:日志文件未轮转,或者某个服务疯狂打日志。/var/lib/docker:Docker镜像和容器占用。/tmp:临时文件未清理。
清理示例:
# 清理journal日志(保留最近7天)
journalctl --vacuum-time=7d
# 清理Docker无用资源
docker system prune -a
# 清空某个过大的日志文件(注意不要rm,要echo空覆盖,否则进程占用不释放空间)
echo "" > /var/log/large.log
4.2 磁盘inode用尽
有时候磁盘空间没满,但无法创建文件,报错 No space left on device。这可能是因为小文件太多,inode用完了。
# 查看inode使用情况
df -i
# 找出哪个目录小文件最多
for dir in /var/log /tmp /home/*; do echo $dir; find $dir -type f | wc -l; done
4.3 文件系统损坏
如果服务器非正常关机(断电、强制重启),文件系统可能损坏。
# 检查文件系统(必须在卸载状态下,或只读挂载)
# 如果是根分区,需要进入rescue模式
fsck -n /dev/sda1 # -n 表示只检查不修复,先看问题
fsck -y /dev/sda1 # 确认问题后,-y 自动修复
注意: 生产环境的根分区修复风险极高,建议先备份数据,或在维护窗口操作。
五、 网络故障:看不见的绊脚石
服务器之间无法通信,或者外网访问不了内网服务。
5.1 基础网络诊断
# 查看网络接口配置
ip addr show
# 或
ifconfig -a
# 查看路由表
ip route show
# 或
route -n
# 测试DNS解析
nslookup google.com
dig google.com
# 测试网络连通性(替代ping,更详细)
traceroute <目标IP>
mtr <目标IP> # 结合ping和traceroute,实时显示丢包率
5.2 防火墙问题(firewalld/iptables)
AlmaLinux默认使用 firewalld。很多时候,服务启动了,但外网访问不了,99%是防火墙在拦。
# 查看防火墙状态
firewall-cmd --state
# 查看当前区域的规则
firewall-cmd --list-all
# 临时打开80端口(HTTP)
firewall-cmd --add-port=80/tcp --permanent
firewall-cmd --reload
# 如果是旧版iptables规则
iptables -L -n -v
快速测试: 临时关闭防火墙,看问题是否解决。如果关闭后正常,那就是防火墙规则问题。
systemctl stop firewalld # 测试用,生产环境慎用
systemctl start firewalld # 测完后记得开回来
5.3 SELinux:红色的拦路虎
SELinux是RHEL系特有的安全模块,经常背锅。当服务正常运行但访问被拒时,第一反应应该是 SELinux。
# 查看SELinux状态
getenforce
# 返回 Enforcing 表示强制模式,Permissive 表示只警告不拦截
# 查看最近的SELinux拒绝日志
ausearch -m avc -ts recent
# 或
journalctl -xe | grep -i selinux | grep -i denied
# 临时设置为Permissive模式(不重启生效)
setenforce 0
# 如果问题解决,说明是SELinux策略问题。需要调整上下文或策略,而不是永久关闭SELinux。
# 永久修改需要在 /etc/selinux/config 中设置
举个例子: 你部署了一个Web应用,代码在 /var/www/html,但Nginx报403 Forbidden。检查SELinux日志:
ausearch -m avc -ts recent | grep nginx
如果发现是SELinux拒绝,你可以用 audit2allow 生成策略,或者调整文件上下文:
# 查看当前上下文
ls -Z /var/www/html
# 恢复默认上下文
restorecon -Rv /var/www/html
六、 内核panic:系统彻底崩溃
如果服务器直接死机,屏幕黑屏,SSH完全无响应,那很可能是内核崩溃(Kernel Panic)。
6.1 如何获取崩溃现场?
- 查看串口日志:如果是物理机且有串口控制台,崩溃信息会输出到串口。
- 查看crash dump:如果之前配置了
kdump,系统崩溃后会生成/var/crash/<日期>/vmcore文件。你可以用crash工具分析这个文件,定位是哪个模块或函数导致的崩溃。 - 查看前一次启动的日志:
journalctl -b -1 -p emerg
# 查看上一次启动中的紧急错误
6.2 预防内核panic
- 保持内核和关键驱动更新。
- 避免加载未签名的、不稳定的内核模块。
- 配置kdump,确保崩溃时能保留现场。
# 检查kdump服务状态
systemctl status kdump
# 如果未启用,启用它
systemctl enable --now kdump
七、 实战案例:一次真实的故障排查全过程
为了让你更有体感,我给你讲一个我亲身经历的案例。
背景: 一台部署了Java微服务的AlmaLinux 8服务器,突然所有服务无法访问,SSH也连不上。监控显示CPU使用率突然降到0%,然后服务器无响应。
排查过程:
连接VNC控制台:看到屏幕卡在启动界面,显示
Kernel panic - not syncing: Attempted to kill init!。分析:这说明系统启动了,但在执行init进程(systemd)时崩溃了。常见原因是
/sbin/init损坏,或者根文件系统只读模式出错。尝试进入Rescue Mode:在GRUB菜单选择
Rescue a AlmaLinux system。挂载根文件系统:
chroot /mnt/sysimage检查init进程:
ls -l /sbin/init # 发现是一个损坏的链接,指向不存在的文件修复:
# 重新安装systemd包 dnf reinstall systemd -y # 或者手动创建链接 ln -sf /usr/lib/systemd/systemd /sbin/init重启:
reboot,系统正常启动。
教训: 这次故障是因为有人误删了 /sbin/init,或者系统更新中断导致文件损坏。定期备份关键系统文件,使用yum/dnf时避免强制中断
