
1. 为什么“看资源”这件事值得系统学一遍我在帮朋友处理服务器问题的时候发现一个很有意思的规律大多数人在拿到一台Linux服务器时第一反应是装上各种监控面板或者敲top看一眼就完事。可真到出问题的时候——数据库响应慢、训练任务卡死、服务被 OOM Killer 干掉——很多人又不知道从哪里看起。排查服务器问题第一个动作永远是“看资源”。这里的资源就三类CPU、内存、GPU显卡。CPU是大脑负责计算调度内存是工作台所有运行中的数据都得放上面GPU则是专用的并行计算单元深度学习训练、推理、视频编解码都靠它。这三者的使用情况直接决定了一台服务器的能力和瓶颈在哪里。这篇内容我按“命令 输出解读 实战场景”的方式来讲覆盖从基础到进阶的完整链路。不管你是刚接触Linux的运维新人还是已经在跑模型训练、调优数据库的开发者这篇都可以当成一份查漏补缺的速查手册。如果你手头的服务器偶尔卡顿、内存告警、GPU利用率上不去那这篇文章特别适合你。2. 内存最容易瞒报的一环2.1 free -h 五列输出每一列都别放过看内存大家最熟悉的就是free -h。但真问起来很多人只盯着used和free这两列其实这是最容易误判的地方。$ free -h total used free shared buff/cache available Mem: 31Gi 18Gi 1.2Gi 345Mi 11Gi 11Gi Swap: 8.0Gi 2.1Gi 5.9Gi我一条条拆开来说total物理内存总量这个没啥可说的。used已经被进程占用的内存。但注意这里的 used 并不等于“不可回收的内存”待会儿讲 buff/cache 你会更清楚。free完全没被分配的内存。很多人觉得 free 小就是内存不够其实不完全对。shared多个进程共享的内存比如共享内存段、tmpfs 临时文件系统都会占这部分通常不大。buff/cache内核用来做磁盘缓存、页缓存的内存。这个值大不代表内存不够——恰恰相反Linux 会尽量用空闲内存做缓存来提高文件读写性能当别的进程需要内存时这部分能被自动回收。available估算出来“还可以直接给新进程使用”的内存。这才是你看机器还扛不扛得住的关键指标。注意判断内存是否紧张请优先看available不要只盯着free。一台机器 free 只有 300MB但 available 还有 20GB说明内核手里捏着大把可回收页缓存新进程进来照样抢不到内存的概率很低。2.2 定位内存杀手别再用 top 手动翻top看内存确实直观进程列表默认按 CPU 排序按下M可以按内存排序但问题在于top 的输出是动态刷新的你很难一眼抓住“到底谁在持续吃内存”。而且 top 只看到进程维度的 RSS有很多内存根本不算在单个进程头上。实际排查时我一般直接甩出ps的排序输出一次性列清楚ps aux --sort-%mem | head -20这个命令把内存占用率降序排列取前 20 个进程。%MEM是进程 RSS 占物理内存的百分比VSZ是虚拟内存的大小RSS是实际驻留内存大小。在看结果的时候我有个经验重点关注 RSS 超过总内存 10% 的进程如果同时存在多个大内存进程那就得算算总和是否接近 total。另外一个好用的工具是pidstat它可以按固定间隔持续采样定位“内存增长趋势”pidstat -r 2 10每 2 秒采样一次共 10 次输出里能看到 minflt/s 和 majflt/s缺页中断数。如果 majflt/s 频繁出现非零值说明进程在做磁盘交换内存已经吃紧了。2.3 数据库内存占用过大是缓存策略在“捣鬼”热搜词里有一条“服务器数据库占用内存过大怎么办”我单独拿出来讲因为这在生产环境里实在太常见了。拿 MySQL 举例innodb_buffer_pool_size默认是 128MB但很多运维同学为了性能会手动调高到物理内存的 60%~70%。这部分内存归 InnoDB 管理论上属于“占用但可再分配”的范畴——说是缓存但它不像页缓存那样能自动回收给别的进程导致你free -h看 used 非常高又没有明显的进程列表占满内存。这时候正确的排查顺序是先用free -h看available是否真的已经见底。如果 available 充足不用慌是正常缓存占用。如果 available 也告警了再查数据库配置里各大缓存池参数、连接数、临时表大小。最后用SHOW ENGINE INNODB STATUS\G看 buffer pool 命中率决定要不要调小缓存。实操心得很多数据库“内存占用过大”其实不是内存泄漏是缓存策略非常激进。盲目调小缓存池会严重影响查询性能正确做法是先看命中率再结合业务并发量去调。3. CPU从“会用 top”到“看懂负载”3.1 先用 lscpu 摸清服务器家底看 CPU 使用率之前你得先知道这台机器有多少核、什么架构。因为多核 CPU 的百分比阈值完全是另一套算法单核 100% 在四核机器上整体也就 25%。$ lscpu Architecture: x86_64 CPU(s): 32 On-line CPU(s) list: 0-31 Thread(s) per core: 1 Core(s) per socket: 16 Socket(s): 2 Model name: Intel(R) Xeon(R) Gold 6248R CPU 3.00GHzCPU(s)是逻辑核总数Socket(s)是物理 CPU 颗数Core(s) per socket是每颗 CPU 的物理核心数Thread(s) per core是超线程数。三者相乘2×16×132就得到了逻辑核总数。这个信息直接影响你对top输出中 load average 的判断——负载不是看绝对数值而是看它与逻辑核数的比例。3.2 top 的收尾一行信息量其实很大top命令本身很简单但大多数人看完进程列表就关掉了反而忽略了真正关键的汇总数据。我通常只关心top的前五行尤其是%Cpu(s)这一行%Cpu(s): 3.2 us, 1.6 sy, 0.0 ni, 94.3 id, 0.8 wa, 0.0 hi, 0.1 si, 0.0 st逐项解释ususer用户态进程占用 CPU 的比例。跑业务程序、编译代码、Python 脚本主要吃这里。sysystem内核态占用 CPU 的比例。系统调用频繁、上下文切换多的时候会高。ninice被调整过优先级的进程占用 CPU 的比例。ididleCPU 空闲比例。这个最大不代表没有瓶颈只是说明 CPU 还没有被打满。wawait I/OCPU 等待磁盘、网络 I/O 完成的时间占比。这个值一旦持续超过 10%基本可以断定瓶颈在磁盘而不是 CPU。hi/si硬件中断和软件中断的占比。ststeal虚拟化场景下宿主机抢走 CPU 的占比。云服务器上如果 st 值持续很高说明宿主机的邻居在“捣乱”。wa是最容易误导人的指标。我在压测环境里经常看到有人一跑任务就盯着id越来越低以为 CPU 不够了结果iostat一看磁盘利用率 100%活生生被 IO 拖住了。3.3 Load Average 到底应该怎么判断Load Average 三个数字分别表示 1 分钟、5 分钟、15 分钟的平均负载这个负载是所有处于运行态和不可中断态的进程数量之和。判断标准负载 / 逻辑核数 0.7 要警惕 1.0 说明任务排队了 2.0 大概率已经不可用。比如说一台 8 核机器load average: 5.6, 4.8, 3.9看绝对值觉得才 5 点几还好但除以 8 就是 0.7已经处于持续高负载区间了。反过来如果你看到 1 分钟负载比 15 分钟高出一大截比如8.0, 1.2, 0.8说明是瞬时突发的峰值任务不一定是持续瓶颈。常见误区load average 不是 CPU 使用率。一个进程卡在内核态等待磁盘 I/O它不占 CPU但一样会拉高 load。我之前就踩过这个坑数据库备份任务把磁盘打满CPU 使用率才 15%负载却飙到了 30差点误判方向。如果要深入定位进程对 CPU 的占用用pidstat -p PID 1 5观察单进程或者top -H -p PID查看进程内部线程的 CPU 分布——这是在排查多线程服务问题时最常用的两个命令。真正排查多线程 CPU 问题的时候top -H可以把每个线程的 CPU 占用拉出来再jstack或者gdb附到对应线程 ID 上就能抓到具体的调用栈。4. GPU深度学习环境下必看的一块4.1 nvidia-smi 输出里藏着哪些关键信息GPU 的查看方法和 CPU 不太一样最常用的命令是nvidia-smi。我第一次跑这个命令的时候下面一长串表格看得人眼花缭乱。实际上核心信息集中在每个 GPU 卡的条目里$ nvidia-smi ----------------------------------------------------------------------------- | NVIDIA-SMI 470.82.01 Driver Version: 470.82.01 CUDA Version: 11.4 | ------------------------------------------------------------------------- | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | || | 0 Tesla T4 Off | 00000000:00:1E.0 Off | 0 | | N/A 51C P0 32W / 70W | 2047MiB / 15109MiB | 0% Default | -------------------------------------------------------------------------重点看几个值TempGPU 核心温度超过 85°C 就该看看散热和清灰了90°C 以上属于高危状态。Memory-Usage显存使用量。模型训练时显存不够会直接 OOM 报错这是最常见的报错之一。GPU-UtilGPU 计算单元利用率。这个值要看场景模型推理服务可能很低但吞吐正常训练任务如果长期低于 50% 就说明有瓶颈。Pwr:Usage/Cap当前功耗和最大功耗。如果显存高但功耗低GPU 可能处于等待数据的状态。第一次排查的时候直接nvidia-smi -l 2可以每 2 秒刷新一次类似top的动态效果。但生产环境里我更推荐用nvidia-smi dmon它输出的是一行行的紧凑数据更容易拿到监控日志里去做趋势分析nvidia-smi dmon -s pucmet -d 5-s参数指定显示类型p功耗、u利用率、c计算过程、m显存、e错误、t温度。这样每 5 秒输出一行把输出重定向到文件就是最朴素的 GPU 监控数据源。4.2 GPU 利用率低但显存占用高问题出在数据管道关于 GPU 使用我有一个心得体会很多人以为 GPU 显存占用高就代表 GPU 在正常工作这个判断是错的。模型训练的时候显存高但 GPU-Util 低是特别典型的现象。打个比方GPU 像一个高速车间显存是车间里的仓库如果“送料员”来不及把数据从硬盘搬到仓库车间里的机器就只能干等着——这时候仓库是满的机器GPU 核心却闲着。排查链路一般是这样先用nvidia-smi确认 GPU-Util 和显存如果显存高、利用率低基本排除显存不足问题。用top看 CPU 几个核心是否被打满如果 CPU 核心全满说明数据预处理、数据增强逻辑在 CPU 端阻塞了。用iostat -x 1看磁盘读速率如果磁盘 %util 接近 100%基本确定是数据读取慢。解决方案无非几种开多进程 DataLoaderPyTorch 里num_workers参数、把数据放到内存或者 NVMe 盘、用更高效的图片解码库替代 OpenCV 默认解码。这个排查思路适用于所有 GPU 加速任务不只是深度学习视频编解码、科学计算也一样。GPU 是“闲着还是忙着”别只看显存GPU-Util 才是核心依据。4.3 CUDA 版本与驱动版本的兼容性确认跑 GPU 任务经常出现“cudaGetDeviceProperties failed”或者运行时报 unsupported driver 之类的错误这多半是驱动和 CUDA 版本对不上。入门级方法是这样检查nvidia-smi # 看右上角 CUDA Version这是驱动支持的最高 CUDA 版本 nvcc --version # 看当前环境里安装的 CUDA toolkit 版本驱动支持的 CUDA 版本必须大于等于实际使用的 CUDA toolkit 版本。比如驱动显示 CUDA Version 11.4你用 conda 装了支持 CUDA 12 的 PyTorch运行时就可能直接崩。还有一个坑nvcc不是一定装了的很多容器镜像里只有运行时没有完整的 CUDA toolkit所以nvcc --version会报 command not found。这时候用ls /usr/local/ | grep cuda看看目录结构或者直接在代码里torch.version.cudaPyTorch 环境确认也行。5. 别一台机器开四个窗口综合诊断工具推荐5.1 dstat一条命令同时看 CPU、内存、磁盘、网络单独跑top、free、nvidia-smi确实能拿数据但手动拉齐时间轴是件痛苦的事。我排查复杂问题时的习惯是先用一个综合工具把所有指标打在一个屏幕上快速定位瓶颈维度再针对性下钻。dstat是这类工具里最顺手的。如果没装# Ubuntu/Debian apt install dstat # CentOS/RHEL yum install dstat然后跑dstat -c -d -m -n -t 5输出会同时刷新 CPU 使用率、磁盘读写的块数、内存状态、网络收发外加时间戳。哪个指标异常一眼就能看出来。确定了瓶颈维度之后再对症下药用pidstat、iostat、nvidia-smi dmon做深度定位。5.2 sar搞定历史趋势回溯排查偶发性问题时实时命令往往来不及抓到现场这时候得有历史数据。sysstat包里的sar命令就是为了干这个的。用之前先开数据采集# 编辑 /etc/default/sysstat 确保 ENABLEDtrue systemctl restart sysstat然后就能随时回溯sar -r -f /var/log/sysstat/sa$(date %d) # 看今天内存使用 sar -u -f /var/log/sysstat/sa$(date %d) # 看今天 CPU 使用 sar -n DEV 1 3 # 实时网络流量场景很典型凌晨 3 点应用挂了一次你人不在电脑前。上班第一件事sar -r -f翻内存历史发现 2:50 开始 memory commit 一路飙升到 100%基本就能锁定是内存耗尽导致 OOM再去翻/var/log/messages或者journalctl验证即可。5.3 扩展思路顺手把 CPU 温度和频率也看了CPU 温度在服务器场景里其实经常被忽略但它对性能的影响是实打实的——CPU 温度过高会触发降频算力直接打折。检查工具是lm-sensors# Ubuntu/Debian apt install lm-sensors # CentOS/RHEL yum install lm_sensors # 初始化检测 sensors-detect --auto # 查看温度 sensors输出里Package id 0是 CPU 整体温度下面每个核还有单独的温度值。服务器机房夏天没开空调或者散热器积灰温度报警往往比 CPU 使用率更能解释“为什么最近变慢了”。我处理过一起案例一台物理机运行同一个任务冬天 2 小时跑完夏天要 5 个小时查来查去最后就是 CPU 过热降频导致的。6. 常见问题与排查技巧实录6.1 CPU、内存占用都不高但服务器卡成 PPT这个现象在热搜词里出现过也是我接到的最高频咨询。第一反应不是继续看 CPU 或内存而是检查磁盘 I/O。用iostat -x 1看%util和await两个指标如果 %util 持续超过 90% 或者 await 明显高于个位数毫秒磁盘就是罪魁祸首。另一个可能被忽略的方向是网络。某些程序即使流量不大如果频繁建立连接、大量小包传输也会导致软中断占用大量 CPU 时间。用top按si列排序看看有没有异常或者用sar -n DEV 1看 pck/s 是否异常高。还有一种情况是系统内存吃紧导致 swap 频繁换入换出表现是free -h看起来有内存但系统整个卡死。用vmstat 1观察si和so的值只要持续非零说明 swap 正在频繁活动。6.2 内存被吃光但进程列表里找不到大头用户态进程确实占用了一部分内存但有时候你ps aux --sort-%mem翻来翻去发现每个进程都不大内存却已经所剩无几。这种情况最常被忽略的是page cache和内核slab。要核实slab是否异常用cat /proc/meminfo直接看SReclaimable和SUnreclaim两个字段再用slabtop细看一下具体是哪个结构在膨胀。我遇到过几次都是内核文件系统缓存结构比如 dentry cache异常增长用echo 2 /proc/sys/vm/drop_caches配合sync可以先应急但根治还得找到具体原因比如是不是日志文件被频繁创建删除。另外共享内存也经常背锅。用ipcs -m查看 System V 共享内存段有些程序异常退出后会残留大块共享内存不释放手动ipcrm -m shmid可以清理。6.3 GPU 看不到、利用率上不去先查初始化状态有台服务器明明插着显卡nvidia-smi却提示No devices were found我用过的排查步骤是用lspci | grep -i nvidia确认系统有没有识别到 PCIe 设备没输出说明硬件层面都没枚举出来。确认驱动加载lsmod | grep nvidia没输出说明nvidia内核模块没加载考虑modprobe nvidia或重装驱动。确认显存有没有被其他进程占满fuser -v /dev/nvidia*可以看到哪些进程正在用显卡设备文件有时候上一个训练任务挂掉了僵尸进程还占着显存不释放手工 kill 掉即可。GPU 利用率上不去的另一个常见原因前面讲过就是数据管道的瓶颈。但我再补充一个容易忽略的点模型并行策略不对。比如单卡显存能装下模型时有些人非要用 DataParallel 把所有卡都放满结果通信开销极大多卡利用率加起来反而很低。这时候 GPU-Util 会显示多张卡各占一部分但整体算力产出还不如单卡。解决方法是批量数据按卡数切分或者干脆检查训练脚本里的device_ids参数。6.4 其他几个高频小问题关于 CPU 和内存的问题还有一个高频点值得单独提醒很多人问“为什么top里单进程 CPU 能超过 100%”。原因很简单这个百分比是相对单核计算的进程在 4 核机器上跑满 4 个线程显示出来就是 400%。所以看到进程 CPU 超高第一反应不是程序出 bug 了而是确认它是不是多线程程序、核数够不够用。热词里有一条特别技术向的“cellranger error: this cpu does not support avx”这本质上是 CPU 指令集不兼容的问题。新版测序分析软件默认编译了 AVX 指令集老 CPU 不支持就罢工。排查方式是lscpu查看Flags里有没有avx、avx2确认缺失的话要么换机器要么找旧版本软件。类似的道理也适用于其他需要特定指令集的计算软件——遇到“Illegal instruction”报错第一反应就是查 CPU 特性集。注意所有涉及 CPU 型号、指令集、架构的判断都要先看lscpu的Flags行。这是判断一台服务器能否运行某些计算密集型软件的最快方式比瞎猜靠谱得多。还有个常见场景是“CPU 压力测试怎么开”。很多人只是想知道服务器稳不稳定但不知道用什么标准衡量。最基本的做法是用stress工具烤机stress --cpu 8 --timeout 60表示用 8 个线程跑 60 秒纯 CPU 计算。跑的同时开top观察温度、CPU 频率和使用率如果出现温度直接顶到TjMax并伴随频率下降说明散热有问题。想更严格一点可以用prime95或者mprime跑更长时间的压力测试这类软件会专门找最耗电、最容易触发故障的计算模式。6.5 排查套路小结折腾了这些年踩过的坑我习惯总结成固定的排查流程现在整理出来分享给有需要的朋友算不上什么高深方法论但胜在稳定有效第一步永远是uptime/top看负载和整体 CPU 状态判断是 CPU 密集问题、IO 密集问题还是空载但系统异常。第二步用free -h确认内存是否告急swap使用情况是否严重如果是进入进程定位环节。第三步用iostat -x 1排除磁盘瓶颈用sar -n DEV 1排除网络瓶颈这两项往往才是“CPU不高但系统卡”的真凶。第四步如果有 GPU用nvidia-smi dmon看利用率和显存趋势区分是算力瓶颈还是数据瓶颈。最后一步整个过程中所有输出都记录下来包括时间戳。因为排查问题最关键的是“变化趋势”不是“某一瞬间的快照”。只盯着当下的top输出是判断不了怪病根因的。这套流程看起来朴素实际上解决了我的大多数线上问题。很多新手一上来就猜是不是代码写错了、是不是中病毒了反而把简单问题复杂化。任何应用层的性能问题说到底都能在系统资源层面找到对应的表征看资源、找瓶颈、再下钻顺序对了问题就已经解决了一半。7. 最后分享两个自己常用的“偷懒”技巧排查过太多服务器问题之后我的习惯是提前做两道准备工作避免每次都临时抱佛脚。第一个是写一个简单的别名集合把所有常用命令的详细输出整合一下放好在~/.bashrc里alias memtopps aux --sort-%mem | head -20 alias cputopps aux --sort-%cpu | head -20 alias gpuwatchwatch -n 1 nvidia-smi alias allstatdstat -c -d -m -n -t 5每换一台新服务器我第一件事就是把这段加进去。临时排查时少敲几个字母看起来省不了多少时间但当你连续处理好几台机器时对比效率差距能节省大半个下午。第二件事我会在服务器上常驻sysstat服务。这样万一夜里某个任务把资源打满挂掉了第二天至少能通过sar把历史曲线翻出来定位到具体时间点。我见过太多同事早上来了面对一台已经恢复正常的机器一脸茫然谁的进程也没抓到啥日志也没留下只能灰溜溜地加个重跑任务。有历史指标在手排查偶发问题的成功率完全是两个级别。最后想说一句实在话Linux 系统优化的空间永远很大但前提是你得先看清楚现状。掌握这些查看命令和排查思路不能保证你避开所有坑但至少能在出问题的时候不再对着黑乎乎的终端界面干瞪眼。遇到资源异常先冷静看再动手改——排障这事儿心态稳了就已经成功一半了。