news 2026/10/10 3:23:46

stress实战:给Linux服务器模拟CPU/内存/IO/磁盘高负载压测

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
stress实战:给Linux服务器模拟CPU/内存/IO/磁盘高负载压测

简介:Linux系统压力测试工具stress的完整源码与文档包,面向系统管理员、运维工程师及内核开发者,用于评估服务器在CPU密集、内存分配等负载下的稳定性与极限性能。压缩包共含32个文件,大小仅199KB,以configure、Makefile.am、Makefile.in等构建脚本为主,辅以stress.c源码、texinfo文档、README说明及测试校验脚本,便于使用者阅读源码、自行编译或交叉验证。目前已有1036人学习。资源内附详细使用说明与参数释义,涵盖--cpu、--vm、--vm-bytes等常用选项,可快速生成定制化压力场景;同时提供configure.in、aclocal.m4等自动构建辅助文件,方便在主流发行版上安装部署。通过结合top、vmstat等监控工具,读者能系统掌握压力测试方法,并据此优化系统资源配置,提升高负载环境下的可靠性。

1. stress工具:给Linux服务器施加一次可控的“人工高负载”

一台新上线的服务器,配置看着很豪华,但业务方反馈“一到大促就卡”。查了CPU平均使用率、内存占用、磁盘IO,全都在阈值以下,你拿不出一个结论:这台机器到底能不能扛住突发压力?这就是我用stress的理由:它能在几分钟内模拟出CPU满载、内存吃紧、IO排队、磁盘持续写入等各种负载,把服务器的真实承受边界试出来。它不是一个诊断工具,而是一个加压源——配合监控命令使用,能把“我觉得没问题”变成“数据证明没问题”。适合所有做系统运维、性能压测和服务器选型评估的开发者。

2. 装好stress的第一天:用最小命令跑通CPU、内存、IO、磁盘四种压测

2.1 安装:Debian系和RedHat系各一条命令

stress是个非常轻量的小工具,主流Linux发行版基本都把它收进了官方软件源,不需要额外配置第三方仓库。我在测试机上验证完安装后,才会考虑在目标机器上安装,避免在生产环境临时装包引入不确定性。

# Debian / Ubuntu 系 sudo apt update sudo apt install -y stress # CentOS / RHEL / Fedora 系 sudo yum install -y stress # 新版 Fedora / RHEL 也可以直接 sudo dnf install -y stress

装完先跑一下stress --version,能输出二进制版本号说明工具可用。如果系统源里没有这个包(精简版发行版偶尔会遇到),就要走编译安装。编译安装也简单,先把编译工具链装好,再解压源码包依次执行configure、make、make install:

sudo apt install -y build-essential tar -xzf stress-*.tar.gz cd stress-*/ ./configure make sudo make install

源码包从软件源或项目发布页获取,stress-*按实际解压出的目录名替换。编译完成后同样用stress --version做验证。这里有一个经验:编译安装时尽量把源码解压到 /usr/local/src 这类系统目录,不要放在用户家目录下,避免权限混乱。

2.2 第一条压测命令:让CPU满载30秒

装好之后第一件事是确认它能产生真实负载。我用一条最小命令验证:生成1个CPU worker,持续运行30秒。

stress --cpu 1 --timeout 30

--cpu 1表示生成1个worker进程,这个进程内部会不断对一个随机数做平方根运算,从而占满一个逻辑核心;--timeout 30表示运行30秒后自动终止。如果机器只有1个核心,这条命令足以让整个系统几乎满载;如果是多核机器,从1开始观察负载曲线更稳妥。

正常跑完后,stress会打印一行successful run completed in 30s。这个输出说明工具本身工作正常,并且超时控制生效了。如果中途想停止压测,按 Ctrl+C 发送中断信号,stress会杀掉它管理的所有worker进程并退出,但已经产生的临时文件不会自动清理。

接下来试一下多核服务器上的常见用法:

stress --cpu 4 --timeout 60

在4核心机器上,这条命令会让4个worker各占一个核心,CPU总使用率接近100%。在8核心机器上跑--cpu 4,只有4个核心满载,另外4个核心保持空闲。理解这一点很重要:压测前先nproc确认核心数,再决定--cpu取多少。我的经验值是:等于核心数做满载测试,一半核心数做半载测试,超过核心数做超载测试。满载验证稳定性,半载验证性能余量,超载对系统冲击大,不适合在生产机上跑。

2.3 用uptime和mpstat确认压力真的生效

stress自己打印的日志只能说明它启动成功了,不能说明系统真的进入了高负载状态。压测过程中我会另开一个终端,用几条命令交叉验证:

uptime mpstat -P ALL 1 free -h vmstat 1 3

uptime主要看load average的第一个值,压测期间它会快速抬升。mpstat按1秒频率打印每个逻辑核心的使用率,正在跑CPU worker的核心%usr会接近100。free -h用于验证内存类压测,--vm-bytes设了多大,used就应该增加多少。vmstat 1 3同时能看到运行队列r、CPU user%、系统调用sy、IO等待wa几个关键指标。

只看stress自己的输出会出现一个盲区:worker启动了,但可能因为CPU配额、cgroup限制或者虚拟化抢占,实际分配到的时间片很少,压力根本没顶上去。所以我会再用pidstat确认单个worker的CPU占用:

pidstat -p $(pgrep -f 'stress --cpu' | head -1) 1

如果某个worker的%CPU接近100,说明它确实在满负荷运转;如果只有30%、50%,说明系统层面已经把它限住了,这台机器的真实负载能力需要重新评估。

3. stress压力参数拆解:CPU、内存、IO、磁盘与混合模式

3.1 CPU压测:--cpu N与系统核心数之间的关系

stress的CPU worker实现很朴素:每个worker进程在死循环里执行平方根运算,持续占用一个逻辑核心的整数和浮点运算单元。对于散热验证来说,3到5分钟持续满载就能让温度传感器读数明显上升;对于稳定性验证,一般至少跑30分钟以上。

选--cpu N时,先nproc看逻辑核心数。核心数以内最理想,比如4核机器--cpu 4,每个worker各占一个核心,互不争抢。超过核心数时,比如2核机器跑--cpu 4,4个worker会抢2个核心,load average会显得很高,但每个worker分到的时间片减半,整体吞吐量不升反降。我在给某模拟项目X做基准测试时,用--cpu 8在4核机器上跑,得到的性能数据完全没有参考价值,后来才发现核心数对不上。

--backoff是一个容易被忽略但很实用的参数,单位是微秒。它让每个worker在启动前先睡指定时间,分批进入满负荷状态,避免所有worker同一瞬间拉起造成负载尖峰。

stress --cpu 4 --backoff 100000 --timeout 60

这里100000微秒等于0.1秒,4个worker会按顺序错开启动。load average仍然会涨,但启动瞬间的“冲顶”平滑很多,适合在继续承载业务流量的机器上做温和压测。

3.2 内存压测:--vm、--vm-bytes、--vm-keep的搭配

内存压测是stress最容易把系统搞死的一个维度。原理是每个vm worker循环执行malloc分配内存、按步长touch每个页面、再free释放的流程。这里的touch很关键:Linux默认是延迟分配物理内存的,malloc成功只能说明虚拟内存够用,必须真正写入每个页面,物理内存才会被消耗掉。

默认情况下,每个vm worker分配的物理内存是256MB。一个完整用法是:

stress --vm 2 --vm-bytes 1G --vm-stride 64 --vm-keep --timeout 60

2个内存worker各占1GB,共2GB物理内存被持续占住。--vm-stride 64表示每64字节touch一次,保证每个4KB页面都被访问到;--vm-keep表示touch完内存后不释放,而是反复重新touch同一块区域。不加--vm-keep时,worker会在分配和释放之间高频切换,内存使用率波动很大,不容易观察稳定的占用量。

计算总内存占用时,要把--vm数和--vm-bytes相乘。2个worker各1GB就是2GB,如果机器本身只有2GB内存,加上系统常驻进程,OOM killer几乎必然被触发。我一般先执行free -h看available值,再让乘积不超过available的一半,给系统自身留足余量。这里没有玄学,纯粹是给内核留活路。

3.3 IO压测与磁盘压测:--io和--hdd的作用范围不一样

很多人以为stress --io N就是模拟磁盘IO压力,实际上它调用的是sync()系统调用,让内核把脏页写回磁盘。这个操作会对块设备产生一定压力,但更多是在消耗CPU。在SSD上跑--io,负载特征更接近CPU高占用,而不是纯粹的磁盘吞吐压力。这是一个容易误判的地方。

真正制造磁盘写入压力的是--hdd。每个hdd worker循环执行创建文件、写入数据、关闭、删除这个流程:

stress --hdd 2 --hdd-bytes 4G --hdd-nonzero --timeout 60

2个磁盘worker各写4GB,默认在当前目录下创建临时文件。不加--hdd-nonzero时写入全零字节,某些文件系统或压缩层会对全零块做特殊优化,导致实际落盘量低于预期;加上这个参数后写入非零数据,测出来的写入量更接近真实场景。跑完后worker会自动清理临时文件,但中途Ctrl+C中断则可能残留,需要手动清理。

--io和--hdd的选择要看目标:怀疑应用卡在块设备读写上,用--hdd制造吞吐压力;怀疑是频繁sync导致CPU升高,用--io复现高占用现象。两条路走的方向不一样。

3.4 混合压测:把多类压力叠加在一起

生产环境里单一瓶颈不常见,更多是CPU、内存、IO同时吃紧。stress允许一条命令指定多类worker:

stress --cpu 2 --vm 1 --vm-bytes 1G --io 1 --hdd 1 --hdd-bytes 2G --timeout 120

这条命令同时跑2个CPU worker、1个内存worker、1个IO worker、1个磁盘worker,持续120秒。各类型worker相互独立,stress创建进程组统一管理,任意一个崩溃不会影响其他worker继续跑。

混合压测时load average的预期值不能按“参数个数求和”来算。4核机器上跑--cpu 2 --vm 1 --io 1,IO worker和VM worker本身也会消耗CPU,实测load可能在3.5到4.0之间。正确做法是先跑30秒观察稳定值,再根据数据调整worker数量,而不是拍脑袋设定预期。

4. 让压测数据有说服力的三个步骤:基线、监控、判读

4.1 压测前先记录零负载基线

不做基线直接压测,是很多压测报告被质疑的根本原因。没有压测前的CPU空闲率、内存占用和load average,你没法证明压力是stress造成的,还是系统本来就一直在高负载。在压测前我会先记录一组60秒的基线数据:

uptime > /tmp/baseline_load.txt free -h >> /tmp/baseline_load.txt mpstat -P ALL 1 60 > /tmp/baseline_mpstat.txt vmstat 1 60 > /tmp/baseline_vmstat.txt

这些命令连续记录60秒的CPU使用率、负载均值、内存状态,输出保存到 /tmp 下。基线数据里最该关注的是idle百分比和load average——如果idle本来就只有30%,说明系统本来就不空闲,压测结果不能算在stress头上。

基线记录这一步经常被跳过去,尤其是时间紧张的时候。我的做法是把它固化到一个脚本里,每次压测前自动执行,不依赖手工操作。

4.2 压测中持续采样,别只看终点

我犯过的错误是“压完才想起来看数据”,结果只有零点和终点,中间过程全是盲区。现在的做法是压测的同时另开终端持续采集指标,采样频率不用太高,5秒一次足够:

watch -n 5 'uptime; free -h | head -2; mpstat -P ALL 1 1 | tail -5'

watch每5秒刷新一次负载和内存信息,mpstat -P ALL 1 1截取当前瞬间的CPU核心采样。多核场景下重点看是不是所有核心都均匀打满,负载是否稳定,有没有出现load先冲高再回落的抖动。稳定的压力表现是:负载在开始10到20秒逐步上升,然后稳定在一个区间不再大幅波动。如果曲线一直在抖,说明有别的定时任务或服务在抢资源。

如果需要归档,用循环采样更好,数据落盘后可以画趋势图:

for i in $(seq 1 60); do echo "$(date +%H:%M:%S) $(uptime)" >> /tmp/load_sample.txt sleep 5 done

这个循环跑5分钟,每5秒记一条带时间戳的load记录。压测结束后把采样文件和其他日志一起归档,作为性能验证报告的附件。

4.3 多快的load算正常,多高的CPU算合格

判读压测结果需要预期模型。单核机器上--cpu 1的load约为1.0;4核机器上--cpu 4的load约为4.0,每个核心user%持续接近100。如果负载没达到预期,比如4核机器跑--cpu 4而user%只有60%,原因通常是其他进程在竞争CPU,或者stress进程被cgroup、虚拟化限流。

内存压测的判读标准是物理内存被真实占用。free -h中的available应明显下降,实际占用量和--vm-bytes总量不能差太多。如果malloc了1GB但free显示可用内存没怎么变化,说明页面没有被touch到,检查是不是漏了--vm-stride,或者系统启用了一种特殊的内存overcommit模式。

磁盘压测的判读标准不是看磁盘用了多少,而是看块设备的忙闲状态。用iostat -x 1看%util和await:

指标合理范围异常信号
%util机械盘接近100%,SSD可能较低长期100%且await升高
await机械盘10-20ms,SSD低于2ms持续增长说明排队严重
w_await与设备类型相关明显高于基线说明写路径堵塞

stress的--hdd属于纯写入型负载,如果目标是测混合读写,默认方式就不够,需要配合其他工具一起做。判读的本质是拿压测数据和基线数据对比,而不是对比一个想象中的“标准值”。

5. stress压测避坑记录:四个真实翻车现场

5.1 内存Worker开太大,系统直接被OOM

现象:在8GB内存的物理机上执行stress --vm 2 --vm-bytes 4G --timeout 300,运行不到1分钟系统失去响应,SSH连接也断了,重连后通过dmesg确认是OOM killer触发并杀掉了大量进程。

原因:2个worker各占4GB,合计8GB,等于整机内存容量。系统本身还有常驻进程占用内存,内核为了保证自身存活只能启动OOM killer。更关键的是--vm-keep模式下内存不释放,OOM一旦触发就无法自动恢复。

解决:压测前先看free -h的available值,把--vm数和--vm-bytes的乘积控制在available的50%以内。如果确实要做OOM演练,也请在测试机上做,不要拿生产机冒险。这条翻车记录我后来每次讲内存压测都会提,因为代价太高了。

5.2 --hdd把根分区写满

现象:执行stress --hdd 1 --hdd-bytes 50G模拟大文件写入,结果几分钟后系统告警磁盘使用率超过90%,根分区被临时文件写满,服务日志开始报错。

原因:stress的hdd worker默认在当前用户目录创建临时文件,当前目录如果正位于根分区,数据就会直接占用系统盘空间。我当时忘了先执行df -h检查各分区剩余空间。

解决:指定一个专用工作目录,并限制写入总量不超过目标分区可用空间的30%。例如先mkdir -p /var/tmp/stress_test,再在该目录下执行压测命令。压测结束后检查目录下有没有类似stress.xxxx的临时文件,有就手动清理。这个坑的根本教训是:磁盘压测前必须先看磁盘分区,而不是只看总量。

5.3 没设timeout,压测变成无限跑

现象:执行stress --cpu 8后去开会,回来发现系统满载跑了2个多小时,期间业务响应明显变慢,造成了线上影响。

原因:--cpu、--io这类参数不设--timeout时,stress会一直运行到被信号终止。我当时没有注意这一点,也没有用timeout命令做外层兜底。

解决:现在每次跑stress都强制带--timeout,即便是10秒的短压测也带上。有时还会再用timeout 600 stress --cpu 8做双重保险。如果确实需要长时间压测,用nohup加日志输出,并在计划任务里设定自动kill时间:

timeout 3600 nohup stress --cpu 8 --vm 1 --vm-bytes 1G >> /tmp/stress_long.log 2>&1 &

这样即使忘记手动清理,一小时后也会自动结束。没有期限的压测等于事故,这个习惯一定要养成。

5.4 压测期间SSH断开,CPU满载不是唯一原因

现象:在云主机上跑stress --cpu 8 --timeout 600,跑了一会儿SSH窗口失去响应,重连很慢,但控制台的CPU监控只显示约70%使用率。

原因:云主机的CPU配额有限,8个worker在争抢受限CPU资源时会触发宿主机的调度限制,SSH进程能分到的CPU时间也被挤占,网络包处理延迟,连接就断了。这不是stress本身的bug,而是云环境资源约束带来的“假死”。

解决:云服务器上做压测前,先查清楚实例规格的CPU配额,是否支持长时间满载。临时验证可以减半--cpu数,或者用taskset把stress绑定到指定核心,给系统保留余量:

taskset -c 0,1 stress --cpu 2 --timeout 300

这条命令只让stress在0号和1号核心上跑,其他核心留给系统进程和SSH通信。压测结束后立刻用pkill -f stress清理所有残余进程,避免压测进程残留。

6. 把stress变成压测骨架:一个可复用的自动化压测脚本

6.1 脚本设计:基线、加压、采样、清理一次完成

手工跑stress最大的问题是数据分散:基线在一处,压测输出在一处,采样记录又在另一处,最后归档要拼半天。我用一个bash脚本把链路串起来:

#!/bin/bash # usage: ./stress_run.sh <duration_seconds> <report_name> DURATION=${1:-300} NAME=${2:-report} CPU_CORES=$(nproc) RDIR="/tmp/stress_${NAME}_$(date +%Y%m%d_%H%M%S)" mkdir -p "$RDIR" # 1. 基线 uptime > "$RDIR/baseline.txt" free -h >> "$RDIR/baseline.txt" cat /proc/loadavg >> "$RDIR/baseline.txt" # 2. 启动压测 stress --cpu $((CPU_CORES/2)) --vm 1 --vm-bytes 512M \ --hdd 1 --hdd-bytes 1G --timeout "$DURATION" \ > "$RDIR/stress.log" 2>&1 & SPID=$! # 3. 周期采样 END=$((SECONDS + DURATION)) while [ $SECONDS -lt $END ]; do echo "$(date +%T) $(uptime)" >> "$RDIR/load.txt" sleep 10 done # 4. 等待结束并汇总 wait $SPID echo "done -> $RDIR"

脚本逻辑:默认压5分钟,用一半核心数做CPU压测,叠加512MB内存worker和1GB磁盘worker,每10秒记一次load。$SECONDS是bash内置变量,配合$DURATION控制采样总时长。命令最后的&让stress在后台运行,主脚本继续执行采样循环,压测结束后所有数据都在以时间戳命名的目录里,直接打包归档。

实际使用时要改三处:--hdd-bytes根据目标分区剩余空间调整;CPU_CORES/2如果要做全量压测就改成$CPU_CORES;采样间隔从10秒改成1秒能看到更细的负载攀升过程,但日志文件会大很多。脚本里没有做worker残留清理,建议压测结束后跑一次pkill -f stress确认进程都退干净了。

我的习惯是压测结束后再记录一次内核版本和stress版本号,一起存进报告目录。因为不同内核版本对内存分配、IO调度的表现有明显差异,这个存档能解释“为什么这次压测数据和上次不一样”的疑问。stress工具本身很简单,但一套完整的压测流程需要基线、采样、版本记录这些东西兜底,缺一个都会让数据失去说服力。希望这篇能帮你在下次压测时少踩几个坑。

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/10 3:23:12

Docker镜像优化:.dockerignore与多阶段构建实战

写这篇东西是因为我见过太多人“会用 Docker”但没用好 Docker。随手写一个 Dockerfile 能跑起来&#xff0c;和写一个既小、又快、又安全的 Dockerfile&#xff0c;中间差的远不止几条命令的距离。这期就聊聊我实际项目里几乎每套 CI/CD 都在用的组合拳&#xff1a;.dockerign…

作者头像 李华
网站建设 2026/10/10 3:23:12

Docker部署开源配置中心:容器化落地全流程与踩坑实录

先说个现象&#xff1a;很多团队第一次接触这套开源配置中心时&#xff0c;第一反应都是去官网把二进制包下载下来&#xff0c;解压、改脚本、配环境变量、注册系统服务&#xff0c;整套流程走下来没个半天搞不定&#xff0c;中途还会踩到版本不兼容、内存不足、启动脚本权限之…

作者头像 李华
网站建设 2026/10/10 3:23:08

MCP网关迁移实战:从Klavis到Zapier、ContextForge与Peta的组合方案

1. 为什么要把 Klavis 的 MCP 网关换掉这几天折腾了一件挺大的事&#xff1a;把我们自建的 Klavis MCP 网关替换掉。先说结论&#xff1a;Klavis 不是不能用&#xff0c;而是当工具数量从 3 个涨到 30 个&#xff0c;调用频率从每天几千次涨到几十万次之后&#xff0c;网关本身…

作者头像 李华
网站建设 2026/10/10 3:23:08

测试工程师必会Linux命令:日志分析与自动化实战

咱们做测试的&#xff0c;平时没少跟 Linux 打交道。不管是被测系统部署在 Linux 服务器上&#xff0c;还是用 Linux 环境搭测试工具、跑自动化脚本、分析日志&#xff0c;哪天离开这东西还真不行。但这个知识点在学校和培训班里往往讲得过于“教科书化”&#xff0c;一上来就是…

作者头像 李华
网站建设 2026/10/10 3:22:49

SpringBoot师资管理系统实战:教师资源调度与排课冲突检测解析

师资管理系统这类题目&#xff0c;算是Java方向毕业设计里非常经典的一道题了。每年都有大量学生选它&#xff0c;原因很简单&#xff1a;业务场景清晰、技术栈主流、功能边界好把控。但越经典的题目越容易做成一锅乱炖——教师信息、课程管理、排班调度、职称评审&#xff0c;…

作者头像 李华
网站建设 2026/10/10 3:21:31

Docker/Kubernetes集群连接超时:conntrack表满排查实录

某个工作日的下午&#xff0c;某业务集群的服务可用率监控曲线突然开始抖动。告警里报的是 A 服务调用 B 服务时出现大量连接超时&#xff0c;应用日志里刷出一屏又一屏curl 56 recv failure: 连接超时。当时第一反应是服务出问题了&#xff0c;可登录节点一看&#xff0c;Dock…

作者头像 李华