
简介本资源为Linux系统管理员与运维开发人员必备的stress压力测试工具源码包专用于CPU与内存极限负载场景下的稳定性验证与性能调优。资源完整包含1.0.1版本源码构建体系共32个文件涵盖configure配置脚本、Makefile系列构建文件.in/.am、核心stress.c实现、文档.texi/.html/.1手册、许可证COPYING、构建辅助脚本install-sh/missing/depcomp及变更日志等全面支持从编译安装到本地化部署的全流程。压缩包仅199KB轻量精简适配各类Linux发行版快速集成。目前已有1037人学习下载读者可直接获取可编译的原始工程结构、标准化GNU Autotools构建链、完整手册与测试用例掌握高可控性压力测试参数组合如--cpu/--vm-bytes、监控协同方法及安全终止机制是深入理解系统资源边界与夯实压测实践能力的可靠基础素材。1. stressLinux 下最轻量却最容易翻车的压测工具装错版本连 CPU 都跑不满你有没有试过在一台新配的 32 核服务器上跑stress --cpu 32结果 top 里最高只看到 800% 的 CPU 占用即 8 核满载其余核心纹丝不动或者更玄学的是明明加了--timeout 60程序却卡死在第 47 秒不退出kill -9都得连发三次才响应这不是硬件问题大概率是你手里的stress不是官方主线版而是某个发行版仓库里打了补丁、阉割了线程调度逻辑的“定制魔改版”。stress看似只有单个二进制文件、不到 200KB但它对内核调度器、cgroup 版本、甚至 glibc 线程栈默认大小都极其敏感。我见过某高校实验室用 Ubuntu 20.04 自带的 stress 1.0.4 测试容器资源限制结果所有--io子测试全部静默失败——因为那个版本压根没链接libaio而错误日志里连 warning 都不打。它不是玩具而是 Linux 系统稳定性验证的第一道门槛适合刚接触性能测试的运维新人快速上手也适合资深工程师做回归基线比对但前提是——你得知道该装哪个 commit、从哪编译、绕开哪些发行版包管理器埋下的坑。2. 下载与编译为什么必须自己编译而不是apt install stress提示Debian/Ubuntu 的stress包如 Ubuntu 22.04 的 1.0.4-5默认禁用--hdd和部分--io功能CentOS 7 的stress1.0.2 甚至不支持--vm-bytes精确控制内存分配粒度。生产环境压测宁可多花 3 分钟编译也不要赌包管理器的良心。2.1 确认系统基础依赖glibc、make、gcc 编译链版本底线stress主线要求最低 glibc 2.17对应 CentOS 7 / Ubuntu 14.04但实际踩坑发现若目标机器是较老的嵌入式 Linux 或定制内核需额外确认sys/syscall.h中是否定义了SYS_getrandom用于熵池初始化。编译前务必执行# 检查关键符号是否存在无输出即通过 nm -D /lib64/libc.so.6 | grep -q getrandom echo ✅ getrandom syscall available || echo ⚠️ may fail on entropy init # 确认 gcc 版本stress 1.0.6 需 GCC 4.8旧版可降级到 1.0.4 gcc --version | head -n1 # 输出示例gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 → 完全兼容若gcc --version显示低于 4.8如 CentOS 6 默认 4.4.7则必须升级 devtoolset 或改用预编译静态二进制见 2.3 节。此处不推荐强行用-stdgnu99降标编译——某些__atomic内建函数调用会静默失效导致--cpu子进程 fork 后无法正确同步状态。2.2 从 GitHub 官方源码编译推荐stress 1.0.62023 年最新稳定版官方仓库地址https://github.com/ColinIanKing/stress注意不要 clone master 分支当前 master 已进入 1.0.7 开发期包含未合入的 cgroup v2 实验性支持但在多数生产内核5.10/5.15下会导致--io测试随机 hang 死。稳定选择是stress-1.0.6tag# 清理可能残留的旧构建 rm -rf stress-build mkdir stress-build cd stress-build # 下载指定 tag 源码避免 git clone 全量历史 wget https://github.com/ColinIanKing/stress/archive/refs/tags/stress-1.0.6.tar.gz tar -xzf stress-1.0.6.tar.gz cd stress-stress-1.0.6 # 配置编译选项启用所有子测试 静态链接规避 libc 版本冲突 ./configure \ --prefix/usr/local \ --enable-all-tests \ # 强制开启 hdd/io/vm-hugepage 等非常规测试 LDFLAGS-static \ # 关键生成静态二进制杜绝运行时 libc 不兼容 CFLAGS-O2 -marchx86-64 # 优化指令集避免在老 CPU 上报 illegal instruction # 编译-j$(nproc) 加速但内存 4GB 时建议 -j2 make -j$(nproc) # 安装到 /usr/local/bin/stress非 /usr/bin避免覆盖发行版包 sudo make install编译成功后验证# 检查是否为静态链接 ldd /usr/local/bin/stress # 正确输出应为not a dynamic executable # 检查功能列表确认 hdd/io 已启用 /usr/local/bin/stress --help | grep -E (hdd|io|vm-hugepage) # 应出现--hdd N spawn N workers spinning on sync(), --io N spawn N workers spinning on I/O, ...2.3 替代方案直接下载预编译静态二进制无 root 权限场景若服务器禁止安装编译工具链如某些金融客户受限环境可使用项目维护者提供的 CI 构建产物。访问 GitHub Actions 的 latest release 页面https://github.com/ColinIanKing/stress/releases/tag/stress-1.0.6下载stress-static-x86_64文件# 下载并赋予执行权限注意校验 SHA256 curl -L -o stress-static https://github.com/ColinIanKing/stress/releases/download/stress-1.0.6/stress-static-x86_64 chmod x stress-static # 快速验证能否启动且不报 missing library ./stress-static --version # 输出stress-ng 1.0.6 # 临时使用不安装 ./stress-static --cpu 4 --timeout 10s注意此二进制由 Ubuntu 20.04 GCC 10.3 构建兼容 glibc 2.17 内核。若遇到FATAL: kernel too old错误请改用 stress-1.0.4 的静态版其内核 ABI 兼容性更宽泛。2.4 验证编译结果检查 stress 是否真正识别到全部 CPU 核心很多用户以为stress --cpu 32就是压满 32 核其实stress默认按逻辑 CPU 数即超线程后的 core × thread分配 worker。需先确认系统真实拓扑# 查看物理核心数与逻辑处理器数 lscpu | grep -E (CPU\(s\)|Core\(s\) per socket|Socket\(s\)) # 示例输出 # CPU(s): 32 # Core(s) per socket: 16 # Socket(s): 2 # stress 会创建 32 个独立进程每个绑定一个逻辑 CPU但若未显式设置 --cpu-method可能因调度策略导致负载不均 # 验证方法启动后立即观察各核心负载 /usr/local/bin/stress --cpu 32 --timeout 20s stress_pid$! sleep 2 # 用 pidstat 按核心查看实时占用需安装 sysstat pidstat -t -p $stress_pid 1 5 | grep stress | awk {print $8} | sort | uniq -c # 若输出中某核心出现频率远高于其他如 10 CPU01 而其余为 1 CPU02说明调度异常需配合 taskset 使用见 3.2 节3. 核心参数详解与典型压测场景配置stress的参数设计看似简单但每个开关背后都关联着内核子系统行为。例如--vm不只是分配内存它触发的是 page fault → alloc_pages → buddy allocator 一整条路径--io则直连 block layer 的 I/O scheduler。理解参数本质才能避开“压了等于没压”的陷阱。3.1 CPU 压力--cpu与--cpu-method的组合玄学--cpu N创建 N 个计算密集型进程但每个进程内部的计算方式由--cpu-method决定。默认all方法会轮询多种算法sqrt,sin,exp但实测发现在 AMD EPYC 7742 上sqrt方法因 FPU 寄存器竞争导致单核利用率仅 70%而bitops方法位运算可稳定拉到 99%# 对比测试同一台机器分别用不同 method 压单核 time /usr/local/bin/stress --cpu 1 --cpu-method sqrt --timeout 30s /dev/null 21 # real 0m30.123s time /usr/local/bin/stress --cpu 1 --cpu-method bitops --timeout 30s /dev/null 21 # real 0m30.005s 更稳定无抖动 # 生产建议固定 method 避免不可控波动 /usr/local/bin/stress --cpu 16 --cpu-method bitops --timeout 120s注意--cpu-method可选值包括all,sqrt,sin,exp,float,int,bitops,matrix,hanoi。其中matrix矩阵乘法对 cache line 冲突最敏感适合测试 NUMA 亲和性hanoi汉诺塔递归深度大易触发栈溢出——若系统ulimit -s设置过小如 8192 KB会导致进程被 SIGSEGV 终止。3.2 内存压力--vm的三种模式与 OOM Killer 触发逻辑stress --vm N默认创建 N 个进程每个分配256MB内存可调。但内存分配行为分三层参数组合行为说明适用场景--vm 4 --vm-bytes 1G每个进程 mmap 1GB 匿名内存立即分配物理页MAP_POPULATE测试内存带宽极限触发 swap--vm 4 --vm-bytes 1G --vm-keepmmap 后调用mlock()锁住内存阻止 swap测试 locked memory 限制RLIMIT_MEMLOCK--vm 4 --vm-bytes 1G --vm-hang 5分配后每 5 秒 touch 一次页面延迟触发 page fault模拟渐进式内存泄漏# 场景测试 OOM Killer 是否正常工作需提前关闭 swap sudo swapoff -a # 启动内存压测4 进程 × 2GB 8GB超过系统可用内存 /usr/local/bin/stress --vm 4 --vm-bytes 2G --vm-keep --timeout 60s # 观察 dmesg 是否出现 Out of memory: Kill process ... dmesg -T | tail -20 | grep -i oom\|kill3.3 I/O 压力--io与--hdd的本质区别这是最多人混淆的点--io是异步 I/O 压力基于 libaio直接向块设备提交 I/O 请求绕过 page cache--hdd是同步文件 I/O 压力open/write/fsync重度依赖 page cache 和 dirty_ratio。二者触发的内核路径完全不同# --io 测试需确保 libaio 已安装 sudo apt install libaio1 # Ubuntu/Debian sudo yum install libaio # CentOS/RHEL # 创建 4 个异步 I/O worker每个持续提交 4KB 随机写 /usr/local/bin/stress --io 4 --hdd-bytes 4K --hdd-noclean --timeout 30s # --hdd 测试纯文件操作更贴近数据库日志写入 # 在 /tmp 下创建临时文件避免影响系统盘 mkdir -p /tmp/stress-hdd /usr/local/bin/stress --hdd 4 --hdd-dir /tmp/stress-hdd --hdd-bytes 1G --timeout 30s排查提示若--io执行后iostat -x 1显示%util为 0检查是否加载了aio内核模块lsmod | grep aio或libaio版本过低需 ≥ 0.3.110。3.4 混合压测用--backoff控制压力梯度避免瞬时雪崩真实业务负载是渐进式的。stress提供--backoff参数让 worker 在完成一轮计算后休眠指定微秒从而模拟“请求洪峰”# 模拟 Web 服务压力每 10ms 处理一次请求等效 100 QPS # CPU worker 每次计算 1ms然后 backoff 9ms /usr/local/bin/stress --cpu 8 --cpu-method bitops --backoff 9000 --timeout 60s # 验证效果用 pidstat 观察 CPU 使用率是否稳定在 ~10% pidstat -u 1 60 | awk $8 ~ /^[0-9]\.?[0-9]*$/ $8 0 {sum $8} END {print Avg CPU%:, sum/NR}4. 常见问题排查5 个血泪经验总结的必踩坑点4.1 现象stress --cpu 32启动后htop显示只有 16 个进程且 CPU 占用率不足 50%原因系统启用了cpusetcgroup常见于 Kubernetes 节点或 systemd 服务隔离stress进程被限制在部分 CPU 集合内。stress默认不主动读取 cgroup 配置而是依赖内核调度器分配但若 cgroup.allowed_cpus 为空或范围过窄fork 出的子进程会被自动迁移到允许的 CPU 上导致数量减半。解决# 检查当前进程的 cgroup CPU 限制 cat /proc/$$/cgroup | grep cpuset # 若输出类似 8:cpuset:/kubepods/burstable/pod...则进入对应路径 cat /sys/fs/cgroup/cpuset/kubepods/burstable/pod*/cpuset.cpus # 临时解除限制需 root echo 0-31 | sudo tee /sys/fs/cgroup/cpuset/kubepods/burstable/pod*/cpuset.cpus # 或启动 stress 时显式绑定全部 CPU taskset -c 0-31 /usr/local/bin/stress --cpu 324.2 现象stress --io 4执行数秒后报错fio: io_u error on file ...: No such file or directory原因--io模式需要/dev/zero或/dev/null作为 I/O 目标设备但某些最小化系统如 Alpine未挂载devtmpfs导致/dev/zero不存在。解决# 检查 /dev/zero 是否存在且可读 ls -l /dev/zero # 若不存在手动挂载 devtmpfs需 root sudo mount -t devtmpfs none /dev # 或改用 --hdd 模式替代文件系统 I/O /usr/local/bin/stress --hdd 4 --hdd-dir /tmp --hdd-bytes 1G4.3 现象stress --vm 8 --vm-bytes 4G启动后立即被 OOM Killer 杀死但free -h显示仍有 10GB 空闲内存原因内核vm.overcommit_memory设置为2严格模式此时overcommit_ratio默认 50限制了可分配虚拟内存总量。计算公式CommitLimit SwapTotal (RAM * overcommit_ratio / 100)。若无 swapCommitLimit ≈ RAM × 0.54G × 8 32G 远超限制。解决# 临时放宽重启失效 echo 1 | sudo tee /proc/sys/vm/overcommit_memory # 启用 heuristic overcommit # 或永久修改写入 /etc/sysctl.conf echo vm.overcommit_memory 1 | sudo tee -a /etc/sysctl.conf sudo sysctl -p4.4 现象stress --hdd 4在 XFS 文件系统上运行缓慢iostat显示%await高达 200ms原因XFS 默认启用allocsize64k而stress的--hdd-bytes默认 1G导致大量小文件碎片写入。XFS 的 extent allocation 在高并发小写时性能骤降。解决# 创建大块连续空间的临时目录XFS 推荐 sudo mkfs.xfs -f -d agcount32 /dev/loop0 sudo mount /dev/loop0 /mnt/stress-hdd # 启动 stress 指向该目录 /usr/local/bin/stress --hdd 4 --hdd-dir /mnt/stress-hdd --hdd-bytes 2G4.5 现象stress --timeout 30s到时后进程未退出ps aux | grep stress显示状态为Duninterruptible sleep原因--io或--hddworker 正在等待慢速存储如 NFS、机械硬盘的 I/O 完成内核将其置为 D 状态此时SIGTERM无法中断。解决# 启动时添加 --verbose 获取详细日志定位卡在哪个系统调用 /usr/local/bin/stress --io 2 --verbose --timeout 30s 21 | grep -E (io_submit|fsync|write) # 强制终止先 kill 用户态进程再 kill 内核态等待 pkill -f stress.*io # 终止主进程 # 若仍有 D 状态残留需等待 I/O 自行完成无法强制 # 预防避免在慢速存储上运行 --io改用 --hdd tmpfs5. 验证压测结果用三类指标交叉验证是否真正在“压”装完stress只是第一步关键是要证明它真的在按预期施加压力。我从不只看top里的 CPU%而是用三类指标交叉验证内核态行为是否触发目标子系统、资源消耗是否达到设定阈值、业务影响是否引发预期副作用。下面给出一套可直接复用的验证脚本和判断逻辑。5.1 验证 CPU 压力捕获 perf event 确认计算路径stress --cpu的本质是让 CPU 执行大量算术指令。用perf抓取cycles和instructions事件可确认是否真正在计算# 启动 CPU 压测后台运行 /usr/local/bin/stress --cpu 4 --cpu-method bitops --timeout 60s # 立即用 perf 监控需提前安装 linux-tools sudo perf stat -e cycles,instructions,cache-references,cache-misses -p $! sleep 10 # 正常输出应类似 # Performance counter stats for process id 12345: # 12,345,678,901 cycles # 24,691,357,802 instructions # 2.00 insn per cycle # 1,234,567,890 cache-references # 12,345,678 cache-misses # 1.00% of all cache refs # # 若 instructions/cycles 接近 2.0说明 CPU 流水线高效利用若 1.0可能是内存等待cache-misses 高或分支预测失败。5.2 验证内存压力检查 page fault 与 swap activity真正的内存压力会引发大量 minor/major page fault。用pidstat和vmstat联合观测# 启动内存压测 /usr/local/bin/stress --vm 4 --vm-bytes 2G --vm-keep --timeout 60s # 并行监控每秒采样 pidstat -r -p $! 1 60 | awk $1 ~ /^[0-9]:[0-9]:[0-9]$/ $5 ! kB {print Minor PF:, $5, Major PF:, $6} vmstat 1 60 | awk $1 ~ /^[0-9]$/ {print pgpgin:, $8, pgpgout:, $9, pswpin:, $10, pswpout:, $11} # 判断标准 # - Minor PF次要缺页应 10000/s表示频繁分配新页 # - Major PF主要缺页应 ≈ 0--vm-keep 锁内存避免 swap # - pswpin/pswpout 应为 0确认未触发 swap5.3 验证 I/O 压力用 iostat blktrace 定位 I/O 类型--io和--hdd的 I/O 特征截然不同用iostat的r/s读请求数和w/s写请求数可区分模式r/sw/sawait (ms)说明--io 4~05000 1异步写直接发往 block layer无读操作--hdd 410001000 10同步读写大量 read() write() fsync()# 启动 I/O 压测 /usr/local/bin/stress --io 4 --timeout 30s # 用 iostat 观察聚焦 nvme0n1 或 sda iostat -x -d nvme0n1 1 30 | awk $1 ~ /^nvme0n1$/ {print r/s:, $4, w/s:, $5, await:, $10} # 若 w/s 3000 且 r/s ≈ 0则 --io 生效若 r/s 和 w/s 均高则可能是 --hdd 模式误用。5.4 综合验证脚本一键运行并输出健康报告将上述验证逻辑封装为stress-validate.sh每次压测后运行即可获得结构化结论#!/bin/bash # stress-validate.sh —— stress 压测健康检查脚本 STRESS_PID$1 if [ -z $STRESS_PID ]; then echo Usage: $0 stress-pid exit 1 fi echo Stress Validation Report for PID $STRESS_PID echo 1. CPU Path Check: sudo perf stat -e cycles,instructions -p $STRESS_PID sleep 5 21 | grep -E (cycles|instructions) echo -e \n2. Memory Pressure: pidstat -r -p $STRESS_PID 1 5 | tail -1 | awk {print Minor PF:, $5, Major PF:, $6} echo -e \n3. I/O Pattern: iostat -x 1 5 | awk -v pid$STRESS_PID $1 ~ /^nvme|^sd/ $4$5 100 { printf %s: r/s%.0f w/s%.0f await%.1f\n, $1, $4, $5, $10 } echo -e \n4. Process State: ps -o pid,ppid,comm,state,time -p $STRESS_PID | tail -1用法/usr/local/bin/stress --cpu 4 --timeout 30s stress-validate.sh $!从那以后我每次部署新环境都强制走一遍stress-validate.sh—— 不是信不过自己编译的二进制而是信不过那些藏在 cgroup、内核参数、文件系统特性里的黑匣子。压测不是为了把机器搞垮而是为了搞清它在哪种压力下会垮、怎么垮、垮之前有什么征兆。希望帮到你。本文还有配套的精品资源点击获取