CentOS内网离线安装stress与CPU/内存/IO压测基线

发布时间:2026/10/29 2:26:13
CentOS内网离线安装stress与CPU/内存/IO压测基线 简介面向需要在 CentOS 等 Linux 环境中开展离线压力测试的运维与开发人员这套资料围绕 stress-1.0.4 的部署与使用整理重点解决无外网环境下压测工具及相关依赖难以安装的问题也适合性能测试初学者熟悉 CPU、内存、IO 等负载模拟场景。压缩包共 43 个文件约 46.66MB包含 stress 源码包、configure/install 等编译构建脚本、readme 与说明文档以及 gcc-g 等 11 个 rpm 依赖包并附带 sar 命令相关材料便于完成离线安装、依赖补齐和基础性能采样。已有 2598 人学习下载。读者可据此获得较完整的 stress 编译安装素材、依赖组件和排错参考用于搭建本地压测环境、验证系统负载表现并辅助日常性能排查。1. 内网机器上没有 stress先看清离线安装这件事的边界linux 上做压力测试stress 大概是最省事的那一类工具一条命令就能把 CPU、内存、IO 里的某一项或几项压满跑完自己退出不留垃圾。可一旦落到 centos 的内网机器上——没有外网源、没有 EPEL、连 yum 都只能指向一个空仓库——stress 的离线安装就变成了一道依赖解析题包从哪来、依赖闭包怎么算、glibc 版本对不对得上、装完怎么验证它真的在压而不是空转。这篇写的就是这条链路从选包到跑出可复现的基线。适合手上有一批不能出网、又要交付性能数据的机器的人也适合第一次给 centos 做离线 rpm 交付、被 Failed dependencies 卡过半天的人。2. 选型与依赖闭包stress、stress-ng 与 glibc 的三方对齐离线安装最容易翻车的地方不在安装命令而在“包从哪台机器上拿”。同一句rpm -ivh包来自同版本机器就是三秒钟的事来自高一个版本的机器就是一堆GLIBC_2.xx not found。所以顺序应该是先定目标机的系统底盘再定用哪个工具最后才算依赖。2.1 先摸清目标机的 glibc 与发行版分支在目标机上跑这几条把结果记下来后面挑包全靠它cat /etc/centos-release # 发行版与次版本例如 7.9 / 8.5 / Stream 9 uname -m # x86_64 还是 aarch64架构必须一致 getconf GNU_LIBC_VERSION # glibc 版本EL7 是 2.17EL8 是 2.28EL9 是 2.34 rpm -q glibc glibc-common # 确认 glibc 包没有被替换过 rpm -qa | grep -E ^(epel|stress) || true # 看看是不是已经装过 EPEL 或旧版 stressgetconf GNU_LIBC_VERSION这一条最值得单独看。EL7 的 glibc 是 2.17EL8 是 2.28两者符号版本不兼容从 EL8 上搬过来的 rpm 在 EL7 上会直接报version GLIBC_2.28 not found。血泪经验是不要相信“都是 centos应该差不多”次版本号差一位都可能让依赖链断掉。取包机器的判据只有三条——同发行版大版本、同架构、同 glibc 分支三条里缺一条就去源码编译那条路见 3.3。2.2 依赖闭包怎么算用一台联网的同版本机器做预演依赖闭包的意思是stress 这个 rpm 自己声明的 Requires加上它依赖的包再往上依赖的所有东西。手工一个个看太蠢用工具拉。# 在一台能出网、且与目标机同版本的机器上执行 sudo yum install -y yum-utils epel-release mkdir -p /tmp/pkg # 方式一只拉 stress 及其解析出的依赖 yumdownloader --resolve --destdir/tmp/pkg stress # 方式二拉全量依赖树适合之后要给几十台机器用 repotrack -a x86_64 -p /tmp/pkg stress stress-ng ls -l /tmp/pkg | wc -l--resolve会按当前机器的已装包状态做补集运算机器上已经有的库不下载。这正是它的坑——如果取包机器是完整安装、目标机是最小化安装补集就不一样了装到目标机上照样缺依赖。所以给内网做交付我一般直接上repotrack它不管你有没有装把整棵树的 rpm 全拉下来包多几个但省掉第二轮返工。-a x86_64指定架构-p指定输出目录。EL8 以上没有yumdownloader的话换 dnf 版本sudo dnf install -y dnf-command(download) dnf download --resolve --alldeps --destdir/tmp/pkg stress stress-ng--alldeps是关键不加它只下载主包不下载依赖。2.3 包完整性、签名与目录规划包拿回来别急着拷先在取包机器上过一遍校验rpm -K /tmp/pkg/*.rpm # 校验摘要与签名输出 digests signatures OK 才算过 rpm -qpR /tmp/pkg/stress-*.rpm | sort # 打印该包声明的全部依赖人工过一眼 rpm -qpl /tmp/pkg/stress-*.rpm # 看它到底往系统里写哪些文件rpm -qpR的输出值得看因为这是目标机上rpm -ivh报错时唯一的对照依据。如果输出里出现rpmlib(PayloadIsZstd)之类的条目说明包用了 zstd 压缩EL7 的 rpm 解不开必须换包——这个问题在跨大版本搬包时非常常见报错却只写一句含糊的依赖失败。目录我习惯这样规划交付时整包 tar 走目标机解压即用路径用途说明/opt/offline/stress/rpms原始 rpm 包只读保留原名/opt/offline/stress/repocreaterepo 生成的本地源由 rpms 复制而来/opt/offline/stress/scripts安装与压测脚本与包解耦方便单独更新mkdir -p /opt/offline/stress/{rpms,repo,scripts} cp /tmp/pkg/*.rpm /opt/offline/stress/rpms/ tar czf stress-offline-$(date %Y%m%d).tar.gz -C /opt/offline stress sha256sum stress-offline-*.tar.gz stress-offline-$(date %Y%m%d).tar.gz.sha256带上 sha256 是有实际意义的内网靠 U 盘或跳板机传输文件截断的概率比想象中高解压出来的 rpm 没报错但rpm -K挂掉排查起来很浪费时间。传完先跑sha256sum -c五秒钟的事。3. 三条离线安装路径rpm 手装、本地仓库与单文件编译包备齐之后落地路径有三条。选哪条不看技术高低看你要装几台机器一两台用 rpm 手装最快十台以上做本地源版本对不上才走编译。3.1 路径一rpm 手装先 --test 再一次性装齐rpm有个容易被忽略的特性它只会在“本次命令给出的所有包之间”解析依赖。所以正确姿势是把整个目录的包一次喂给它而不是一个一个装。# 1. 先做一次演练只看依赖缺不缺不实际写入 rpm -ivh --test /opt/offline/stress/rpms/*.rpm # 2. 演练通过后一次性安装rpm 会在同批次内互相满足依赖 rpm -ivh /opt/offline/stress/rpms/*.rpm # 3. 如果提示包已存在且版本相同用替换模式重装 rpm -Uvh --replacepkgs /opt/offline/stress/rpms/stress-*.rpm # 4. 校验安装结果 rpm -q stress rpm -V stress # 无输出表示文件校验全部通过--test这一步是后悔药它把依赖检查完整跑一遍但不落盘报错信息和真装时一模一样。我见过太多人跳过它结果装到一半失败系统里留下一半已装、一半未装的库包回滚比重装还麻烦。--replacepkgs处理的是“同名同版本已存在”的场景--oldpackage处理的是“要降级”的场景——后者在离线环境里要慎用因为降级一个被其他包依赖的库可能连带把别的服务搞挂。真正缺依赖又不想污染系统时考虑--nodeps不建议。--nodeps只是把检查关掉程序运行时照样error while loading shared libraries等于把问题从安装期推迟到运行期更难查。3.2 路径二createrepo 做本地源给多台机器用机器一多手装就不划算了而且 rpm 手装不解决“以后还要装别的包”的问题。做成本地源后续所有离线安装都走同一条通道。# 目标机上先准备好 createrepo它自己也必须离线装 rpm -ivh /opt/offline/stress/rpms/createrepo_c-*.rpm \ /opt/offline/stress/rpms/python3-*.rpm # 依赖按 rpm -qpR 的输出顺序补 # 建源 mkdir -p /opt/offline/stress/repo cp /opt/offline/stress/rpms/*.rpm /opt/offline/stress/repo/ createrepo_c /opt/offline/stress/repo # 写 repo 文件 cat /etc/yum.repos.d/offline-stress.repo EOF [offline-stress] nameoffline stress packages baseurlfile:///opt/offline/stress/repo enabled1 gpgcheck0 EOF # 只启用这一个源来装避免内网其他坏源拖慢或直接报错 yum --disablerepo* --enablerepooffline-stress install -y stress stress-ng yum --disablerepo* --enablerepooffline-stress list installed | grep -E ^stress说明几个参数。baseurlfile://走本地文件系统不需要 http 服务如果要多机共享把 repo 目录放到内网 http 下baseurl换成http://内网IP/stress即可。gpgcheck0是因为本地包没有导入对应的 GPG key关掉校验能少一轮报错对包来源有要求的环境把 key 一起带过去rpm --import后改回gpgcheck1。--disablerepo*这个参数看着粗暴其实是省时间的关键。内网机器上常常残留着指向外网的 repo 配置yum install会先去尝试连接、超时、重试一次几十秒报的错还跟真正的问题无关。装完别忘验证二进制能不能跑which stress stress-ng stress --version stress-ng --version 21 | head -33.3 路径三源码编译版本对不上时的出路前面说过跨大版本搬 rpm 会因为 glibc 符号版本挂掉。这时候源码编译是唯一出路。好消息是 stress 本体极其轻量——它主体就是单个 C 文件只依赖 libc 和 pthread离线机器上只要装了 gcc 就能编。# 前提有 gcc 与 make。最小化安装的机器从 ISO 挂本地源装 mount -o loop /opt/iso/CentOS-*.iso /mnt cat /etc/yum.repos.d/local-iso.repo EOF [local-iso] namelocal iso baseurlfile:///mnt enabled1 gpgcheck0 EOF yum --disablerepo* --enablerepolocal-iso install -y gcc make glibc-devel # 编译安装 tar xf stress-*.tar.gz cd stress-*/ ./configure --prefix/usr/local make -j$(nproc) make install /usr/local/bin/stress --version如果连 configure 都嫌麻烦stress 的源码包里通常带着stress.c直接一句编完gcc -O2 -pthread -o /usr/local/bin/stress stress.c /usr/local/bin/stress --version-O2打开优化让压测循环不至于被编译器拖慢-pthread必须加否则链接阶段会报undefined reference to pthread_create。这条路的代价是没有 rpm 数据库记录rpm -q stress查不到后面做资产盘点容易漏所以我在脚本里都会留一行注释写清来源和编译时间。stress-ng 就别想这条路了。它的依赖面宽得多libaio、libattr、libbsd、libgcrypt、zlib 都在可选列表里离线环境凑齐这些开发包的成本远高于直接搬 rpm。真要在低版本系统上用 stress-ng 的高级功能优先考虑把它跑在容器里或者干脆换一台机器。4. 参数配方CPU、内存、IO 三类压测怎么设才测得出问题装完只是开始。stress 的参数少但每一个都有“设了等于没设”的写法压出来的数字漂亮实际问题一个没暴露。4.1 CPU 与内存worker 数和字节数要分开算先看机器的底nproc # 逻辑核数超线程算两个 free -m # 看 available不是 free awk /MemAvailable/{print int($2/1024) MB} /proc/meminfoCPU 压测简单worker 数等于逻辑核数就能把调度器的队列压满stress --cpu $(nproc) --timeout 600s --verbose内存压测才是容易出事的地方。--vm-bytes是每个 worker的分配量不是总量这一点必须在脑子里焊死# 2 个 worker每个 1G合计约 2G--vm-hang 0 表示分配并触页后立刻释放反复制造缺页 stress --vm 2 --vm-bytes 1G --vm-hang 0 --timeout 300s--vm-hang 0和给一个大值的区别在于压测形态0 是“不停地 mmap、写页、munmap”压的是缺页异常和内存分配路径给 300 就是“分配 1G 常驻 300 秒”压的是常驻内存对系统的影响。前者容易暴露内存管理路径的问题后者更接近真实业务的内存占用形态两个都值得跑。总量控制上我一般让worker 数 × vm-bytes落在MemAvailable的 70% 到 80%剩下 20% 留给系统和监控进程——压到 100% 的后果不是“压得更狠”而是 OOM killer 直接把 stress 或者更重要的进程干掉。stress-ng 在这块更省心它支持百分比stress-ng --vm 2 --vm-bytes 70% --vm-keep --timeout 300s --metrics-brief--vm-keep让内存保持映射不释放--metrics-brief在结束时打印 bogo ops 和实际耗时是判断“它到底干了多少活”的依据。4.2 IO 与组合场景先分清 sync 和真写盘--io和--hdd是两个完全不同的东西混用会得出错误结论# io worker 只反复调用 sync()制造的是内核回写压力本身不产生新数据 stress --io 4 --timeout 120s # hdd worker 真的创建文件、写入、删除默认落在执行 stress 时的当前目录 mkdir -p /data/stress-tmp cd /data/stress-tmp stress --hdd 2 --hdd-bytes 1G --timeout 300s在一台干净的、没有脏页的机器上跑--ioiostat的%util几乎不动因为sync()没东西可刷。这不是工具坏了是压测目标选错了。要压磁盘吞吐就用--hdd并且一定cd到真实块设备上的目录再跑——/tmp在很多镜像里是 tmpfs写进去的是内存压出来的是内存带宽不是磁盘。组合压测用来找资源争抢的拐点stress --cpu $(nproc) --io 2 --vm 2 --vm-bytes 1G \ --hdd 1 --hdd-bytes 512M --timeout 15m这一条把四类负载叠在一起观察的是系统在满负荷下的调度行为——比如 CPU 压满时 IO 的await会不会被拉长内存压力上来后si/so有没有开始交换。stress-ng 对应写法用--temp-path显式指定落盘目录比依赖当前目录靠谱stress-ng --cpu 4 --hdd 2 --hdd-bytes 2G --temp-path /data/stress-tmp \ --timeout 300s --metrics-brief4.3 监控侧让采样窗口和压测窗口对齐压测不配监控等于闭着眼睛开车。三个采集器够了# 后台起监控采样次数与压测秒数一致保证窗口对齐 vmstat 1 600 /var/tmp/vmstat.log 21 iostat -x 1 600 /var/tmp/iostat.log 21 MPID$! stress --cpu $(nproc) --timeout 600s -v /var/tmp/stress.log 21 wait $MPID || truevmstat里重点看四列r是运行队列长度CPU 压满时应该接近核数cs是上下文切换做 CPU 压测时不应该暴涨暴涨说明有锁竞争或调度异常si/so是换入换出非零就说明内存压过头了wa是 IO 等待。iostat -x里重点看%util、r/s、w/s、await四列await突然从个位数跳到几十毫秒说明队列开始堆积。事后一定要查 OOMdmesg -T | grep -i -E out of memory|killed process这条命令是黑匣子。stress 被 OOM killer 干掉时终端上只有一行Killed看不出是谁干的dmesg里才有完整的Out of memory: Killed process pid (stress)记录连当时的 meminfo 快照都带着。5. 避坑与排查五条现场记录每条都带现象5.1 rpm -ivh 报一堆 Failed dependencies现象error: Failed dependencies: libaio.so.1()(64bit) is needed by stress-ng-...一屏能刷十几行。原因依赖是在另一台机器上解析的取包机的已装包状态和目标机不一致或者用了yumdownloader的默认补集逻辑把“取包机已装”的库跳过了。解决回到 2.2 用repotrack拉全量树或者直接上本地源让 yum 自己算。临时补一两个库时用rpm -qpR对照报错清单逐个确认版本注意()(64bit)后缀说明要 64 位版本。绝对不要用--nodeps绕过去。5.2 压测跑着跑着进程没了现象stress --vm 2 --vm-bytes 4G在 8G 内存的机器上跑到第二分钟进程消失终端只留一句Killed。原因--vm-bytes是每个 worker 的量2 × 4G 已经顶到物理内存上限再加上系统自身占用OOM killer 必然介入。容器里还要再叠一层 cgroup 限制。解决先算总量再跑控制在MemAvailable的 70% 左右。容器环境额外看cat /sys/fs/cgroup/memory.maxcgroup v2或/sys/fs/cgroup/memory/memory.limit_in_bytesv1。跑完用dmesg -T | grep -i oom确认是不是真的 OOM别把段错误误判成内存不足。5.3 压测数字好看业务却没感觉现象stress --io 8跑满top里 stress 的 CPU 占用很高但iostat -x的%util几乎不动磁盘吞吐没变化。原因--ioworker 干的事就是反复sync()没有脏页时它只是空转消耗 CPU压根不产生磁盘写入。另外如果压测目录是 tmpfs写的是内存不是盘iostat自然看不到动静。解决压磁盘吞吐换--hdd并且确认落盘目录是真实块设备df -hT /data/stress-tmp看到ext4/xfs才算数看到tmpfs就换目录。要更精确的 IO 模型用 fio 交叉验证stress 的--hdd不适合做 IOPS 基准。5.4 --hdd-bytes 设太大把宿主机写满现象跑完一轮压测/或/data的可用空间少了一大截重启也没恢复。原因--hdd会在结束时删掉临时文件但进程被 kill、超时异常、或者机器在压测中途重启临时文件就留下来了。--hdd-bytes乘上 worker 数就是峰值占用很容易超过分区余量。解决--hdd-bytes不超过目标分区可用空间的 50%worker 数也别开太多。异常退出后用find /data/stress-tmp -name stress.* -size 100M -delete清残留跑之前先看一眼df -h养成习惯。5.5 装完 command not found 或者版本不对现象明明rpm -q stress有输出stress --version却是旧版本或者which stress找不到。原因系统里原本就有同名包rpm -ivh因为已存在被拒但很多人没注意到那行报错或者源码装到了/usr/local/bin而某些受限 PATH 下找不到也有可能是 shell 的 hash 缓存还指着旧路径。解决按这个顺序查——rpm -q stress看包的版本type -a stress看 PATH 里所有同名命令ls -l /usr/bin/stress /usr/local/bin/stress看实际文件最后hash -r清缓存。要用新版本就用绝对路径调用别指望 PATH 顺序自动帮你选对。6. 做成可复现的基线一个脚本和四个必须看的数单次压测的价值有限能复现、能对比的基线才有价值。下面这个脚本我一般在每台新机器交付前跑一遍参数只有两个时长和落盘目录。#!/usr/bin/env bash set -euo pipefail DURATION${1:-300} # 压测时长单位秒 TMP_PATH${2:-/data/stress-tmp} # hdd worker 落盘目录必须是真实块设备 OUT/var/log/stress-baseline/$(date %Y%m%d-%H%M%S) mkdir -p $OUT $TMP_PATH command -v stress /dev/null 21 || { echo stress 未安装先回到第 3 章; exit 1; } CPU_N$(nproc) AVAIL_MB$(awk /MemAvailable/{print int($2/1024)} /proc/meminfo) VM_MB$(( AVAIL_MB * 70 / 100 / 2 )) # 2 个 vm worker各占可用内存的 35% # 监控先起保证采样窗口覆盖整个压测过程 PIDS() vmstat 1 $DURATION $OUT/vmstat.log 21 PIDS($!) if command -v iostat /dev/null 21; then iostat -x 1 $DURATION $OUT/iostat.log 21 PIDS($!) else echo 未装 sysstat跳过 iostat 采样 $OUT/iostat.log fi # 压测本体CPU 满核 内存 70% 单路 hdd ( cd $TMP_PATH stress --cpu $CPU_N --vm 2 --vm-bytes ${VM_MB}M \ --hdd 1 --hdd-bytes 1G --timeout ${DURATION}s -v ) $OUT/stress.log 21 for p in ${PIDS[]}; do wait $p || true; done dmesg -T 2/dev/null | tail -n 200 $OUT/dmesg.log || true if grep -qiE out of memory|killed process $OUT/dmesg.log; then echo 警告压测期间出现 OOM把 VM_MB 的系数调小后重跑 fi echo 结果目录$OUT几个关键点。set -euo pipefail让脚本在任一命令失败时立刻停避免拿着一份不完整的数据做结论。MemAvailable才是可分配内存的真实口径MemFree会把缓存算成已用用它算出来的VM_MB会小得离谱压不出任何压力。监控进程先起、压测后跑、最后逐一wait是为了让vmstat的采样窗口把整个压测过程包住事后对齐时间轴不会出现“压测开始前十秒没有数据”的尴尬。dmesg单独落到文件里出问题时不用回现场。结果出来后只盯四个数多一个都别看观察项取值方式参考判断运行队列rvmstat.log的第六列CPU 压测期间接近nproc说明压满远超核数说明有阻塞上下文切换csvmstat.log的第十二列CPU 纯计算压测时不应暴涨暴涨优先怀疑锁竞争换入换出si/sovmstat.log的第七、八列非零即内存压过头与 OOM 记录对照看磁盘awaitiostat.log的await列与空载基线比翻倍以上说明队列已堆积判断这一轮压测有没有效标准很朴素r要起得来si/so要压得住dmesg要干净stress的退出码要是 0。四个都满足这份数据才有资格进交付文档任何一项不满足先回头查参数别急着下结论说机器性能不行。最后留一句自己的教训。早年给一批内网机器做压测图快用了--nodeps装 rpm程序能跑起来压测数据也出得挺漂亮交付两周后业务方复现时全崩——缺的那个库是 IO 相关模块的只在特定负载下才被调用平时根本看不出来。从那以后我每次做离线交付都强制走一遍rpm -qpR对依赖、--test演练、装完rpm -V校验这三步宁可多花五分钟。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询