前言:为什么我又造了一个轮子?
今天是2026年4月2日,我依然在凌晨两点处理生产环境的报警。说实话,网上的Linux命令手册多如牛毛,从"菜鸟教程"到各种"必会60个命令",但我发现它们都有一个通病:太干净了。它们给的命令在测试环境跑得欢快,一到生产环境,面对几十G的日志、满载的IO和高并发的网络连接,那些教科书式的命令要么跑死机器,要么输出结果根本没法看。 最近带新人,发现他们遇到服务器卡顿只会无脑重启,或者用 top 看一眼CPU就慌了手脚。这让我意识到,有必要整理一份真正带有"生产环境血泪史"的速查手册。这不是简单的命令罗列,而是我过去5年在无数次故障复盘、性能压测中总结出来的生存法则。这里没有花哨的参数,只有能救命的组合拳。
一、 连接追踪与网络排错:别只盯着 ping 看
很多运维一看到网络不通就 ping,但在微服务架构下,ping通不代表服务通。我更习惯用 ss 替代 netstat,因为后者在连接数上万的时候慢得让人想砸键盘。
1. 快速定位大量 TIME_WAIT 的陷阱
如果你发现服务器访问缓慢,且大量端口被占用,首先检查是不是处于 TIME_WAIT 状态。这通常发生在短连接频繁关闭的场景。不要盲目调低 tcp_tw_reuse,先看看到底是谁在搞鬼。
# 统计各种 TCP 状态的数量,ss 比 netstat 快得多# -t: TCP, -n: 不解析服务名(数字显示), -a: 所有ss -tan | awk 'NR>1 {print $1}' | sort | uniq -c | sort -rn# 输出示例:# 5000 TIME-WAIT# 200 ESTAB# 50 LISTEN如果 TIME_WAIT 超过几千,说明你的后端服务可能没有正确配置连接池,或者负载均衡器健康检查间隔太短。
2. 实战:抓包只要"关键帧"
以前我年轻的时候,tcpdump -i any 一开就是半天,结果几GB的包文件用 Wireshark 打开直接卡死。在生产环境,你要学会"吝啬"地抓包。
# 场景:排查 80 端口连接建立慢的问题 (SYN/FIN/RST)# -i eth0: 指定网卡# -nn: 不进行域名和端口解析,节省时间# -c 100: 只抓 100 个包,够分析即可# 'tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) != 0': 过滤握手和断开的关键包tcpdump -i eth0 -nn -c 100 'tcp port 80 and (tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) != 0)'二、 磁盘与日志分析:如何从 10GB 日志中找线索
生产环境最怕磁盘写满导致服务不可用。很多时候,日志文件动辄几十GB,cat 或 grep 直接操作大文件会导致 IO 飙升,甚至把业务进程拖死。
1. 绝对禁止在生产大文件上直接 grep
如果你有一个 20GB 的 nginx.log,想找 500 错误,千万别直接 grep "500" nginx.log。这会读入整个文件。我的做法是先看尾部,或者使用 less 分页查看。
# 高效查看大文件:先看文件大小,再看最后 1000 行ls -lh nginx-access.logtail -n 1000 nginx-access.log | grep " 500 "# 或者使用 less,按 / 搜索,按 q 退出,不占用大量内存less +F nginx-access.log2. 实战:查找访问量最高的 IP (DDOS 快速定位)
当服务器负载突然飙升,CPU 被吃满,但业务逻辑看起来正常时,要第一时间怀疑是被爬了或者被攻击了。这个命令组合我用了无数次,能在几秒钟内从海量日志里揪出罪魁祸首。
# 分析 Nginx 日志,找出访问次数最多的前 5 个 IP# awk '{print $1}':提取第一列(假设是IP)# sort | uniq -c:统计重复次数# sort -rnk 1:按第一列数字倒序排列# head -n 5:取前5awk '{print $1}' nginx-access.log | sort | uniq -c | sort -rnk 1 | head -n 5三、 系统资源排查:CPU 飙升时的三板斧
看到 CPU 100% 很慌?别急。首先要区分是"用户态"忙还是"内核态"忙。如果是用户态,多半是业务代码死循环或计算密集;如果是内核态,可能是系统调用过多或硬件驱动问题。
1. top 的正确打开方式
不要只盯着第一行的 load average 看。进入 top 后,按 1 可以展开多核 CPU 的详情,按 H 可以查看线程模式。
# 如果 top 太重,可以使用 htop(如果安装了)# 或者使用 pidstat 每秒输出一次 CPU 数据,持续 5 次# -u: 查看 CPU 使用率, -p ALL: 所有进程, 1: 间隔1秒, 5: 输出5次pidstat -u -p ALL 1 52. 实战:定位导致 CPU 飙升的 Java 线程
如果是 Java 应用,CPU 飙升时,单纯看 jps 没用。你需要把 Java 的线程 ID 和操作系统的线程 ID (PID) 对应起来。
# 1. 找到 Java 进程 PIDJAVA_PID=$(ps -ef | grep java | grep app-name | awk '{print $2}')# 2. 打印线程栈,输出到文件jstack $JAVA_PID > jstack.log# 3. 找到消耗 CPU 最高的操作系统线程 PID (通过 top -H 查看,假设是 12034)# 4. 将 10 进制的 PID 转为 16 进制 (jstack 里是 16 进制)printf "%x\n" 12034# 输出:2f02# 5. 在 jstack.log 里搜索 nid=0x2f02,就能看到具体哪行代码在死循环grep "0x2f02" jstack.log -A 20四、 踩坑 / 注意事项:那些让我痛不欲生的坑
这一章没有命令,只有血泪。如果你能避开这些坑,你的周末能少很多次加班。
1. rm -rf 的绝命时刻
现象: 在清理日志时,手抖多敲了一个空格,把 rm -rf /usr/app/logs 敲成了 rm -rf /usr/app /logs。瞬间,应用目录被清空,服务直接挂掉。
教训: 永远不要在生产环境直接使用 rm -rf。请使用 trash-cli 或者先 mv 到 /tmp,过几天再删。另外,alias rm='rm -i' 虽然烦,但能救命。
2. tar 解压覆盖了配置文件
现象: 发布新版本时,直接 tar -xzf new.tar.gz。结果压缩包里包含了一个旧的 application.properties,直接覆盖了线上正在使用的配置,导致数据库连接串变成测试库,大量业务报错。
教训: 解压前务必看一眼压缩包内容 tar -tzf new.tar.gz。或者,使用 --skip-old-files 参数,如果文件已存在则跳过。
# 安全解压:跳过旧文件,不覆盖tar -xzf new.tar.gz --skip-old-files3. 磁盘满了,但 du 看不到大文件
现象:df -h 显示磁盘使用率 100%,但是 du -sh /* 加起来却只用了 40%。这通常是文件被删除了,但进程还占用着文件句柄(比如 Nginx log 没做 rotate)。
教训: 用 lsof | grep deleted 查找。找到那个 PID,重启该进程(或者 reload),空间瞬间释放。
# 查找已删除但仍被占用的文件lsof | grep deleted# 输出示例:# java 12345 root 123u REG 8,1 10737418240 1234 /var/log/app.log (deleted)五、 实战锦囊:高频命令组合速查
最后,为了方便大家(以及我自己)快速查阅,我整理了几个最常用的"一键"组合。
| | |
|---|
| find . -name "*.log" -mmin -10 | |
| netstat -tlnp | grep :8080 | |
| ps -ef | grep "python bot" | grep -v grep | awk '{print $2}' | xargs kill -9 | |
| tail -f error.log | grep --line-buffered "Exception" | |
| uptime | |
总结
Linux 运维不是背字典,而是对系统原理的理解和经验的积累。命令只是工具,真正重要的是你如何通过这些工具去构建一个"可观测、可恢复"的生产环境。上面提到的每一个坑,我都亲身经历过,希望这份手册能成为你值班时的护身符。记住,在按下回车键之前,多想一秒,多看一眼。