ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

CentOS离线安装stress压力测试工具:依赖检查与压测避坑指南

CentOS离线安装stress压力测试工具:依赖检查与压测避坑指南 简介面向CentOS服务器运维与性能测试人员这份离线安装包重点解决无外网环境下无法通过yum直接安装压力测试工具的问题基于stress-1.0.4整理同时附带sar命令相关组件可覆盖从负载生成到性能监控的常见需求。它既适合初次接触压力测试的新手快速搭建环境也方便有经验的工程师在内网隔离环境中统一分发部署既可选用现成rpm包安装依赖也可利用configure、make等脚本从源码编译灵活度较高。包体共43个文件压缩后约46.66MB。其中11个rpm包直接对应安装所需依赖configure、install-sh、depcomp、missing等自动构建脚本支撑源码编译C语言源文件展示stress核心逻辑.texi、.tex、html、info等文档则提供用法与格式说明目录结构清晰便于按需取用。目前已有2589人学习下载。通过该包可一次性补齐离线部署所需依赖与编译链避免逐个搜索rpm的繁琐配合sar可实时观测CPU、内存、I/O等指标形成“压测—观测”的完整闭环。对希望研究stress实现细节的读者源码连同多格式文档也提供了良好入口。1. 先泼盆冷水CentOS 离线装 stress问题不在网很多人以为 CentOS 离线安装 stress 压力测试工具只要把 rpm 拷进去就能直接跑。实战里最常见的翻车恰恰不在“能不能下载”而在依赖匹配、架构选错、脚本偷偷联网这三件事上。这个离线安装包解决的是在内网环境里把 linux 压力测试工具 stress 装到 CentOS 上并且稳定跑完冒烟测试。我拆过几个离线安装包发现真正能用的那版都做了三件事架构区分、依赖预检、压测示例缺一个都会在目标机器上多折腾两小时。这套资源适合两类人一类是隔离网络里的运维和实施机器没有外网需要一次性把 stress 带进去另一类是刚接手服务器验收想快速验证 CPU、内存、磁盘能不能打满的测试工程师。先说结论stress 本身很小依赖基本只有 glibc但离线安装的坑全在“你以为没问题”的地方。这份资源把下载、依赖、安装和验证串成了一条链照着操作比临时上网搜命令靠谱。它解决的不是“怎么下载”而是从拿到包到压测命令真正能出数的完整路径。2. 认识 stress压测工具那么多为什么离线包里先备它2.1 stress 到底在压什么CPU、内存、IO、磁盘四种负载stress 这类工具的原理不复杂fork 出多个 worker 子进程每个 worker 循环执行一类消耗资源的操作直到 timeout 或者收到退出信号。CPU 型 worker 做的是平方根运算让整数单元和浮点单元持续跑满VM 型 worker 分配指定大小的内存块并且逐页写入防止系统把内存页懒分配IO 型 worker 不停触发 sync制造内核和磁盘的 I/O 等待HDD 型 worker 会在当前目录创建临时文件写入再删除反复制造磁盘写放大。这个设计决定了它的定位适合做快速冒烟不适合做长期业务仿真。比如你要验证新到货的服务器能不能跑满 16 核stress --cpu 16 --timeout 60就能在一分钟内看到负载曲线。但如果你想测数据库在混合读写下的抖动stress 给不了这么细的模型那是 fio、sysbench、stress-ng 的活。还有一个经常被忽略的点stress 只负责制造压力不负责输出“性能报告”。压测期间系统发生了什么要靠 uptime、top、iostat 这些外部命令去采集。理解这一点你才不会被 stress 的安静执行误导以为没有报错就是没有压力。实际上CPU 型压力让系统负载升高正是你希望看到的“正常异常”。离线安装之所以优先考虑 stress是因为它的二进制很小运行时不依赖额外的第三方库CentOS 自带的 glibc 基本都能满足。很多内网机器明明有压力测试需求却因为包管理工具不可用一直没测过这类轻量工具最适合放进离线工具包。2.2 选型为什么不是 stress-ng也不是 sysbench用哪款压测工具取决于你要压什么。我自己一般这样区分需要单点快速压 CPU 和内存用 stress需要更细的负载模型、fork 压力、资源限制组合用 stress-ng需要数据库性能基线用 sysbench。sysbench 依赖要复杂一些离线包体积大纯为了占 CPU 没必要。stress-ng 是 stress 的增强版参数多到能模拟几十种压力模型但同样带来更大的二进制和更复杂的启动参数。在 CentOS 最小安装的离线环境里多一个依赖就多一个翻车点stress 的“简陋”反而是优势。下面按离线安装场景做一组对比工具二进制大小依赖复杂度适合场景离线安装难度stress几十 KB低主要依赖 glibcCPU、内存、IO 快速冒烟低stress-ng数 MB中细粒度负载组合、压力调优中sysbench数 MB中高数据库、线程、内存基准中高如果内网机器用途是“验证服务器资源上限”选 stress 就够了。这份离线包里的示例脚本也是围绕这个场景组织的。如果后续发现 stress 的负载模型不够用再考虑把 stress-ng 也做成离线包那是另一个交付问题了。2.3 离线安装前的依赖检查先用 rpm 问清楚在把包拷进内网之前先在有网机器或者刚解压的目录里做一次依赖查询。rpm 有一个很实用的组合参数-qpR表示对未安装的包文件查询 Requires 列表。我在实际项目里会先跑这条命令确认系统自带依赖能否满足。# 在离线包根目录执行列出 stress rpm 依赖 rpm -qpR RPMS/x86_64/stress-*.rpm这条命令的输出一般是 /bin/sh、libc.so.6()(64bit)、rpmlib 一系列条目。/bin/sh由 bash 包提供libc.so.6 来自 glibcrpmlib 是 rpm 自身属性正常 CentOS 都能满足。如果输出里出现类似GLIBC_2.14这样的符号版本要求就要额外留意CentOS 7 的 glibc 是 2.17CentOS 8 是 2.28只要包不是拿更新系统编的一般问题不大。同时检查架构# 确认目标机架构离线包目录名要与它保持一致 uname -mx86_64 和 aarch64 的 RPM 不能混用这是离线安装里最容易踩的坑。依赖预检做完了才轮到安装脚本上场。安装过程中如果还报缺少依赖优先看是不是 32 位库没装而不是怀疑 glibc 本身。2.4 如果离线包只有源码编译安装的边界在哪有些离线环境拿不到现成 RPM只有源码包。源码编译也是可用路线但需要 gcc、make、kernel-devel 配合。stress 源码很小configure 脚本生成 Makefilemake make install默认装到 /usr/local/bin。这条路的坑在于内网机器往往没装编译工具链gcc 和 glibc-headers 又是一串依赖所以只有在包内确实没有 rpm 时才走这条路而且装完后要用ldd /usr/local/bin/stress检查动态库。相比 RPM 方案源码编译的二进制可能链接到较新的 glibc反而不如官方 RPM 稳。若离线包结构里没有 RPMS 目录只有源码记住优先找同版本系统的 RPM不要急着 make。源码编译适合用来应急不适合作为交付基线。3. 拆解离线包结构拿到手先清点三件事3.1 离线包里应该有哪些文件离线安装包和普通源码包不一样它必须自带三个能力不同架构的 RPM、依赖兜底、可复现的安装脚本。下面是一个典型的目录结构也是我拆包时期望看到的样子。你拿到的实际包可能多了日志目录或 systemd 示例但核心文件不会有太大出入。stress-offline/ ├── RPMS/ │ ├── x86_64/ │ │ └── stress-*.rpm │ └── aarch64/ │ └── stress-*.rpm ├── deps/ ├── examples/ │ ├── cpu_stress.sh │ └── memory_stress.sh ├── install.sh └── README.txt看到这个结构第一件事不是执行 install.sh而是清点三样。第一RPMS 下面是不是有和目标机器匹配的架构目录。第二deps 目录里是不是真的放了依赖包而不是只留了一句“请自行安装”。第三install.sh 里的安装命令用的是 rpm 还是 yum如果脚本里有 yum 关键字说明它可能不适合完全离线环境后面要格外小心。README.txt 也别跳过作者通常会把 OS 版本和测试过的内核写在里面。如果 README 里写了“仅支持 CentOS 7”就不要拿到 CentOS 8 上强行装。文件用途可以用一张表看得更清楚文件/目录作用使用时机RPMS/x86_64 或 aarch64对应架构的 stress RPM安装主程序deps/兜底依赖包仅当依赖检查发现缺失examples/压测示例脚本安装后对照使用install.sh一键安装入口正常安装流程README.txt兼容性说明和注意事项安装前阅读3.2 install.sh 为什么先做“三查”架构、旧版本、依赖一个好的离线安装脚本不会直接rpm -ivh一把梭而是先做三次检查查架构、查旧版本、查依赖。查架构避免装错包查旧版本避免和已有版本冲突查依赖避免装到一半失败。下面这段脚本是一个可复现的精简版完整包里的 install.sh 逻辑类似。#!/bin/bash # 离线安装 stress 的精简脚本只保留核心判断逻辑 set -euo pipefail ARCH$(uname -m) RPM_PATHRPMS/${ARCH} # 1) 架构检查目录不存在直接退出 if [ ! -d ${RPM_PATH} ]; then echo 当前架构 ${ARCH} 不在离线包中请检查包是否匹配 2 exit 2 fi # 2) 旧版本检查已存在则先卸载避免 rpm 冲突 if rpm -q stress /dev/null 21; then echo 发现旧版本 stress先执行 rpm -e stress rpm -e stress || true fi # 3) 依赖检查过滤系统自带项逐条确认 MISSING$(rpm -qpR ${RPM_PATH}/stress-*.rpm | \ grep -v ^rpmlib | grep -v ^/bin/sh | \ while read -r dep; do rpm -q --whatprovides ${dep} /dev/null 21 || echo ${dep} done) if [ -n ${MISSING} ]; then echo 依赖未满足请先安装 deps/ 目录下的 rpm 2 echo ${MISSING} 2 exit 3 fi # 最后再安装 rpm -ivh ${RPM_PATH}/stress-*.rpm逻辑说明set -euo pipefail的u让未定义变量直接报错pipefail保证管道命令中任何一段出错都会让脚本失败。依赖检查部分用grep -v过滤掉 rpmlib 和 /bin/sh这两个是 rpm 和 bash 自带的然后对剩余每个依赖调用rpm -q --whatprovides如果能找到提供者就静默通过找不到才输出到 MISSING 变量。这样真正缺了什么一眼可见。参数说明rpm -q --whatprovides libc.so.6()(64bit)这种写法比yum provides更快而且不依赖 yum 源离线环境也能用。rpm -e stress || true里的|| true是为了防止卸载旧版本出错时直接终止脚本如果旧版本本来就不完整卸载失败可以忽略后面安装时用--replacepkgs覆盖。3.3 如果依赖检查真的报了缺包deps 目录怎么兜底我见过很多离线包把 deps 目录做得有名无实里面只有 README没有任何 RPM。合格的离线包会在 deps 里放与主版本同源的依赖并且按安装顺序加数字前缀比如 01-glibc-common-.rpm、02-rpm-libs-.rpm。内网机器如果是最小化安装偶尔会缺某些公共库但 stress 的依赖很轻实测遇到最多的是缺 32 位兼容库或高版本 glibc。出现这种情况时不要直接卸掉系统 glibc优先用rpm -Uvh升级变体# 进入 deps 目录按文件名顺序安装兜底依赖 cd deps rpm -Uvh 01-*.rpm 02-*.rpm 2/dev/null || true cd ..逻辑说明rpm -Uvh的 U 表示升级如果系统已有低版本会升级到包内版本如果没安装则直接装上。2/dev/null || true是兜底写法防止某个包系统里已经更新导致输出错误中断。依赖装好后再回到根目录重新执行bash install.sh。注意不要为了跳过依赖检查而给 rpm 加--nodeps或--force。离线环境里强制安装可能当时能过但压测进程跑起来后段错误、内存异常会一起找上门后面排查成本远高于正常处理依赖。3.4 安装前校验文件完整性和执行权限离线包从一台机器传到另一台很可能在传输过程中损坏。我见过因为压缩包中断导致 RPM 半截安装时报 “rpm: not an rpm package” 的情况。所以在执行 install.sh 之前先检查文件类型和校验值。# 确认 rpm 文件确实是 RPM 格式而不是损坏的空文件 file RPMS/x86_64/stress-*.rpm # 对比离线包 README 里的 SHA256 值确保文件完整 sha256sum RPMS/x86_64/stress-*.rpm逻辑说明file命令会输出 RPM 格式标记如果输出 “gzip compressed data” 或 “data”说明文件损坏或下载不完整。sha256sum计算出的哈希值要和 README.txt 里记录的比对不一致就重新传包。参数说明sha256 是当前最常用的校验方式比 md5 更可靠有些包会用--check直接校验但离线包手动比对已经足够。脚本里的安装命令也会有set -e兜底但传输校验能让你在安装前就发现风险。4. 离线安装与首轮压测两条命令验证到底装没装上4.1 上传包、执行脚本、确认版本拿到离线包之后我用的是“先验货、再安装”的顺序。把包传到目标机器的 /root 或 /opt 下解压进入目录先跑一遍目录里的 README 或 install.sh 前的校验命令确认系统版本。然后执行安装脚本。install.sh 会完成架构检查、旧版本卸载、依赖检查、RPM 安装四步。脚本结束后不要急着压测先用 version 命令确认可执行文件已经进入系统路径。# 进入离线包目录执行安装 cd stress-offline/ bash install.sh # 安装完成后确认可执行文件 stress --version逻辑说明bash install.sh不依赖脚本可执行权限哪怕上传时权限位被 Windows 改过也能跑。stress --version会输出版本信息和构建标识能输出版本说明 rpm 安装成功且动态库被正确解析。如果这步报 “command not found”优先检查 /usr/local/bin 或 /usr/bin 是否在 PATH 中而不是重新安装。在很多精简镜像里系统 PATH 可能不包含 /usr/local/bin这是源码安装路线常见的问题。RPM 安装默认把 stress 放到 /usr/bin一般不会遇到。如果确实发生可以直接用绝对路径/usr/bin/stress --version验证再把 /usr/local/bin 加进 PATH不用急着卸载重装。4.2 CPU 压测首跑四 worker 跑 30 秒首次压测我习惯从 CPU 开始原因很简单CPU 负载最容易观察也不需要预留磁盘空间。下面这条命令会创建 4 个 worker每个 worker 持续执行平方根运算30 秒后自动退出。命令本身不会对系统做任何持久改动适合作为冒烟测试基线。# 4 个 CPU worker持续 30 秒 stress --cpu 4 --timeout 30参数说明--cpu 4的 4 是 worker 数量不是 cpu 编号建议先用nproc查看逻辑核数再决定是压满还是压一部分。--timeout 30单位是秒到时间后 stress 会向所有 worker 发送终止信号并退出。命令正常结束的退出码是 0如果被外部 kill退出码非 0可以作为后续自动化判断的依据。压测过程中另开一个终端观察系统状态# 观察负载和 CPU 占用 uptime top -bn1 | head -n 5逻辑说明uptime输出 load average 的三个数字压满 4 核时一分钟平均负载会接近 4。top -bn1是单次非交互输出head -n 5取前几行就够了。压测结束后负载会逐渐回落如果回落很慢说明机器上还有别的后台任务在抢资源。4.3 内存和磁盘压测参数怎么调别一把梭CPU 验证通过后可以根据需求做内存和磁盘压测。内存压测的重点是--vm-bytes的取值它表示每个 VM worker 分配多少字节内存。stress 会逐页写入所以内存会被真实占用而不是只做虚拟分配。磁盘压测的重点是--hdd-bytes和临时文件存放位置不指定当前目录时默认用当前目录做临时文件这很容易在一个没空间的挂载点写满盘。# 2 个内存 worker各占用 1G运行 60 秒 stress --vm 2 --vm-bytes 1G --timeout 60 # 2 个磁盘 worker各写 2G 临时文件运行 60 秒 mkdir -p /data/stress-test stress --hdd 2 --hdd-bytes 2G --timeout 60 -d /data/stress-test参数说明--vm-bytes 1G支持 K/M/G 单位2 个 worker 总共会尝试占满 2G 内存压测前用free -h确认余量。-d指定磁盘 worker 的工作目录--hdd-bytes 2G是每个 worker 的临时文件大小两个 worker 会同时产生 4G 峰值占用所以目标目录至少留出双倍空间才安全。如果不指定--timeoutstress 会一直跑下去直到手动 CtrlC自动化脚本里必须带 timeout。实际压测里“压测结束磁盘被写满”是我的血泪经历。--hdd的临时文件在正常退出时会清理但如果压测进程被强制 kill临时文件可能残留。因此我在生产环境跑磁盘压测前会先df -h检查目录剩余空间再find /data/stress-test -name stress.* -delete清理历史残留。这两步虽然简单但能避免绝大多数意外。4.4 压测退出码和 timeout 的单位陷阱自动化脚本里经常有人把 timeout 写成 30mstress 会把 m 解析成“米”还是“秒”实际上数字后缀解析只支持 s/m/htimeout 30m会被当作 30 秒加一个无效字符直接报错。正确写法是--timeout 30s或--timeout 1m数字与单位间不能有空格。另外stress 不带 timeout 时会一直运行直到收到 SIGINT/SIGTERM。手动 CtrlC 时退出码是 130正常 timeout 到期退出码是 0。如果脚本要判断“压测是否成功”不能只看 exit code还要检查 worker 是否全部退出。可以这样看# 查看 stress 是否还有残留进程 pgrep -x stress echo 还有 worker 在跑 || echo 已全部退出逻辑说明pgrep -x stress用精确进程名匹配避免匹配到包含 stress 关键字的其他进程。这个检查在压测被中断时很有用。参数说明-x表示精确匹配如果你的环境没有 pgrep用pidof stress代替。命令行压测可以随机应变但写进脚本就要把这些边界考虑清楚。5. 避坑清单离线安装 stress 时最常见的五个翻车现场5.1 报错 GLIBC_2.14 缺失但系统 glibc 明明更高现象在 CentOS 7 机器上执行rpm -ivh stress-*.rpm系统提示libc.so.6(GLIBC_2.14) is needed而rpm -q glibc显示版本是 2.17明明满足条件却装不上。原因RPM 依赖匹配不止看包版本还要看给定的符号版本是否在当前 glibc 的符号表里。多数 CentOS 7 的 glibc 包含 2.14 符号但某些精简镜像或容器基础镜像可能裁剪了兼容符号另一个常见原因是把 32 位和 64 位依赖混在一起查32 位包的依赖在 64 位系统上会显示缺失。解决先用ldd --version或rpm -q glibc确认真实符号表再确认当前架构。如果确实提示缺少 32 位版本安装glibc.i686变体。不要给 rpm 加--nodeps跳过这个参数会隐藏问题压测时直接段错误更难受。排查时我会把rpm -qpR的输出完整保存和系统已有包逐个比对而不是只看报错那一条。5.2 安装成功但一跑就 Segmentation fault现象stress --version能输出版本但执行stress --cpu 1后立即报Segmentation fault退出码不是 0。原因最常见的是 RPM 架构不匹配比如在 aarch64 机器上装了 x86_64 的包rpm 虽然能装但运行时指令集不兼容其次是 RPM 是在更高版本系统上编译缺失某些新符号。解决执行uname -m与离线包目录名对照再用ldd $(which stress)看动态库依赖。如果ldd输出里有 “not found”说明包与系统库不匹配需要换包。遇到这种情况我最常做的是回到安装脚本的架构检查那一步看日志里是否跳过了 RPMS 目录匹配。段错误不是偶发现象基本都能在 ldd 里找到线索。5.3 install.sh 里藏了 yum 命令内网一执行就卡住现象内网机器运行bash install.sh后没有任何输出日志停在yum install ...等了很久才报无法连接镜像源。原因部分离线包为了省事在依赖处理时直接调yum install这在有网环境没问题但内网没有源就会卡在超时等待。更隐蔽的是脚本先检测到缺少依赖然后自动执行 yum而用户直到看到报错才知道它在联网。解决安装前grep -n yum install.sh看一眼发现 yum 关键字就说明脚本不适合纯离线。正确的离线脚本应该先查 deps 目录缺依赖时提示用户手动安装而不是隐式联网。如果脚本里执意要用 yum就在执行时断开目标机器外网让它无法“假装可以联网”。我在交付离线包时会在 README 里特意写明“不依赖 yum 源”就是为了避免这种误解。5.4 磁盘压测把目录写满业务侧直接告警现象执行stress --hdd 4 --hdd-bytes 10G --timeout 60后磁盘被写满压测结束后临时文件没有完全清理业务日志开始报 disk full。原因--hdd 4会创建 4 个 worker每个 worker 都会写入到--hdd-bytes指定的大小总峰值是 40G而不是 10G。如果当前目录正好是业务分区压力直接打到业务路径上。stress 正常退出会清理临时文件但被 kill 或断电时残留文件会留在原地。解决压测前必须指定专用目录并用df -h确认空间。命令里加-d /tmp/stress-test或手动创建/data/stress-test后操作。压测结束后检查残留文件find /data/stress-test -type f -name stress.* -delete。从那以后我每次做磁盘压测都会把“分区可用空间 / worker 数 / 每个 worker 大小”三项写进备注避免拍脑袋定参数。5.5 同样参数两次压测结果差很多负载不稳定现象第一次stress --cpu 4 --timeout 60load average 能到 4第二次跑同样命令负载只在 2 左右徘徊明显没压满。原因有可能是机器上有其他业务在抢占 CPU也有可能是 CPU 调频策略导致核间跑到不同频率更常见的是压测时间太短top 采样窗口恰好落在 worker 启动阶段。解决压测前用top -bn1看整体空闲 CPU再用taskset绑定 CPU 范围减少调度噪声# 绑定 0-3 号逻辑核压力只落在这几个核上 taskset -c 0-3 stress --cpu 4 --timeout 60参数说明taskset -c 0-3把 stress 进程绑定到前四个逻辑核避免线程在不同核间迁移。负载观察至少持续 30 秒uptime的 1 分钟平均比top的瞬时值更有参考性。如果绑定后负载还是不达标再用pgrep -x stress确认 worker 数量用ps -o pid,ppid,stat,cmd -C stress查每个子进程状态。这些排查步骤能快速区分“压力没起来”和“压力被系统调度稀释了”。6. 从“装一次”到“随时能装”自己做离线仓库的验证方法如果你手里已经有了一份能用的离线包下一步值得做的是把“装一次”变成“随时能装”。方法是找一台能联网的同版本 CentOS 机器用 yum 工具把 stress 和它的运行时依赖一次性拉下来再生成一个本地 yum 源。这样内网后续不仅能把 stress 装到多台机器上还能顺带装其他常用小工具。# 在有网机器上创建目录并下载 stress 包及其依赖 mkdir -p /tmp/stress-offline yumdownloader --resolve --destdir/tmp/stress-offline stress # 生成 repodata把目录变成可在内网识别的 yum 源 cd /tmp/stress-offline createrepo .逻辑说明--resolve会把运行时依赖一起下载到目录createrepo .生成 repodata 子目录yum 才能识别为一个可用源。参数说明yumdownloader 来自 yum-utils如果没有安装就先yum install -y yum-utilscreaterepo来自 createrepo 包CentOS 7 自带CentOS 8 用 dnf-plugins-core 的dnf reposync替代。把整个目录出到内网后配置一个 local stress 源就能用常规 yum 命令安装。验证本地源是否可用的命令也很简单。内网机器上放一个新配置文件指向离线源然后执行查询# 内网机器上只启用本地离线源查询 stress 是否可见 yum --disablerepo* --enablerepostress-local list stress如果能列出 stress 包信息说明本地源能被 yum 正确解析再执行yum install -y stress就完成了。到这里你已经有了两条离线落地方案直接 rpm 安装适合单台机器本地 yum 源适合批量交付。回想我第一次给内网机器装 stress只拷了一个 rpm 包结果到了现场发现缺一个小依赖又跑回去拿。从那以后我每次打包都会在下载机器上先跑一遍rpm -qpR把依赖列表打印出来存档再确认架构目录和目标机器一致才敢带出门。这次分享的离线包本质就是把这条验证路径固化成了脚本和目录结构。希望帮到你。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进