Linux卡住了?这篇帮你快速自救
半夜短信响起:"服务器挂了,命令行敲什么都不响应。" 你深吸一口气,打开手机SSH准备战斗——然后发现连SSH也卡了。这种事,运维/后端没遇上过几次是不存在的。
别慌。这篇不是教科书,是老司机踩坑实录。讲的是你真的遇到了Linux卡死、命令行敲了没反应时,怎么一步步把机器救回来。Ctrl+C/S/Z、kill -9、top/htop、OOMKiller、磁盘爆满、sshd卡死、systemctl无法使用——这些场景都会讲到。
一、先搞清楚:你是哪种卡法?
Linux卡住分好几种,处理方式完全不一样,上来就重启的都是莽夫。
1. 终端假死(按键有反应但无输出)
最常见的类型。你敲了命令,屏幕光标卡住,什么都不出来,但键盘能打字。这种一般是程序在等I/O或者跑进了死循环。
先试这个:
# 先按 Ctrl+Q 解锁(有些场景是 Ctrl+S 锁屏的)
# 如果不管用,按 Ctrl+Z 挂起到后台
# 然后 jobs 看看后台有什么,再 bg 拉回来或 kill 掉
jobs
bg %1
# 或者直接 kill 掉
kill %1
2. SSH卡死(连上了但命令不执行)
连上了,但敲什么都是空白,十秒二十秒没响应。这种往往是网络问题或者服务器负载过高。
# 强制断开当前会话,热知识:SSH呆等也会卡
# 按 ~. 三个字符快速断开(注意是SSH会话内的转义符)
# 或者新开一个终端重新连,用另一个终端排查问题
# 新开一个终端连上去
ssh user@your-server
# 看看SSH进程状态
ps aux | grep ssh
3. 机器完全无响应(连ping都不通)
这是最严重的。SSH连不上,ping也不回,机器可能是真的挂了或高负载。这时候能用的只有IPMI/iLO/ILO/DRAC等远程管理卡,或者——有备用root。
# 通过IPMI远程查看控制台
ipmitool -H YOUR_IL_HOST -U ADMIN -P PASSWORD sol activate
# 或者在本地终端查看Serial Console日志
dmesg | tail -100
journalctl -xn 50
二、5步急救法:不管什么卡,先按这个顺序来
Step 1:区分卡在哪一层
上来就 kill -9 是新手操作。正确姿势是:先用 Ctrl+C 尝试正常退出,等两秒不行再考虑更强硬的手段。
# Ctrl+C 发送 SIGINT,程序会尝试优雅退出(相当于程序收到"请您下班"的信号)
# 大部分程序会收这个信号,注册了signal handler的会先清理再退出
# 如果 Ctrl+C 没反应,等几秒后再试 Ctrl+\ (SIGQUIT)——这是强制退出,不清理
# Ctrl+\ 会让程序立即退出,产生core dump(如果配置了的话)
Step 2:确认是shell的问题还是程序的问题
敲个空命令看看shell还活着不:
# 敲这个,如果返回 bash 提示符,说明shell正常,是程序卡了
echo "still alive"
# 如果有反应但很慢,说明系统负载已经很高了
# 敲这个,如果什么都没返回——很可能是SSH客户端或终端的问题
# 试试 Ctrl+J(有时候Ctrl+C被映射坏了,Ctrl+J等效回车)
Step 3:挂起/切后台
程序卡住了,先 Ctrl+Z 挂起,拿到控制权再说:
# Ctrl+Z 发送 SIGTSTP,挂起进程到后台
# 程序会暂停,不会退出,你还能继续敲命令
jobs # 查看后台任务
fg %1 # 拉回前台继续(如果想继续让它跑的话)
kill %1 # 杀掉后台任务
Step 4:定位卡住的进程
拿到控制权后,第一件事是找出谁在搞事情:
# 看负载状态,三个数字:1分钟/5分钟/15分钟平均负载
uptime
# 11:23:45 up 99 days, 3:22, 2 users, load average: 15.23, 12.10, 9.45
# load average 15.23 意味着有15个进程在排队,机器已经很吃力了
# 看进程状态,按CPU排序
top
# 按 M 按内存排序,PID找出来,准备kill
# 如果top也卡,试试这个——htop更友好,但一般系统不一定预装
htop
Step 5:杀掉它
找到PID了,开杀。但别上来就用 -9,留到最后:
# 先温柔地 kill (SIGTERM, 信号15)——正常退出信号
kill [PID]
# 等5秒,没反应?再试试
kill -15 [PID]
# 还卡着?上 -9 (SIGKILL)——强制杀掉,不给程序清理的机会
# 这个信号程序是拦不住的,直接被内核拿走
kill -9 [PID]
# 如果你不知道PID,但知道进程名,用这个批量招呼
pkill -f "python.*script.py" # 匹配进程名
killall -9 python # 按名字杀掉所有python进程
数据库进程、写入中的文件、锁文件——都可能被留在不干净的状态。遇到数据库或重要服务卡住,先试 kill -15,等15秒,再 kill -9。这15秒可能是救命的关键。
三、Ctrl+C / Ctrl+S / Ctrl+Z 到底啥区别?
这三个是Linux人每天都在用但不一定说得清楚的操作。老司机给你讲明白:
| 快捷键 | 信号 | 程序行为 | 场景 |
|---|---|---|---|
Ctrl+C | SIGINT (2) | 优雅退出 | 想正常终止程序时首选 |
Ctrl+Z | SIGTSTP (20) | 暂停挂起 | 想暂时挂起,回头继续的场景 |
Ctrl+S | XOFF(流控) | 暂停终端输出 | 这个不是信号!只是让终端不显示输出,按 Ctrl+Q 恢复 |
Ctrl+\ | SIGQUIT (3) | 强制退出+dump | Ctrl+C 不管用时的升级选项 |
# Ctrl+S 的正确用法——真的只是锁屏幕,不影响程序运行
# 比如你要切到别的窗口看日志,但程序还在疯狂输出,用这个暂停一下
# Ctrl+Q 解锁,恢复终端输出
# 很多新手不知道这个,以为程序卡了,其实只是屏幕暂停了
四、top/htop 实战:怎么看出谁在搞死机器?
top 是运维最重要的工具之一,但很多人只会看前三行。咱们来深入讲讲。
# top 默认视图,按 P 按CPU排序,按 M 按内存排序
top
# 常用交互命令(top运行后按这些键)
# P - 按CPU排序(默认)
# M - 按内存排序
# N - 按PID排序
# T - 按运行时间排序
# k - 杀掉进程(输入PID回车,再选信号)
# r - 重新设置优先级(renice)
# 1 - 展开看每个CPU核心
# f - 配置显示列
# q - 退出
看 top 输出,重点关注这几列:
# S 列的状态含义
# R - Running,正在运行
# S - Sleeping,可中断睡眠(等I/O、网络、信号等)
# D - Disk sleep,不可中断睡眠(等硬件,典型是等待磁盘)
# Z - Zombie,僵死进程,父进程没回收
# T - Stopped,挂起状态
# %CPU 特别高的进程——看看是正常计算还是死循环
# %MEM 特别高的——可能内存泄漏
# TIME+ 特别长还在跑——可能是僵尸祖传进程
如果 top 卡住了(是的,top 也会卡),用这些方法绕过:
# 批量模式,不进入交互,直接输出快照
top -b -n 1 | head -30
# 只看指定进程
top -p [PID]
# htop——如果装了的话,好用太多
# 支持鼠标、树形视图、颜色区分、可视化CPU/内存
htop
apt install htop 或 yum install htop,htop 默认支持颜色、鼠标操作、树形进程关系,比 top 直观太多。如果你的机器连 htop 都装不上——说明网络也有问题,这时候先解决网络。
五、内存不足:OOMKiller 到底是怎么工作的?
OOMKiller 是 Linux 内核的自我保护机制——当物理内存耗尽,内核会挑一个进程杀掉来腾出空间。这个进程不是随机的,是按 oom_score 来排序的。
怎么判断是不是 OOMKiller 在搞鬼?
# 看系统日志里有没有 oom-killer 字样
dmesg | grep -i "oom-killer"
# 输出大概长这样:
# [1234567.890123] Out of memory: Killed process 12345 (python) total-vm:2048000kB, anon-rss:1024000kB, file-rss:0kB
# 看 journalctl 也有
journalctl | grep -i "oom"
怎么看进程的 oom_score?
# oom_score 分数越高,被干掉的可能性越大
# 这个分数是根据内存占用、运行时间、进程优先级算出来的
cat /proc/[PID]/oom_score
# 可以手动调分数,调整后越不容易被杀(调低)或越容易被杀(调高)
echo 1000 > /proc/[PID]/oom_score_adj
怎么防止重要进程被 OOMKiller 杀掉?
# 给进程设置 oom_score_adj 为负数,降低被杀概率
# 数值范围:-1000 到 1000,越负越不容易被杀
echo -500 > /proc/[PID]/oom_score_adj
# 永久调整,在 systemd 服务文件里加
# [Service]
# OOMScoreAdjust=-500
内存真的不够了怎么办?
# 查看内存使用情况
free -h
# 看谁在吃内存
ps aux --sort=-%mem | head -20
# 查内存泄漏的祖宗——看看哪个进程内存一直涨
pmap -x [PID] | tail -5
# 如果有swap,可以临时清一清(但别指望swap能救命)
swapoff -a && swapon -a
六、磁盘爆满:很多卡死问题的根源
磁盘满了会导致:日志写不进去、程序无法正常fork、系统服务无法启动。很多"玄学"问题查到最后都是磁盘问题。
# 先看整体磁盘使用情况
df -h
# 看 inode(有时候磁盘有空间但inode耗尽了)
df -i
# 找大文件——从根开始,按目录一层层找
du -sh /* 2>/dev/null | sort -hr | head -20
# 看指定目录的大小
du -sh /var/log
常见踩坑目录:
# 日志文件——最大的坑
# 多年没轮转的日志,轻轻松松吃掉几十G
# 查看各日志文件大小
ls -lhS /var/log/
# 清理老日志前,先看看在写的进程有没有在用这些文件
lsof +D /var/log/
# core dump 堆积
# 每次程序崩溃都会产生core文件,这玩意儿有时候几个G
find / -name "core.*" -type f -size +100M 2>/dev/null
不要直接 rm 日志文件!程序还在往里面写,rm 之后磁盘空间不会释放(文件被删但进程还握着文件描述符)。正确方式是:truncate -s 0 /var/log/xxx.log 或者 echo "" > /var/log/xxx.log,然后再 kill -HUP 触发日志进程重新打开文件。或者用 logrotate 自动化管理。
七、sshd 卡死了怎么办?
SSH 连上了但是敲命令没反应,这种情况太常见了。先判断是网络问题还是 sshd 进程卡了。
# 在另一个终端快速连上去测试
ssh -o ConnectTimeout=5 user@server
# 能连上,说明sshd没死,是你的会话有问题
# 用 Ctrl+] 退出,然后重新连
# 如果连不上——sshd可能真卡了
# 用 IPMI 登录管理口,在本地重启 sshd
systemctl restart sshd
如果连 IPMI 都没有,只能等——SSH 有个 ServerAliveInterval 选项,断连会自动重试。但如果你已经卡死了,老老实实找机房值班重启。
# 避免以后SSH卡死,在 ~/.ssh/config 里加这些
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
TCPKeepAlive yes
八、systemctl 无法使用怎么办?
systemctl 本身卡住了,或者服务卡在启动/停止状态——这是很常见的坑。
systemctl 卡住了
# 先确认是systemctl卡了还是服务卡了
# Ctrl+C 打断 systemctl,看看是不是 systemd 自己问题
# 看看 systemd 进程状态
ps aux | grep systemd
# journalctl 也能看系统日志
journalctl -u nginx --since "10 minutes ago"
服务卡在启动/停止状态
# 看服务当前状态
systemctl status nginx
# 如果卡在failed状态,强制杀
systemctl kill -s SIGKILL nginx
# 清掉 PID 文件,手动 reset 状态
rm /var/run/nginx.pid
systemctl daemon-reload
systemctl restart nginx
最暴力解法——直接操作 systemd 管理树
# 查看 systemd 的 cgroup 树,看看服务进程还在不在
systemctl status
# 如果 systemd 自己挂了(很少见),用这个重置
systemctl daemon-reexec
每次修改服务配置后,记得 systemctl daemon-reload 再 restart。reload 是让 systemd 重新读取配置,restart 是重启服务,很多人忘了 daemon-reload 导致改完不生效。
九、预防措施:怎么让机器别那么容易卡?
1. 监控先行
# 装个监控,zabbix/prometheus/grafana/...,总得有一个
# 重点监控:CPU负载、内存使用、磁盘使用、inode使用
# 告警阈值:磁盘85%、内存90%、负载超过CPU核心数
# 简单巡检脚本
df -h | awk 'NR>1 $5>85 {print "Disk alert: " $0}'
free | grep Mem | awk '{printf "Mem: %.0f%% used\n", $3/$2*100}'
2. 日志轮转要配置好
# /etc/logrotate.conf 是全局配置
# /etc/logrotate.d/ 里的文件是各服务单独配置
# 手动测试 logrotate 配置
logrotate -d /etc/logrotate.conf
3. 合理设置 limits
# /etc/security/limits.conf
# 避免一个进程把系统资源吃光
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535
# 看当前 limits
ulimit -a
4. 不要在生产跑奇怪的命令
# rm -rf / 类的悲剧每年都有
# 危险操作前,养成习惯先 echo 看看路径
echo rm -rf /var/log/xxx
# 确认路径对了再跑
# 用 alias 限制高危命令
alias rm='rm -i' # 交互式删除
十、写在最后
Linux 卡住了不可怕,怕的是卡住了乱来。记住这个顺序:
Ctrl+C → Ctrl+Z → 定位进程 → kill → kill -9
大多数卡死问题按这个顺序都能解决。少用 -9,多用 -15,给程序一个收场的机会。
真正预防卡死的方法只有一个:监控到位、磁盘留余量、日志管好。这三件事做到位,你的服务器稳定性能上一个台阶。
如果觉得这篇文章有用,收藏起来,下次凌晨三点服务器报警的时候,这篇就是你的救命手册。
需要更多运维工具?去 CloverTools 开发工具集 看看,里面有大量实用工具,帮你把重复劳动自动化。
常见问题
A: 这类工具一般有明确的输入框和输出框,按提示输入内容,点击对应按钮即可得到结果。建议先用简单示例测试功能是否正常,再处理实际数据。
A: 根据具体工具类型决定。格式转换工具适合处理第三方数据,编码工具适合加密传输,压缩工具适合文件上传前处理。多积累工具使用经验,遇到问题时能快速判断用哪个工具解决。
A: 不同工具有不同侧重,重点是理解原理。可以同时安装多个类似工具,实际使用中对比效果,选择最顺手的一个。随着使用经验增加,你也能判断工具的好坏。