☰
Linux stress 压测实战:CPU、内存、IO 混合场景与避坑指南
2026/10/6 19:46:30 网站建设 项目流程

简介:stress 是 Linux 平台上一款经典的开源压力测试工具,面向系统管理员、运维工程师与内核调优爱好者,用于在受控环境下模拟 CPU、内存、进程与线程的高负载场景,评估系统极限性能与稳定性。本资源为 stress-1.0.1 源码包,共 32 个文件,压缩包约 199KB,包含 configure 构建脚本、stress.c 核心源码、Makefile 系列编译文件、README/INSTALL 说明文档以及 texinfo 手册与 man 手册等,覆盖从编译安装到参数使用的完整链路。已有 3079 人学习下载,适合希望深入理解压力测试原理、自行编译定制或研究其实现细节的读者。通过阅读源码与文档,可掌握 CPU 线程压测、内存分配与释放、进程创建销毁等核心逻辑,并配合 top、vmstat 等工具观察系统在高负载下的表现,为性能调优与稳定性排查提供参考。

1. stress 压测到底在压什么:从一次 CPU 飙到 800% 的线上排查说起

线上告警说某台 4 核机器 load average 冲到 32,登录一看top里八个stress进程把 CPU 吃得干干净净。这不是故障,是我自己压的。stress这个工具在 Linux 圈子里算老面孔了,它不测磁盘 IOPS,不测网络吞吐,专门干一件事:按你指定的方式把系统资源吃到某个水位,然后看系统在高负载下会不会崩、会不会变慢、会不会触发 OOM。它解决的是「我的服务在极限情况下还稳不稳」这个问题,适合运维、后端、嵌入式 Linux 开发者做容量验证和故障复现。很多人第一次接触它是因为面试题里问「怎么模拟 CPU 满载」,但真正用起来,参数组合和观测方法才是分水岭。下面按「它怎么工作 → 怎么装怎么跑 → 参数怎么调 → 坑在哪 → 怎么进阶」的顺序讲透。

2. stress 的工作模型与安装选型:为什么它比 dd 和 yes 更适合做压测

2.1 stress 的进程模型:fork 出一堆 worker 各自干活

stress的核心逻辑很朴素:你告诉它要几个 CPU worker、几个 IO worker、几个 VM worker,它就fork()出对应数量的子进程,每个子进程进入一个死循环,按类型执行不同的系统调用。CPU worker 做的是sqrt()运算,IO worker 做的是write()和unlink(),VM worker 做的是malloc()后反复读写内存页。父进程负责监控子进程状态,收到信号后统一回收。

这个模型决定了它的两个特点。第一,压测强度是「进程数 × 单进程负载」,不是百分比,所以你在 8 核机器上跑--cpu 4和 4 核机器上跑--cpu 4,对系统的影响完全不同。第二,它不关心业务逻辑,只关心系统调用层面的资源消耗,所以用它压出来的结果反映的是内核调度和内存管理的极限,不是你的应用在真实流量下的表现。想测应用层,得用wrk、ab那类工具,stress的定位是系统级基线。

2.2 安装:包管理器一条命令,但要注意版本差异

主流发行版仓库里都有stress,安装本身没有难度:

# Debian/Ubuntu 系 sudo apt update && sudo apt install -y stress # RHEL/CentOS/Rocky 系 sudo yum install -y epel-release && sudo yum install -y stress # 验证安装与版本 stress --version

逻辑说明:stress在 EPEL 源里,CentOS 最小化安装默认没有 EPEL,所以要先装epel-release。--version输出的是版本号,老版本(如 1.0.4)和新版本(如 1.0.7)在参数支持上有差异,比如--vm-bytes的默认值不同,压内存时如果不显式指定,结果会不一致。

参数说明:-y表示自动确认,-q可以静默安装减少输出。如果你在容器里装,注意基础镜像可能是alpine,需要用apk add stress,但 alpine 仓库里的版本可能更老,建议先stress --version确认。

2.3 和 dd、yes、md5sum 压测的差别

有人用yes > /dev/null压 CPU,用dd if=/dev/zero of=/tmp/test bs=1M count=10000压 IO。这些土办法能用,但有几个硬伤。yes只能压单核,想压多核得手动起多个进程再手动 kill,没有统一的超时控制。dd压 IO 时如果没加oflag=direct,数据会走页缓存,压出来的 IO 曲线是假的。stress把这些封装成了参数:--timeout控制持续时间,--cpu N控制并发数,--hdd配合--hdd-bytes控制写入量,而且它会在结束后自动清理临时文件。做可重复的压测,用stress比手搓命令靠谱。

3. 用 stress 跑通四类压测:CPU、内存、IO、混合场景的命令与观测

3.1 CPU 压测:指定核数与超时,配合 mpstat 看每核负载

最常用的场景是验证多核 CPU 在满载时的调度表现:

# 启动 4 个 CPU worker,持续 60 秒,输出详细日志 stress --cpu 4 --timeout 60s --verbose # 另开一个终端,每秒采样一次所有 CPU 的使用率 mpstat -P ALL 1

逻辑说明:--cpu 4会 fork 出 4 个进程,每个进程绑定一个逻辑核跑满。--timeout 60s让 stress 在 60 秒后自动退出,避免忘记 kill 导致机器一直高负载。--verbose会打印每个 worker 的启动和结束信息,方便确认实际起了几个进程。mpstat -P ALL 1每秒输出一行,%usr列接近 100 说明该核被吃满,%idle接近 0 说明没有空闲。

参数说明:--cpu后面的数字建议不要超过nproc的输出值,超了会导致进程在核间频繁切换,load average 虚高但实际吞吐不增。--timeout支持s、m、h、d单位,不写单位默认秒。如果只想压特定核,用taskset -c 0,1 stress --cpu 2把 stress 绑到 0 和 1 号核上。

3.2 内存压测:vm 与 vm-bytes 的配合,盯紧 OOM killer

内存压测比 CPU 危险,因为分配过量会触发 OOM,可能杀掉你的业务进程:

# 启动 2 个 VM worker,每个分配 512M,持续 120 秒 stress --vm 2 --vm-bytes 512M --timeout 120s --verbose # 另开终端观察内存和 OOM 事件 free -m dmesg -w | grep -i "oom\|killed process"

逻辑说明:--vm 2起两个进程,每个进程通过malloc()申请--vm-bytes指定的内存,然后反复写入数据触发缺页中断和物理页分配。free -m里看available列,如果降到接近 0,说明内存压力到位了。dmesg -w实时跟踪内核日志,一旦出现Out of memory: Killed process,说明压过头了。

参数说明:--vm-bytes支持K、M、G后缀,默认单位是字节。总内存消耗约等于vm 数量 × vm-bytes,但实际会略高,因为进程本身还有栈和代码段开销。建议总分配量不超过available内存的 80%,留出余量给系统。如果要做 OOM 测试,可以故意超过,但要确保机器上没有关键业务,或者用 cgroup 限制 stress 的内存上限。

3.3 IO 压测:hdd 与 hdd-bytes 控制写入量,iostat 看 await

IO 压测主要验证磁盘在持续写入下的响应延迟:

# 4 个 IO worker,每个写 256M 临时文件,持续 90 秒 stress --hdd 4 --hdd-bytes 256M --timeout 90s --verbose # 另开终端观察磁盘指标 iostat -x 1

逻辑说明:--hdd 4起 4 个进程,每个进程在/tmp下创建临时文件并反复写入、删除。--hdd-bytes控制每个进程写入的数据量。iostat -x 1每秒输出扩展统计,重点看%util(设备利用率)和await(平均等待时间)。%util接近 100 说明磁盘饱和,await飙升说明 IO 队列积压。

参数说明:--hdd的写入路径默认是当前目录,建议先cd /tmp再执行,避免污染工作目录。如果磁盘是 SSD,%util可能不会到 100,因为 SSD 的并行度高,这时候看await和r/s、w/s更有意义。--hdd-bytes设太小会导致进程频繁创建删除文件,压出来的是元数据操作而不是数据写入,建议至少 128M 起步。

3.4 混合压测:同时压 CPU 和内存,观察系统整体表现

真实场景往往是多种资源同时吃紧,混合压测更接近线上故障:

# 2 个 CPU worker + 2 个 VM worker(各 256M)+ 2 个 IO worker stress --cpu 2 --vm 2 --vm-bytes 256M --hdd 2 --hdd-bytes 128M --timeout 180s --verbose # 综合观测 vmstat 1 10

逻辑说明:这条命令同时启动 6 个 worker,CPU、内存、IO 三线并进。vmstat 1 10每秒采样一次共 10 次,重点看r(运行队列长度)、si/so(换入换出)、wa(IO 等待占比)。如果r持续大于 CPU 核数,说明 CPU 是瓶颈;如果si/so不为零,说明内存不够开始用 swap,性能会断崖式下跌。

参数说明:混合压测的 worker 总数建议不超过nproc × 2,否则进程调度开销会掩盖真实瓶颈。--timeout设长一点,比如 180 秒,让系统有足够时间进入稳态。观测时先看vmstat的全局指标,发现异常再用pidstat定位到具体进程。

4. stress 压测的避坑与排查:五个血泪教训

4.1 压测把 SSH 压断,机器失联

现象:跑stress --cpu $(nproc)后 SSH 卡死,命令敲不进去,只能硬重启。

原因:所有 CPU 都被 stress 占满,sshd 进程抢不到时间片,网络中断处理也被延迟。

解决:永远留一个核给系统,用--cpu $(( $(nproc) - 1 ))。更稳妥的做法是用nice降低 stress 优先级:nice -n 19 stress --cpu $(nproc),这样 sshd 能优先获得调度。

4.2 内存压测触发 OOM,业务进程被误杀

现象:stress --vm 4 --vm-bytes 2G跑了几秒,MySQL 进程消失,日志里出现Killed process。

原因:stress 申请的内存超过了系统可用内存,内核 OOM killer 按评分选择牺牲品,业务进程因为占用内存多被选中。

解决:压测前用free -m确认available值,总分配量控制在 70% 以内。如果必须压到极限,用 cgroup 把 stress 限制在独立的内存组里:systemd-run --scope -p MemoryMax=2G stress --vm 2 --vm-bytes 1G,这样 OOM 只会杀 stress 自己。

4.3 IO 压测把磁盘写满,系统无法启动

现象:stress --hdd 8 --hdd-bytes 10G跑完发现/tmp满了,重启后系统卡在登录界面。

原因:stress 异常退出时临时文件没清理干净,或者--hdd-bytes设得太大,把根分区写满。

解决:压测前用df -h确认目标分区剩余空间,--hdd-bytes乘以 worker 数不要超过剩余空间的 50%。压测后手动检查ls /tmp | grep stress并清理。更安全的做法是把临时目录挂到独立分区或 tmpfs 上。

4.4 容器里跑 stress 压的是宿主机

现象:在 Docker 容器里跑stress --cpu 4,容器内top看到 4 个进程,但宿主机 load 飙升,其他容器变慢。

原因:容器默认共享宿主机的 CPU 资源,没有做 cgroup 限制,stress 消耗的是宿主机的核。

解决:启动容器时加--cpus=2限制 CPU 配额,或者用--cpu-shares设置相对权重。压测前用cat /sys/fs/cgroup/cpu.max确认容器的 CPU 上限,确保 stress 的 worker 数不超过配额。

4.5 压测时间设太长,忘记加 timeout

现象:下班前跑了个stress --cpu 8没加--timeout,第二天上班发现机器还在满载,风扇狂转。

原因:stress 默认无限期运行,不加--timeout就会一直跑下去。

解决:养成习惯,任何 stress 命令都带--timeout,哪怕设个1h也比不设强。如果已经忘了,用pkill stress或killall stress快速清理,然后uptime确认 load 回落。

5. 进阶:用 stress-ng 补位和写可复现的压测脚本

stress本身功能有限,不支持网络压测、不支持指定 CPU 亲和性、不支持统计报告。做更细的压测,我一般会切到stress-ng,它是 stress 的超集,参数更丰富:

# 安装 stress-ng sudo apt install -y stress-ng # 压 4 个核,每个核跑不同的算法,持续 60 秒,输出统计 stress-ng --cpu 4 --cpu-method all --timeout 60s --metrics-brief # 压网络:启动 2 个 TCP 客户端和 2 个服务端,走本地回环 stress-ng --sock 2 --timeout 60s --metrics-brief

逻辑说明:--cpu-method all让每个 worker 轮流使用不同的计算模式(如sqrt、trig、bitops),比 stress 单一的sqrt更能暴露 CPU 的浮点、整数、分支预测等不同单元的瓶颈。--metrics-brief在结束后输出每个 worker 的吞吐量(bogo ops/s),方便对比不同配置下的性能差异。--sock是 stress 没有的,能压本地网络协议栈。

参数说明:--cpu-method可选值有all、sqrt、trig、bitops、matrix等,all最全面但耗时最长。--metrics-brief输出的是 bogo ops,不是标准单位,只用于横向对比,不要当成绝对性能指标。

写可复现的压测脚本,关键是把参数、观测命令、清理逻辑都固化下来:

#!/bin/bash # stress_test.sh - 可复现的 CPU+内存混合压测 set -euo pipefail DURATION="${1:-60s}" CPU_WORKERS="${2:-2}" VM_WORKERS="${3:-1}" VM_BYTES="${4:-256M}" LOG_DIR="/var/log/stress_test" mkdir -p "$LOG_DIR" echo "[$(date)] 开始压测: cpu=$CPU_WORKERS vm=$VM_WORKERS vm_bytes=$VM_BYTES duration=$DURATION" # 后台启动观测 vmstat 1 "$DURATION" > "$LOG_DIR/vmstat.log" 2>&1 & VMSTAT_PID=$! # 启动 stress,超时自动退出 stress --cpu "$CPU_WORKERS" --vm "$VM_WORKERS" --vm-bytes "$VM_BYTES" \ --timeout "$DURATION" --verbose > "$LOG_DIR/stress.log" 2>&1 # 等待观测进程结束 wait "$VMSTAT_PID" 2>/dev/null || true echo "[$(date)] 压测结束,日志在 $LOG_DIR" echo "--- vmstat 摘要 ---" tail -5 "$LOG_DIR/vmstat.log"

逻辑说明:set -euo pipefail让脚本在出错时立即退出,避免压测跑一半失败还继续。vmstat在后台采样,日志落到独立目录,方便事后分析。stress的--timeout保证不会无限运行。脚本最后输出 vmstat 的尾部数据,快速判断压测期间的系统状态。

参数说明:DURATION默认 60 秒,CPU_WORKERS默认 2,VM_WORKERS默认 1,VM_BYTES默认 256M。调用时按需覆盖,比如./stress_test.sh 120s 4 2 512M。日志目录/var/log/stress_test需要写权限,普通用户跑的话改成$HOME/stress_test。

我自己的习惯是:任何压测前先nproc和free -m确认资源基线,压测中至少开两个终端分别看vmstat和dmesg,压测后检查dmesg有没有 OOM 记录、df -h有没有磁盘写满。这套流程跑下来,基本不会翻车。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询