别再只会 `ls` 了!这几条 Linux 命令才是运维保命的丹书铁券,关键时刻能让你少写两份故障报告
哪怕做了这么多年运维,半夜手机铃声一响,我心脏还是会漏跳半拍。
那种感觉你们都懂,迷迷糊糊摸过手机,看到告警群里一排红色的字,脑子瞬间清醒,紧接着就是一身冷汗。打开电脑,连上 VPN,黑底白字的终端窗口一跳出来,那时候能救你的,不是什么高大上的架构图,也不是PPT里吹的那些云原生概念,而是你敲击键盘的肌肉记忆。
咱们这行,说白了,大部分时间是在和 Linux 内核那一堆莫名其妙的状态较劲。很多新人问我,说看了好几本书,命令背了一大堆,真出了事儿还是只会 cd、ls、reboot 三板斧。
其实不是你背得少,是你没搞懂哪些命令是“看热闹的”,哪些是“救命的”。今天我不跟你们扯什么 mkdir 怎么建目录,那种百度一下就有东西没啥好讲的。咱们聊聊那些真正能在 CPU 飙升、磁盘爆满、网络丢包时,帮你快速定位“凶手”的家伙事儿。
这篇有点长,建议先收藏,下次排障没思路的时候,翻出来看看。
top:不仅仅是看个热闹
出了问题,谁都会敲个 top。但大部分人敲完 top,也就看看那个 %CPU 谁最高,然后就没下文了。
兄弟,那太浪费了。top 这个界面,其实是个富矿。
这里面最有用的其实不是那个跳来跳去的 CPU 占用率,而是第一行的 Load Average(平均负载)。这三个数字(1分钟、5分钟、15分钟)是你判断系统压力的第一道关口。
很多人搞不清楚 Load 到底多少算高。有个很经典的的比喻:你把 CPU 想象成一座桥。
如果 Load 等于 CPU 核数,那是刚刚好,车流顺畅。
如果 Load 大于核数,比如你是 4 核,Load 到了 8,那就意味着有一半的进程在排队等着过桥。
如果是 CPU 密集型任务,Load 高通常意味着 CPU 真的不够用了;但如果是 I/O 密集型(比如数据库读写慢),Load 高可能 CPU 占用并不高,而是大量进程卡在 D 状态(Disk Sleep,不可中断睡眠)。
这时候你在 top 界面按一下 1,把所有 CPU 核展开看看,是不是某一颗核被跑死了?还是比较均衡?
再按一下 c,显示完整的命令行路径,别只看个 java 或者是 python,你得知道是哪个脚本在作妖。
还有一个容易被忽视的:wa(I/O wait)。在 CPU 状态那一行,如果这个数字飙到了 30% 甚至 50%,别查 CPU 了,赶紧去查查是不是磁盘快挂了,或者数据库在疯狂刷盘。
vmstat:给系统把把脉
如果 top 看得眼花缭乱,觉得信息量太大,我强烈推荐你用 vmstat。
vmstat 1,每一秒刷新一次。这命令简直就是系统的“心电图”。
盯着看几列:
- r (run): 等待运行的进程数。如果这个数长期大于 CPU 核数,系统肯定卡。
- b (block): 等待 I/O 的进程数。这玩意儿要是多了,说明磁盘或者网络存贮(NFS)可能是瓶颈。
- si / so (swap in / swap out): 这两个一定要是 0,或者偶尔跳一下。如果这两个数一直哗哗变,说明内存爆了,系统在疯狂用硬盘当内存使,那速度能不慢吗?
以前有次帮朋友排查一个 Web 服务慢的问题,CPU 不高,内存也够,就是慢。敲了个 vmstat 1,发现 cs (Context Switch,上下文切换) 每秒好几万。后来查出来是代码里开了太多线程在空转,光是线程调度就把 CPU 累吐血了。这种问题,光看 CPU 使用率是看不出来的。
ps:抓贼要抓现行
ps 大家都用,ps -ef | grep java 估计是很多人的起手式。
但我更喜欢用 ps aux --sort=-%cpu | head -10。
这行命令的意思是:列出所有进程,按 CPU 占用率倒序排列,只看前 10 个。一目了然,谁是资源大户直接揪出来。
另外,还有一个场景特别搞心态。
就是你发现一个进程卡死了,想 kill 掉它,结果它变成了僵尸进程(Zombie,状态 Z)。这时候你用 ps 就能看到后面有个
记住了,僵尸进程你是杀不死的,因为它已经死了。你要杀的是它的父进程(PPID)。
用 ps -ef | grep 僵尸进程PID 找到它的 PPID,然后送父进程上路,僵尸自然就消失了。
netstat & ss:到底是谁连着我?
网络不通,或者端口被占,这时候就是这两个兄弟登场的时候。
老一点的系统用 netstat,新一点的(CentOS 7+)推荐用 ss,因为 ss 跑得快,尤其是在并发连接数几万几十万的时候,netstat 能卡到你怀疑人生。
最常用的组合拳:ss -lntp。
l: listening,监听中的。n: numeric,不解析域名,直接显示 IP,速度快。t: tcp。p: process,显示是哪个进程占的端口。
还有一个场景,服务器连接数暴涨,你想看看是哪个 IP 在搞你(或者是正常的业务洪峰)。
可以用这行神命令:
netstat -nat | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr | head -20
看着长,其实逻辑很简单:拿出所有连接 -> 提取第五列(对端IP) -> 去掉端口号 -> 排序 -> 统计每个 IP 出现的次数 -> 按次数倒序排 -> 取前 20 个。
如果发现某个陌生的 IP 有几千个连接,那恭喜你,可能被 CC 攻击了,或者是哪个内部服务配置错在疯狂重试。
awk & grep:文本处理的瑞士军刀
在 Linux 上干活,离不开处理日志。
以前我也傻乎乎地用 vi 或者 cat 打开几个 G 的日志文件,结果终端直接卡死,被主管骂了一顿。
查日志,一定要学会“流式处理”。
grep 就不多说了,加个 -A 10 (显示匹配行之后 10 行) 和 -B 10 (之前 10 行) 是基操,方便你看报错的上下文。
这里重点吹一下 awk。这玩意儿其实是一门编程语言,但我们不需要精通,会皮毛就够用了。
比如,Nginx 的访问日志,你想知道哪个接口访问最慢?
假设日志格式里,倒数第二列是响应时间。
tail -n 10000 access.log | awk '{if($NF > 1) print $0}'
这就把最近一万条请求里,响应时间超过 1 秒的请求都打印出来了。($NF 表示最后一列)。
再比如,你要把一个文件里所有的空行删掉:
awk 'NF' file.txt
就这么简单两个字母。
学会 awk,你能把那一堆乱七八糟的日志变成整齐的报表,老板看到都会觉得你这人显着“专业”。
lsof:谁动了我的文件?
这个命令全称是 List Open Files。它的强项在于解决那些“灵异事件”。
比如,最经典的:你明明用 rm 删除了好几个 G 的大日志文件,结果 df -h 一看,磁盘空间根本没释放!
这时候别慌,多半是某个进程还打开着这个文件句柄没松手。系统认为文件还在被用,只是从目录结构里删了入口而已。
输入 lsof | grep deleted。
如果你看到一堆标记着 (deleted) 的文件,找准后面那个进程 PID,重启那个服务或者 kill 掉那个进程,空间瞬间就回来了。那种看着磁盘占用率从 100% 掉到 40% 的瞬间,真的比捏脚还爽。
dmesg:内核在说什么悄悄话?
有时候,服务器挂了,但应用日志里啥也没有。Java 没报错,Nginx 也很正常。这时候,你就得去问问操作系统本身了。
dmesg 或者直接看 /var/log/messages (Ubuntu 下是 /var/log/syslog)。
这里面记录了硬件和内核级别的信息。
比如,OOM (Out of Memory) Killer。
如果你的 Java 进程突然没了,也没留下任何遗言,多半是被 Linux 内核干掉了。
去 dmesg | grep -i "kill" 或者是 grep "Out of memory" 看看。
如果看到类似 Killed process 1234 (java) 的字样,那就实锤了:内存不够,系统为了自保,挑了个最占内存的把你宰了。
还有网卡报错、硬盘 I/O 错误,这些底层硬件的哀嚎,也只能在这里听到。
find:时间的魔法
运维不仅要救火,还得会打扫战场。
清理旧文件,find 是最靠谱的。
千万别手滑写个 rm -rf /*,那你就出名了。
安全删除 30 天前的日志:
find /var/log/myapp/ -name "*.log" -mtime +30 -exec rm -f {} \;
解释一下:
-mtime +30: 修改时间在 30 天以前的。-exec ... \;: 对找到的每个文件执行后面的命令。
有时候你会遇到文件名是乱码或者带特殊字符删不掉的文件,也可以用 find 配合 -inum (inode 编号) 来删,这招专治各种疑难杂症。
strace:最后的绝招
如果上面这些都用了,还是找不到原因。程序就是卡住,不报错,也不输出日志,CPU 也不高。
这时候,只能请出上帝视角的工具:strace。
它可以跟踪进程和 Linux 内核交互的所有系统调用。
strace -p 进程PID
你会看到屏幕疯狂滚动:open(...), read(...), write(...), connect(...)。
如果屏幕突然不动了,或者疯狂循环打印同一行报错,那就是卡住的地方。
有一次,一个 Python 脚本莫名其妙卡死,我挂上 strace 一看,发现它在疯狂尝试连接一个内网不存在的 DNS 服务器,超时设置得特别长。没有 strace,这问题我估计得查到明年去。
不过要注意,strace 会严重拖慢程序运行速度,生产环境慎用,除非你真的走投无路了。
闲聊两句
写了这么多,其实命令这东西,真是那是那句老话:熟能生巧。
刚入行的时候,我也喜欢在桌面上贴个便利贴,上面写满了参数。后来敲得多了,遇到问题手指头比脑子反应还快。
大家千万别觉得运维就是搬服务器、装系统的。现在的环境越来越复杂,容器化、微服务、云原生,底层的逻辑其实还是 Linux 内核那一套。你把这些基础命令玩透了,哪怕上面跑的是 Kubernetes,Pod 出问题了你进到容器里,用的还得是 top 和 netstat。
工具是死的,人是活的。这些命令就像咱们手里的螺丝刀和万用表,能不能修好机器,还得看咱们对系统原理的理解。
行了,今天就聊到这。本来还想扯扯 tcpdump 抓包的事儿,那个更刺激,下次有机会再单独开一篇细说。
要是觉得这篇文章对你有那么一点点帮助,哪怕是帮你回忆起某个遗忘的参数,记得点个赞、在看,转发给身边那个还在对着黑屏发愁的兄弟。
干运维不容易,咱们得互相撑着点。
如果这篇文章对你有帮助,别忘了点赞转发支持一下!想了解更多运维实战经验和技术干货,记得关注微信公众号@运维躬行录,领取学习大礼包!!!我会持续分享更多接地气的运维知识和踩坑经验。让我们一起在运维这条路上互相学习,共同进步!
公众号:运维躬行录
个人博客:躬行笔记