服务器跑着跑着突然卡死,SSH连不上,业务全部中断,这是运维人员最怕遇到的噩梦。面对CentOS系统卡顿甚至完全死机的情况,第一时间的判断和操作往往决定了故障恢复的速度。先别急着强制重启,强制重启虽然简单粗暴,但会丢失系统日志和故障现场,后续排查根本原因就难了。如果服务器还能通过本地终端或带外管理(IPMI、iLO)登录,立即执行 top 命令查看系统负载和CPU占用情况。如果连本地终端都无响应,可以尝试使用SysRq魔术键安全重启,尽量把内存数据同步到磁盘,命令序列是:按住Alt+SysRq,依次按下R、E、I、S、U、B,每个键间隔2秒,这能最大程度减少数据丢失。

快速定位系统负载源头

登录系统后,第一件事就是运行 uptime 查看系统负载。如果1分钟、5分钟、15分钟的平均负载数值持续走高,甚至超过CPU核心数的几倍,说明系统正承受巨大压力。接下来用 top 或 htop 实时观察哪个进程在疯狂消耗CPU资源。如果发现某个进程CPU占用率持续100%,记下它的PID,用 strace -p PID 追踪该进程的系统调用,看它卡在哪个操作上。常见情况是磁盘I/O读写异常、死锁或者程序本身陷入死循环。如果确认是业务进程问题,可以先 kill -9 PID 终止它,恢复系统正常后再排查代码逻辑。

内存耗尽导致的系统假死

内存不足是CentOS卡死的另一大元凶。当物理内存和Swap交换分区全部耗尽时,内核的OOM Killer机制会开始强制杀进程,这个过程本身就会导致系统严重卡顿。执行 free -h 查看内存使用情况,如果available列数值极低,Swap使用率接近100%,说明内存已经撑爆。用 ps aux --sort=-%mem | head -20 列出内存占用最高的前20个进程。很多时候是MySQL、Java应用或某个脚本内存泄漏造成的。临时解决办法是重启这些高内存占用的服务,但根本方案是调整应用的内存限制参数,比如MySQL的innodb_buffer_pool_size、Java的-Xmx参数,或者增加物理内存。

磁盘I/O瓶颈引发的连锁反应

磁盘I/O打满会导致整个系统响应变慢,甚至看起来像死机一样。用 iostat -x 1 查看磁盘利用率,如果%util列接近100%,说明磁盘已经不堪重负。再配合 iotop 找出是哪个进程在疯狂读写磁盘。常见场景包括:日志文件瞬间暴增撑满磁盘、数据库大量慢查询产生临时表写入、备份任务在业务高峰期执行、或者磁盘本身出现坏道导致读写重试。如果是日志问题,立即清理或轮转日志文件;如果是数据库慢查询,先杀掉这些查询进程,再优化SQL语句;如果是磁盘硬件问题,dmesg | grep -i error 查看内核日志中是否有I/O错误,有的话赶紧备份数据并更换磁盘。

系统进程数耗尽与文件句柄泄漏

Linux系统中一切皆文件,每个进程、每个网络连接都占用文件句柄。当文件句柄达到系统上限时,新的SSH连接无法建立,服务也无法响应。用 ulimit -n 查看当前限制,用 lsof | wc -l 统计已打开的文件句柄数量。如果数量接近上限,用 lsof -n | awk '{print $1}' | sort | uniq -c | sort -rn | head -20 查看哪个进程占用了最多的句柄。通常是应用程序没有正确关闭文件或网络连接导致的句柄泄漏,需要重启该应用并修复代码。临时应急可以调高系统限制:编辑 /etc/security/limits.conf 添加 * soft nofile 65535 和 * hard nofile 65535,然后重新登录生效。

内核参数优化预防卡死

与其每次卡死后手忙脚乱,不如提前优化内核参数来降低死机概率。编辑 /etc/sysctl.conf 文件,加入以下关键参数:

# 避免内存不足时系统假死
vm.overcommit_memory = 1
vm.overcommit_ratio = 80

# OOM Killer触发后立即杀死进程,减少卡顿时间
vm.panic_on_oom = 0
kernel.panic_on_oops = 1
kernel.panic = 10

# 优化内存回收机制,减少磁盘I/O抖动
vm.dirty_ratio = 10
vm.dirty_background_ratio = 5
vm.vfs_cache_pressure = 50

# 增加网络连接追踪表大小,防止连接数过高时丢包
net.netfilter.nf_conntrack_max = 2097152
net.nf_conntrack_max = 2097152

修改后执行 sysctl -p 让配置生效。这些参数能让系统在资源紧张时表现得更稳定,而不是直接卡死。特别是vm.dirty_ratio和vm.dirty_background_ratio,控制了脏页内存的比例,避免大量数据突然刷盘导致I/O阻塞。

使用cgroup限制资源滥用

如果服务器上运行着多个服务,某个服务突然占用大量资源会把整个系统拖垮。用cgroup对关键资源进行隔离和限制是更高级的做法。以限制某个服务的CPU和内存为例:

# 创建cgroup组
mkdir -p /sys/fs/cgroup/cpu/myapp
mkdir -p /sys/fs/cgroup/memory/myapp

# 限制CPU使用率不超过50%
echo 50000 > /sys/fs/cgroup/cpu/myapp/cpu.cfs_quota_us
echo 100000 > /sys/fs/cgroup/cpu/myapp/cpu.cfs_period_us

# 限制内存最大使用2GB
echo 2147483648 > /sys/fs/cgroup/memory/myapp/memory.limit_in_bytes

# 将进程PID加入cgroup
echo $PID > /sys/fs/cgroup/cpu/myapp/cgroup.procs
echo $PID > /sys/fs/cgroup/memory/myapp/cgroup.procs

这样即使该服务出现异常,也不会耗尽整台服务器的资源,其他服务仍然能正常运行,SSH也能保持连接,给运维人员留下操作空间。

硬件故障的排查思路

如果系统频繁无规律卡死,上面软件层面的排查都找不到原因,就要考虑硬件问题了。内存条故障是最常见的原因之一,可以用 memtest86+ 工具对内存进行全面检测,这个测试需要在重启后引导进入,建议在业务低谷期进行。CPU过热也会导致系统降频或死机,用 sensors 命令查看CPU温度,如果温度超过80度,检查散热风扇是否正常运转、散热片是否积满灰尘。电源供电不稳定则会导致随机重启或死机,检查服务器电源指示灯和系统日志中是否有硬件错误记录。用 dmidecode -t memory 查看内存详细信息,用 smartctl -a /dev/sda 检查硬盘健康状态,重点关注Reallocated_Sector_Ct和Current_Pending_Sector这两个指标,数值不为零就说明硬盘已有坏道。

系统日志分析找出真凶

卡死前后的系统日志是破案的关键线索。重点查看以下几个日志文件:/var/log/messages 记录了系统级事件,包括OOM Killer杀死进程的记录、内核报错、硬件异常等;/var/log/dmesg 是内核环形缓冲区日志,记录了驱动加载和硬件相关错误;应用自身的日志则要看具体位置。用 journalctl -k 查看本次启动以来的内核日志,用 journalctl --since "10 minutes ago" 查看最近10分钟的所有日志。如果发现类似 "Out of memory: Kill process" 的记录,说明是内存不足触发了OOM;如果出现 "task blocked for more than 120 seconds" 这类信息,说明有进程因I/O问题被阻塞,通常是磁盘或NFS存储响应超时。

应急脚本自动化处理

为了在卡死发生时能自动恢复,可以编写一个监控脚本,用crontab每分钟执行一次,检测系统负载和内存状况,超过阈值就自动采取行动。脚本示例如下:

#!/bin/bash
# 系统负载监控与自动处理脚本

LOAD=$(uptime | awk -F'load average:' '{print $2}' | cut -d, -f1 | xargs)
CORES=$(nproc)
MEM_AVAILABLE=$(free -m | awk 'NR==2{print $7}')
THRESHOLD_LOAD=$(echo "$CORES * 2" | bc)

# 负载超过核心数2倍时,记录高负载进程
if [ $(echo "$LOAD > $THRESHOLD_LOAD" | bc) -eq 1 ]; then
    echo "$(date): High load detected: $LOAD" >> /var/log/load_monitor.log
    ps aux --sort=-%cpu | head -10 >> /var/log/load_monitor.log
fi

# 可用内存低于500MB时,重启关键服务
if [ "$MEM_AVAILABLE" -lt 500 ]; then
    echo "$(date): Low memory: ${MEM_AVAILABLE}MB, restarting services" >> /var/log/load_monitor.log
    systemctl restart nginx
    systemctl restart php-fpm
fi

把这个脚本加入crontab:* * * * * /usr/local/bin/system_monitor.sh,就能实现基本的自动监控和应急处理。但要注意阈值设置合理,避免误杀正常进程。

长期运维策略与监控体系

解决单次卡死只是治标,建立完善的监控和预警体系才是治本。部署一套Prometheus加Grafana的组合,监控CPU使用率、内存使用率、磁盘I/O、网络流量、文件句柄数等关键指标,设置合理的告警阈值。当某项指标连续5分钟超过阈值的80%时,通过企业微信或钉钉发送告警通知,让运维人员在系统彻底卡死之前就能介入处理。定期巡检服务器,清理过期日志、检查磁盘空间、更新系统补丁,这些看似琐碎的日常工作,能避免大量突发故障。对于核心业务,考虑做高可用架构,用Keepalived实现双机热备,一台服务器宕机时另一台自动接管,业务中断时间从几十分钟缩短到几秒钟。