☰
Linux离线压力测试入门:stress工具rpm安装与压测实战
2026/10/21 8:10:28 网站建设 项目流程

简介:面向 CentOS 及其他 Linux 发行版运维、测试人员的离线压力测试工具安装包,解决无法联网环境下 stress 工具难以部署的问题,同时兼顾 sar 命令的使用需求,适合需要快速开展 CPU、内存等负载压测的场景。整包共 43 个文件,大小约 46.66MB,以 11 个 rpm 安装包为核心,辅以 configure、am、m4 等构建脚本、c 源码以及 texi/info/html 文档,既可直接安装,也保留了源码编译的可能。已有 2592 人学习下载,属于常见基础工具资源。通过该资源可完成 stress-1.0.4 的离线部署,借助 sar 监控压力下的系统表现,并参考 readme、news、changelog 理解版本变化与使用细节。

1. 离线 rpm 选型:为什么内网压测第一件事是装 stress

当一台不联网的 CentOS 服务器摆在面前,你想快速确认 CPU 或内存能不能顶住高峰时,最省事的工具不是 sysbench,也不急着源码编译,而是先装一个体积不到 1MB 的 stress。我接到的很多 linux 压力测试任务,第一件事都是找同版本内网机器导出一份 stress 的 rpm 包,传到目标机用 rpm -ivh 安上。它没有守护进程、不依赖 yum 源,装完直接在命令行里跑,行为足够透明。

stress 的设计目的很单一:通过 fork 子进程制造可控压力,把机器推到指定载荷水位。它不模拟业务、不测 TPS、不生成完整报告,但压测第一阶段需要的恰恰是这套最小工具。拿到负载水位后,再用 top、vmstat、sar 判断瓶颈是 CPU 算力不足、内存带宽受限,还是磁盘 IO 顶不住。对内网环境做环境验证、上线前基线测试、容器过载演练,stress 都是最快见效的离线方案。

2. 离线安装:依赖预检、rpm 获取与安装落地

2.1 先搞清楚 stress 依赖什么,避免在安装阶段翻车

离线安装的第一个判断点是依赖面有多宽。stress 是 C 写的,运行时只依赖 glibc,具体到动态链接库就是 libc.so.6,所以它的 rpm 依赖列表通常很短。你在 CentOS 7 上看到的 stress rpm,要求一般是这样的:

rpm -qp --requires stress-1.0.4-15.el7.x86_64.rpm

这条命令直接读取 rpm 包的依赖需求,不安装也能查。常见输出除了 libc.so.6,还会带 GLIBC_2.14 这类版本标记。

拿到需求后,把它和目标机器的 glibc 版本对比。用 getconf 和 rpm 一起看:

getconf GNU_LIBC_VERSION rpm -qa | grep -i glibc

第一行显示当前 glibc 的运行版本,第二行列出已安装的 glibc 相关包。如果系统是 glibc 2.17,rpm 要求 GLIBC_2.14,那没问题,因为 glibc 的符号版本向后兼容,2.17 可以满足 2.14 的需求。如果系统是 2.12,就会报缺 GLIBC_2.14,这种情况下别硬上,换一个需求更低的 stress 包,或者找对应旧发行版编译的版本。

这里要强调一个原则:不要把 rpm 的依赖报错立刻交给 --nodeps 处理。--nodeps 绕过的是 rpm 层面的文件依赖检查,绕不过运行时的动态链接失败。我见过有人把 CentOS 8 的 stress 装到 CentOS 7 上,安装阶段侥幸通过,一运行就报段错误,后面排查花的力气远大于重新下一个包。

在准备离线包之前,把下面信息先记下来:

uname -m cat /etc/redhat-release

uname -m 给 CPU 架构,redhat-release 给发行版主版本。这两个值直接决定你要找的是 el7 x86_64 还是 el8 aarch64 的包。架构不对,rpm 会在安装时明确提示架构冲突;发行版不对,依赖版本经常对不上。

2.2 三种获取 rpm 的方式,从联网机器到内网迁移

离线环境里没有 yum 源,但可以通过另外几台机器把 rpm 包搭出来。

第一种方式,找一台和目标机同样发行版、同样架构、能联网的机器,用 yumdownloader 把 stress 和它的依赖一起抓下来:

yum install -y yum-utils yumdownloader --resolve stress

--resolve 会让 yumdownloader 把依赖一并下载。下载目录下会多出几个 rpm 文件,用 ls 看看属于哪些包。把这一串文件传到目标机,安装时一并指定给 rpm,rpm 会自行按依赖顺序处理。注意这里要求两台机器的发行版大版本一致,小版本差异通常问题不大,但如果盲目用 CentOS 6 的包装到 CentOS 7 上,前面说的 GLIBC 问题就会出现。

第二种方式,从另一台已经装好 stress 的同版本服务器上查询包安装情况,这种方法适合确认目标机器上哪个版本可用:

rpm -qa | grep stress rpm -ql stress

第一条命令查询包名是否已安装,第二条查看它安装了哪些文件。严格来说 rpm -ql 只能给你文件路径,不能反过来生成 rpm 包。想把已安装的包还原成可再分发的 rpm,需要 yumdownloader 或 rpmbuild 这类工具才能完成,这里提一句避免误操作。

第三种方式,是提前在联网机器上用 yum 的缓存特性把包存下来,然后打包带到内网。例如:

yum install --downloadonly --downloaddir=/opt/stress_rpm stress

--downloadonly 和 --downloaddir 组合使用,会把 stress 及依赖全部存到指定目录,不触发实际安装。这种方式的好处是保留 yum 的版本解析结果,得到一组一致可用的 rpm。文件传完后,用 sha256sum 做一次完整性校验:

sha256sum /opt/stress_rpm/*.rpm

拿校验值和源端对比,能提前发现传输损坏。虽然 rpm 包本身有内部校验,但很多时候 rpm 报错提示不够明确,很难一眼认出是文件损坏。

2.3 rpm 安装实操:一条命令到底

文件备齐后,在目标机上安装:

rpm -ivh stress-1.0.4-15.el7.x86_64.rpm

如果没有任何依赖报错,进度条走完就算成功。安装后验证:

stress --version

能看到 stress version 1.0.4 之类的输出。

如果下载了多个依赖包,最好把文件全部列在一条命令里:

rpm -ivh lib*.rpm stress*.rpm

这样 rpm 会先整体解析所有包的依赖关系,再按依赖顺序安装,而不是按照命令行里罗列的顺序。它能自动把被依赖的包装在前面。

安装完成后,确认命令路径:

which stress

正常返回 /usr/bin/stress。如果机器上以前装过源码版 stress,实际生效的可能是 /usr/local/bin/stress,这时要看 PATH 顺序,确认你到底调用的是哪一个。用 rpm 版覆盖源码版之前,建议先把源码版备份,避免排查时连版本都对不上。

2.4 架构与 glibc 匹配检查:安装前省十分钟,安装后省两小时

再细说一遍匹配检查,因为这是离线 rpm 安装里最常出问题的环节。

uname -m

输出 x86_64 就找 x86_64 的包,输出 aarch64 就找 aarch64 的包。rpm 包名里通常带架构后缀,比如 stress-1.0.4-15.el7.x86_64.rpm,其中的 x86_64 就是架构标记。如果包名里写的是 noarch,说明它是跨架构的脚本或数据包,不在此讨论范围内。

接下来看 glibc 需求:

rpm -qp --requires stress-1.0.4-15.el7.x86_64.rpm | grep GLIBC

如果结果显示的是 GLIBC_2.14,而机器上 getconf GNU_LIBC_VERSION 输出 2.17,说明满足需求。如果输出 2.12,则这条依赖不满足。这种情况下,1.0.4 这个 rpm 不适合直接装,要找针对更老系统的版本。

还有一种情况是 rpm 命令提示依赖检测失败,但看不出缺哪个具体符号。这时加 --test 先跑一次演练,不实际安装:

rpm -ivh --test stress*.rpm

它能帮你把缺失的依赖列全,而且不会动系统。这是我准备在生产机上安装任何离线 rpm 前必做的一步。

3. 参数实战:CPU、内存、磁盘压测与系统观测

3.1 CPU 压测:nproc 确认核数后分配给 stress

CPU 压测是 stress 场景里最直接的。先确认机器逻辑核数:

nproc

然后让 stress 按满载目标分配 worker。想要压满 4 核:

stress --cpu 4 --timeout 60

--cpu 代表启动的 worker 进程数,--timeout 是过期时间,单位秒。这样 60 秒后 stress 会自动结束,避免压测后忘记收尾。

查看压力是否到位:

uptime

如果 load average 持续大于核数,说明压力已经制造出来了。如果想更精确看每个 worker 的状态,用 top 进入进程视图,观察几个 stress 进程的 %CPU 总和是否接近 100 乘核数。

不过这里有一个容易忽略的细节:当用 stress --cpu 8 去压一台超线程机器时,8 个 worker 会在超线程上分时执行,负载可能比预想高不少。所以压测前我先确认超线程状态:

lscpu | grep "Thread"

如果 Thread(s) per core 是 2,说明超线程开启,8 核机器实际有 16 个逻辑核。此时要把 --cpu 设成 16 才让逻辑核全忙,只压 8 个逻辑核的话,load average 大概在 8 左右,CPU 使用率只在 50% 上下,看起来像是没压透。

3.2 内存压测:--vm 与 --vm-bytes 的参数逻辑

内存压测和 CPU 压测的差别在于要控制总量,不能盲目分配。参数结构是:

stress --vm 4 --vm-bytes 2G --vm-hang 30

--vm 是并发 worker 数,--vm-bytes 是每个 worker 分配的内存块大小,--vm-hang 表示分配后保持占用多少秒。以上命令会启动 4 个进程,每个分配 2G 内存,总共 8G,然后在内存里挂起 30 秒。

想要压一台 64G 内存的机器,先预留出系统本身最少需要的内存,比如 4G,剩下的 60G 再分给 worker。如果用 8 个 worker,每个分配 7G:

stress --vm 8 --vm-bytes 7G --vm-hang 60

注意 --vm-bytes 如果写得太接近实际物理内存总量,会触发 OOM 或系统换页,把整台机器拖到卡死。内存分配完,用 free -g 看内存水位:

free -g

available 那一行降到很低时,说明内存压力已经制造完成。

还有一个常见误用:--vm-hang 不设或者设为 0 时,stress 会快速 malloc 然后释放,不断重复,内存使用率会在低水位附近跳动,看起来像压力不足。其实那是它在反复分配又释放。想要稳定观察内存水位,把 --vm-hang 设大一点,比如 60 秒,保留足够观察窗口。

3.3 磁盘压测:--hdd 的副作用

磁盘压测是 stress 里最需要谨慎的部分。stress 的磁盘 worker 行为如下:

stress --hdd 2 --hdd-bytes 2G

这个命令创建 2 个磁盘 worker,每个 worker 不断创建临时文件并写满 2G 后删除,再重新创建。文件默认落在临时目录,通常是 /tmp。对于挂载 tmpfs 的 /tmp 机器,这个命令实际压的是内存而不是磁盘,要先用 df -h /tmp 确认挂载类型再做判断:

df -h /tmp

如果输出 tmpfs,说明它跑在内存里,磁盘压测结果毫无意义。这种情况下要指定工作目录:

stress --hdd 2 --hdd-bytes 2G -d /data

-hdd-verify 这个参数可以额外加上,它会让 worker 在写完文件后重新读取校验数据,提高 IO 压力。另一个注意点是目录空间:压测前先用 df -h 确认目标分区剩余空间,确保大于 --hdd-bytes 乘以 worker 数。比如两个 worker 各写 2G,分区至少要留 5G 以上,因为连续读写会产生临时文件叠加。

在线上机器压磁盘之前,我先用 iostat 看一眼当前 IO 水位:

iostat -x 1 5

如果 %util 已经接近 90%,则不适合再叠加压力,要先把业务流量控制在低峰再动手。主要原因是 stress --hdd 对系统的影响不仅是磁盘吞吐,还会把页缓存和内核写回线程一起拉满,SSH 超时、日志采集延迟、数据库 checkpoint 变长这些连锁反应都会出现。

3.4 用 vmstat 与 top 读压测现场的实时指标

压测进行时,单看 load average 不够,需要配合 vmstat 观察运行队列和 IO 等待。常用一条固定采样命令:

vmstat 2 10

每隔 2 秒采一次,共 10 次。输出的关键列有 r、b、si、so、wa。r 是运行队列长度,如果持续大于 CPU 核数,说明 CPU 已经满载;b 是阻塞进程数,持续非零说明 IO 卡了;si、so 是换入换出量,内存压测时可以观察是否在疯狂 swap;wa 是 IO 等待时间占比。

同时用 top 看进程状态:

top -d 2

在进程列表里,R 状态表示运行中,D 状态表示不可中断睡眠,通常是在等 IO。如果看到大量 stress 进程处于 D 状态,说明压力已进入磁盘领域,结论就明确了。

压测结束后,可能有子进程残留。这种情况下的处理手段是,先用 pgrep 列出所有 stress 进程:

pgrep -a stress

然后按 pid 逐个结束:

pkill -9 stress

不过 pkill -9 是强杀,stress 的子进程可能来不及清理临时文件就退出,所以日常操作中更推荐在启动时就用 --timeout 让进程自己结束,避免用强杀手段收尾。

4. 结果解读:把压测数据变成可交付的判断

4.1 区分 CPU 使用率与 CPU 负载:压测结果最容易误读的地方

压测后拿到一堆数据,第一件事是区分两个概念:CPU 使用率与 load average。使用率看的是 CPU 在单位时间内有多少时间片被占用,来自 top 或 /proc/stat;负载看的是处于运行或不可中断状态的进程平均数量,来自 uptime 或 /proc/loadavg。

比如一台 4 核机器,CPU 使用率 100%,load average 只有 4,这是健康满载;如果 CPU 使用率只有 50%,load average 却到了 8,说明进程大量排队等待非 CPU 资源,可能是磁盘 IO 或锁竞争,此时 CPU 反而不是瓶颈。压测时最容易犯的错是只看单指标,看到 CPU 高就断言 CPU 瓶颈,实际可能是磁盘把进程阻塞住,进程还在运行队列里堆积。

4.2 用 sar 记录趋势:实时观察和留存分析缺一不可

stress 压测通常要持续几分钟甚至半小时,只看实时数据很难判断系统是不是在缓慢劣化。我一般在压测前就启动 sar 后台采集:

sar -u 2 600 -o /tmp/sar_cpu.log > /dev/null 2>&1 &

这条命令每隔 2 秒采集 CPU 数据,共 600 次,大约 20 分钟,并把结果写入 /tmp/sar_cpu.log。等压测结束后,用 sar 读取汇总:

sar -u -f /tmp/sar_cpu.log

输出会按时间列出 %user、%sys、%iowait 等列,能清楚看到压测开始点和结束点的趋势变化。这里的 sar 是否可用,取决于 sysstat 包是否已安装。离线系统如果没装,可以提前从依赖源准备 sysstat 的 rpm,否则只能退回到持续运行的 top 命令配合重定向记录。

另一种做法是直接写一个循环,定时把指标追加到文本文件:

for i in $(seq 1 100); do top -bn1 >> /tmp/top_snapshot.log vmstat 1 2 >> /tmp/vmstat_snapshot.log sleep 2 done

这个命令循环 100 次,每次抓取 top 和 vmstat 快照并追加到日志。缺点是日志会迅速变大,100 次大约几十 MB,最好在压测结束后直接打包保存。

4.3 压测报告的指标选取:交付时让看的人一眼抓住重点

压测结束后,我通常整理一张表格,把几项关键指标按不同压测阶段汇总,而不是把一堆原始日志丢给决策人。表格字段大概是这样:

压测阶段持续时间运行队列%CPU%iowait内存可用结论
CPU 压测 4 核5 分钟4.295112GCPU 容量紧张
CPU 压测 8 核5 分钟8.699210GCPU 满载,进程排队明显
内存压测 32G5 分钟3.13000G内存分配压力到上限
磁盘压测 2 worker5 分钟6.225808G磁盘 IO 成为瓶颈

这张表格能用三行话讲清楚结论:5 分钟压测内,运行队列持续大于可用核数,CPU 使用率保持 95% 以上,且没有触发 OOM,说明 CPU 密集场景下机器容量偏紧。读表的人不需要理解 stress 具体参数,也能判断这台机器适合放什么样的业务。

4.4 压测进程收尾与数据备份:不要给生产环境留尾巴

压测结束后的收尾动作比启动更重要。每次压测结束后,我固定做三件事:确认所有 stress 进程退出,备份压测产生的临时数据,记录压测时间和命令参数。

确认进程退出的命令:

pgrep -a stress || echo "no stress process"

如果还有残留,用 pkill 结束掉。备份数据指的是把 vmstat、sar、top 记录文件归档,因为压测报告往往当天出不完,归档后方便第二天续写。命令参数通常直接写在压测脚本里,便于追溯负载来源。

归档命令:

mkdir -p /var/log/stress_test/$(date +%Y%m%d) cp /tmp/*.log /var/log/stress_test/$(date +%Y%m%d)/

这样做的好处是,当压测结果后面被质疑机器配置有问题时,可以回溯当时压测命令和指标记录,而不是靠记忆。

5. 避坑排查:离线 stress 最常见的五类翻车现场

5.1 现象:rpm 提示缺 GLIBC_2.14,--nodeps 硬装后段错误

现象:rpm -ivh 安装 stress 时报错“需要 libc.so.6(GLIBC_2.14)(64bit)”,安装者图省事加了 --nodeps 继续装,rpm 装完后运行 stress --version 直接段错误。

原因:stress 可执行文件里用到了较新版本的 glibc 符号,而系统 glibc 版本过老,无法解析这些符号。rpm --nodeps 只跳过文件依赖检查,不会改变运行时的动态链接结果。

解决:不要用 --nodeps 硬装。先查看目标机的 glibc 版本,getconf GNU_LIBC_VERSION,如果低于 rpm 包需求的最大 GLIBC 版本,就换一个面向更老系统的 stress rpm。能用 --test 预检就先预检,rpm -ivh --test stress*.rpm 可以在不安装的情况下把依赖冲突完整列出来。

5.2 现象:CPU 压测跑起来了,但 %CPU 始终只有 50% 左右

现象:在同一台 8 逻辑核服务器上执行 stress --cpu 8,top 里 8 个 stress 进程各占 50% CPU,整体使用率只有 50%。

原因:最常见的是超线程带来的逻辑核与物理核误解。8 逻辑核对应 4 物理核 8 线程时,stress 的 8 个 worker 在超线程上分时共享执行单元,单 worker 顶不上去。另一种原因是进程被 cgroup 的 cpu 配额限制,比如容器环境默认把整机 8 核限制成了 4 核。

解决:先用 lscpu 查看 Thread(s) per core,确认实际逻辑核数。再检查进程的配额限制,cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us 等文件。如果是云虚拟机配额限制,则加大配额或接受当前压力水位;是超线程导致的情况,则把 --cpu 设置为逻辑核数 8,观察整体的 load average 是否达到 8,这才是判断满载的关键指标,而不是逐个进程的 %CPU。

5.3 现象:内存压测后 SSH 无响应,只能通过带外管理重启

现象:stress --vm 8 --vm-bytes 8G 跑在 64G 内存机器上,机器在几分钟内出现 SSH 延迟、登录后命令无响应,最后只能通过远程管理口重启。

原因:内存总量被压到接近物理上限,系统开始大量换页。当换页占满 IO 路径,SSH 守护进程本身也要等待内存分配和 swap 操作,整个系统进入假死状态。

解决:压测前必须预留足够余量,一般可用内存至少保留总量的 10%~15% 不被压力覆盖。压测时用 free -g 盯 available 值,一旦低于预设阈值,立即用 pkill -9 stress 中止,或者干脆把 --timeout 设为 30 秒,限制单次压测时长。如果是纯内存压力测试,还可以考虑把 sysctl vm.swappiness 设为 0,让内核尽可能避免 swap,减少连锁卡顿。

5.4 现象:磁盘压测结束后,应用容器报磁盘空间不足

现象:stress --hdd 2 --hdd-bytes 10G 跑在 /tmp 挂载为磁盘的机器上,程序结束后,应用日志和临时文件无法写入,df -h 显示根分区 100%。

原因:stress 的 --hdd 临时文件默认写到 TMPDIR 或 /tmp 指定目录,当这个目录位于根分区且空间有限时,大量临时文件把分区写满。stress 在异常退出时没有来得及清理临时文件,残留数据继续占用空间。

解决:压测前先确认空闲空间和写入位置,df -h /tmp。如果想避免占用业务分区,可以把临时文件目录切到独立挂载卷:

mkdir -p /data/stress_tmp stress --hdd 2 --hdd-bytes 5G -d /data/stress_tmp

压测结束后检查残留:

find /data/stress_tmp -type f -name "stress*" -delete

上面命令把 stress 建立的临时文件按名字清理掉。更稳妥的方式是压测前设置 TMPDIR 环境变量,让它写到独立分区,避免业务分区被临时文件影响。

5.5 现象:旧版 stress 运行时报 invalid option -- 't',压测无法按时结束

现象:执行 stress --cpu 2 --timeout 60 时,提示 invalid option -- 't',进程一直运行不退出,最后手动 kill。

原因:下载的 stress 版本太老,比如 1.0.2 或更早的版本,不支持 --timeout 参数。部分 Linux 发行版默认仓库里的旧包没有带超时功能。

解决:换用支持超时参数的 1.0.4 版本,或者用外部命令限制运行时间,比如用 timeout 工具包裹:

timeout 60 stress --cpu 2

timeout 是 coreutils 自带的命令,不依赖 stress 本身的支持。注意 timeout 发送 TERM 信号时,stress 的子进程可能不会全部结束,必要时用 timeout -k 5 90 stress --cpu 2 组合,90 秒后先发 TERM,5 秒后再补 KILL,确保没有残留。

6. 进阶:把压测流程脚本化,跑完自动落一份压测记录

压测如果只在命令行手工敲,超过半小时就容易漏记参数或忘看关键指标。我现在的固定做法是把压测场景写成一段脚本,每轮执行后自动把时间和参数写入日志,后续复盘时不需要靠回忆确认当时压了多少。

脚本大致长这样:

#!/bin/bash # 单次压测脚本,参数:<持续时间秒> <CPU核数> <内存大小G> <磁盘worker数> DURATION=${1:-60} CPU_NUM=${2:-4} MEM_BYTES=${3:-8G} HDD_WORKER=${4:-0} LOG_DIR="/var/log/stress_test/$(date +%Y%m%d_%H%M%S)" mkdir -p "$LOG_DIR" # 压测前记录基线 uptime > "$LOG_DIR/baseline.txt" free -g >> "$LOG_DIR/baseline.txt" iostat -x 1 3 >> "$LOG_DIR/baseline.txt" # 启动后台监控 vmstat 2 "$((DURATION/2))" > "$LOG_DIR/vmstat.log" & MON_PID=$! # 执行压测 stress --cpu "$CPU_NUM" --timeout "$DURATION" if [ "$MEM_BYTES" != "0G" ]; then stress --vm 2 --vm-bytes "$MEM_BYTES" --vm-hang 30 --timeout "$DURATION" fi if [ "$HDD_WORKER" -gt 0 ]; then stress --hdd "$HDD_WORKER" --hdd-bytes 2G --timeout "$DURATION" -d "$LOG_DIR" fi wait "$MON_PID" # 压测后记录负载采样 uptime >> "$LOG_DIR/baseline.txt" free -g >> "$LOG_DIR/baseline.txt" echo "压测完成,日志目录:$LOG_DIR"

脚本执行逻辑很直白:先记录基线,然后启动后台 vmstat 监控,再按 CPU、内存、磁盘三个维度依次压测。每个维度都带 --timeout,避免跑过头。磁盘压测时,把临时文件目录指定到日志目录,压测文件与结果在同一分区,结束后清理也方便。

我见过有人把三组压力同时并发跑,压出来的结果很难定位瓶颈,所以脚本里我故意设计成顺序执行。CPU 压完再压内存,内存压完再压磁盘,每段压测结束后都可以直接从日志目录里读取对应时段指标,分清每个资源维度的独立表现。

最后还要强调一下磁盘压测的临时文件清理,脚本末尾最好补一段强制清理:

find "$LOG_DIR" -type f -name "stress*" -delete

那次莫名磁盘告警之后,我把这段加到了所有压测脚本的强制收尾步骤。从那以后,每次压测完我都会先跑一遍 pgrep -a stress 和 find 清理命令,确认没有残留再交还机器,定期检查压测日志也成了习惯。希望帮到你。

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

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

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

立即咨询