服务器日常运维命令:top看负载/df看磁盘/free看内存/netstat看端口
服务器变慢或报错别急着重装:top 看负载、df 看磁盘、free 看内存、netstat 看端口,这四条命令通常能在一分钟内把问题定位到 CPU、磁盘、内存还是网络层。下面用四个排障案例说明每列该怎么读。
案例一:后台打开要十几秒,先看 top 的负载怎么读
有个做外贸独立站的客户反馈,后台列表页要等十几秒才出来,重启 Nginx 也没用。登上去第一件事是敲 top,第一行就给出了线索的一半:
top - 09:12:41 up 46 days, 2:13, 1 user, load average: 12.4, 9.8, 6.3
load average 三个数分别是 1 分钟、5 分钟、15 分钟的平均负载,它本身没有绝对好坏,要和 CPU 核数放在一起比。nproc 查出这台机器是 4 核,而 15 分钟负载已在 6 以上,说明请求队列在持续堆积。按常见经验,负载长期高于核数的 1 到 1.5 倍就该查了,具体阈值以业务能忍受的响应时间为准。
接着读 %Cpu(s) 那一行:us 高是应用自己算得凶,sy 高多半是系统调用或网络中断密集,wa 高则是磁盘 IO 拖住了。这个案例里 wa 只有百分之几,us 却接近满载,方向立刻明确:不是磁盘,是 PHP 进程在抢 CPU。
在 top 界面里几个动作能省很多时间:按 1 展开每个核心,避免"总 CPU 不高但单核跑满"被掩盖;按 P 按 CPU 排序、按 M 按内存排序;shift + e 切换内存单位。找到吃 CPU 的 PHP-FPM 进程号后,用 top -Hp 进程号 看线程,再配合 pidstat -u 1,基本能锁定是哪段代码或哪条慢查询。
案例二:df 显示还有空间,文件却写不进去
第二个案例是上传接口报错,日志里全是 No space left on device,但运维面板显示磁盘才用了六成左右。
df -h 看的确实是容量,还有一条常被忽略的命令:df -i,它看的是 inode。一个分区 inode 用满,即使还剩几十 GB 空间,也建不了新文件。这个案例里 /var 分区的 inode 使用率已经到顶,元凶是程序往同一个目录写了上百万个 session 小文件。
定位方式是从根往下钻:
du -sh /* 2>/dev/null | sort -h
du -sh /var/* | sort -h
df -i
如果发现 df 和 du 的结果对不上,比如 df 说用了九成,du 一层层加起来只有四成,那多半是"幽灵文件":文件已经被 rm 删掉,但还有进程握着它的句柄在写。用 lsof +L1 或 lsof | grep deleted 能找到,重启或 reload 对应进程后空间立刻释放。
结论很直接:清理日志不要只写 rm -rf,配上 logrotate 做按天切割和保留份数,再给关键目录加 inode 数量告警,比事后救火省事得多。
案例三:进程半夜消失,free 要看的不是 free
第三个案例是 Java 服务在凌晨两三点被重启,业务侧只看到 502。
free -m 里同时有 free 和 available 两个值,判断内存够不够要看 available,它是应用真正还能拿到的量,包含可回收的 buff/cache。free 很小但 available 还有几个 G,通常是正常的缓存占用,不用慌。
真正要确认是不是被系统杀掉的,查内核日志:
dmesg -T | grep -i -E 'oom|killed process'
journalctl -k | grep -i oom
看到 Out of memory: Killed process 就说明是 OOM Killer 干的。这时再回头调小应用的内存上限,比如 php-fpm 的 pm.max_children、Java 的 -Xmx,让它别把整机吃光。vmstat 1 里的 si/so 两列如果长期非零,说明已经在用 swap,响应变慢是必然的,加 swap 只是缓冲,不是解决办法。
案例四:端口不通,先分清没监听还是被拦
有客户问"网站打不开是不是服务器挂了",一问端口是 443。
先在本机确认服务状态:
ss -tunlp | grep -E ':80|:443'
ss -lntp | grep 8080
curl -I http://127.0.0.1:8080
ss 是 netstat 的现代替代,老系统没有就用 netstat -tunlp。如果输出里根本没有对应端口,那是服务没启动或者只绑到了 127.0.0.1;如果有监听,且本机 curl 通、外网不通,问题就在链路上:云厂商安全组、本机防火墙、上层负载均衡或 CDN 回源。防火墙看 iptables -L -n --line-numbers,用 firewalld 的看 firewall-cmd --list-all。外部连通性用 nc -vz 域名 端口 或 telnet 验证,比在浏览器里干等快。
另外 TIME_WAIT 数量异常多,通常是短连接开得太频繁,考虑在应用侧做连接复用,而不是去改内核参数硬压。
四个案例的共同结论:把命令变成固定巡检
单点快照容易误判,真正有用的是趋势。把上面几条命令写成一个脚本,交给 crontab 每 5 分钟跑一次,超过阈值就告警:
#!/bin/bash
cores=$(nproc)
load=$(awk '{print $1}' /proc/loadavg)
df -h | awk 'NR>1 && int($5)>85 {print "disk:", $0}'
free -m | awk 'NR==2 && $7<200 {print "mem available low"}'
ss -lnt | grep -q ':443' || echo "443 not listening"
判断阈值可以参考:负载持续超过核数的 1.5 倍、分区使用率超过八成半、available 低于总内存的一成、关键端口不在监听列表。这些数字只是起点,最终要按自己业务的实际表现调。
再补一句经验:top、df、free、netstat 这四条命令解决的是"现象在哪一层",不解决"为什么"。先定位层,再去翻应用日志和慢查询;顺序反了,排查时间会翻好几倍。