vmstat 是Linux系统中用于报告虚拟内存统计信息的命令。它可以显示有关进程、内存、分页、块IO、陷阱和CPU活动的信息。vmstat对于识别系统瓶颈和性能问题非常有用,特别是在内存和CPU资源方面。
vmstat [选项] [延迟 [次数]]
| 选项 | 说明 |
|---|---|
-a, --active |
显示活跃和非活跃内存 |
-f, --forks |
显示自系统启动以来的fork数量 |
-m, --slabs |
显示slab信息 |
-n, --one-header |
只显示一次头部信息 |
-s, --stats |
显示事件计数器和内存统计 |
-d, --disk |
显示磁盘统计 |
-D, --disk-sum |
显示磁盘统计摘要 |
-p, --partition 设备 |
显示指定分区的详细统计 |
-S, --unit 字符 |
指定显示单位(k, K, m, M) |
-t, --timestamp |
为每行输出添加时间戳 |
-w, --wide |
宽输出模式 |
-V, --version |
显示版本信息 |
-h, --help |
显示帮助信息 |
| 字段 | 说明 | 示例值 |
|---|---|---|
| Procs (进程) | ||
| r (Running) | 运行队列中等待运行的进程数 | 0 |
| b (Blocked) | 处于不可中断睡眠状态的进程数 | 0 |
| Memory (内存) | ||
| swpd | 已使用的虚拟内存大小(交换空间) | 0 KB |
| free | 空闲的物理内存大小 | 263168 KB |
| buff | 用作缓冲区的内存大小 | 7216 KB |
| cache | 用作缓存的内存大小 | 217820 KB |
| inact (-a选项) | 非活跃内存大小 | 123456 KB |
| active (-a选项) | 活跃内存大小 | 345678 KB |
| Swap (交换) | ||
| si (Swap In) | 从磁盘交换到内存的数据量(KB/s) | 0 KB/s |
| so (Swap Out) | 从内存交换到磁盘的数据量(KB/s) | 0 KB/s |
| IO (输入输出) | ||
| bi (Blocks In) | 从块设备接收的块数(块/s) | 0 块/s |
| bo (Blocks Out) | 发送到块设备的块数(块/s) | 0 块/s |
| System (系统) | ||
| in (Interrupts) | 每秒中断数(包括时钟中断) | 1 次/s |
| cs (Context Switches) | 每秒上下文切换次数 | 100 次/s |
| CPU (中央处理器) | ||
| us (User Time) | 用户进程占用CPU时间百分比 | 0 % |
| sy (System Time) | 系统进程占用CPU时间百分比 | 0 % |
| id (Idle Time) | CPU空闲时间百分比 | 99 % |
| wa (Wait IO) | 等待IO的CPU时间百分比 | 0 % |
| st (Stolen Time) | 虚拟化环境中被偷取的时间百分比 | 0 % |
显示虚拟内存统计信息:
# 显示一次统计信息
vmstat
# 显示活跃和非活跃内存
vmstat -a
# 宽输出模式
vmstat -w
# 示例输出:
# procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
# r b swpd free buff cache si so bi bo in cs us sy id wa st
# 0 0 0 263168 7216 217820 0 0 0 0 1 100 0 0 99 0 0
以指定间隔连续显示统计信息:
# 每2秒刷新一次,持续显示
vmstat 2
# 每5秒刷新一次,显示10次后停止
vmstat 5 10
# 添加时间戳
vmstat -t 2
# 只显示一次头部信息
vmstat -n 2
# 示例输出(连续模式):
# procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
# r b swpd free buff cache si so bi bo in cs us sy id wa st
# 0 0 0 263168 7216 217820 0 0 0 0 1 100 0 0 99 0 0
# 1 0 0 263120 7216 217820 0 0 0 0 123 456 5 2 93 0 0
# 0 0 0 263100 7216 217820 0 0 0 2 89 345 3 1 96 0 0
显示系统事件计数器和内存统计摘要:
# 显示系统统计摘要
vmstat -s
# 示例输出:
# 4095996 K total memory
# 3804188 K used memory
# 2053144 K active memory
# 1168940 K inactive memory
# 291808 K free memory
# 12636 K buffer memory
# 1625488 K swap cache
# 4194300 K total swap
# 0 K used swap
# 4194300 K free swap
# 375586 non-nice user cpu ticks
# 1550 nice user cpu ticks
# 348438 system cpu ticks
# 25836313 idle cpu ticks
# 10432 IO-wait cpu ticks
# 66 IRQ cpu ticks
# 1675 softirq cpu ticks
# 0 stolen cpu ticks
# 1234567 pages paged in
# 2345678 pages paged out
# 0 pages swapped in
# 0 pages swapped out
# 3456789 interrupts
# 4567890 CPU context switches
# 1651234567 boot time
# 1234567 forks
显示磁盘和分区统计信息:
# 显示磁盘统计信息
vmstat -d
# 显示磁盘统计摘要
vmstat -D
# 显示指定分区的详细统计
vmstat -p /dev/sda1
# 示例输出(磁盘统计):
# disk- ------------reads------------ ------------writes----------- -----IO------
# total merged sectors ms total merged sectors ms cur sec
# sda 12345 678 1234567 4567 8901 234 890123 3456 0 12
# sdb 9876 543 987654 3210 7654 321 765432 2345 0 8
显示内核slab缓存信息:
# 显示slab信息
vmstat -m
# 显示特定单位的slab信息
vmstat -m | head -20
# 示例输出:
# Cache Num Total Size Pages
# ext4_inode_cache 1234 1500 928 44
# dentry 5678 6000 192 21
# buffer_head 3456 4000 104 39
# ...
# 显示自系统启动以来的fork数量
vmstat -f
# 示例输出:
# 1234567 forks
# 以KB为单位显示(默认)
vmstat
# 以千字节为单位(k=1000, K=1024)
vmstat -S k # 1000字节为单位
vmstat -S K # 1024字节为单位
# 以MB为单位
vmstat -S m # 1000×1000字节为单位
vmstat -S M # 1024×1024字节为单位
# 示例(以MB为单位):
# procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
# r b swpd free buff cache si so bi bo in cs us sy id wa st
# 0 0 0 257 7 212 0 0 0 0 1 100 0 0 99 0 0
#!/bin/bash
# 脚本1:系统性能监控
echo "=== 系统性能监控 ==="
echo "开始时间: $(date)"
echo ""
# 监控10次,间隔2秒
echo "监控系统性能(10次采样,间隔2秒):"
vmstat -n 2 10
# 提取关键指标
echo ""
echo "性能指标分析:"
# 获取最后一次vmstat输出(跳过前两行头部信息)
LAST_STATS=$(vmstat 1 2 | tail -1)
# 解析各个字段
IFS=' ' read -r r b swpd free buff cache si so bi bo in cs us sy id wa st <<< "$LAST_STATS"
echo "运行队列进程数 (r): $r"
echo "阻塞进程数 (b): $b"
echo "CPU用户时间 (us): ${us}%"
echo "CPU系统时间 (sy): ${sy}%"
echo "CPU空闲时间 (id): ${id}%"
echo "CPU等待IO时间 (wa): ${wa}%"
echo "已用交换空间 (swpd): ${swpd} KB"
echo "空闲内存 (free): ${free} KB"
# 性能阈值检查
if [ "$r" -gt 5 ]; then
echo "⚠️ 警告: 运行队列过长,可能存在CPU瓶颈"
fi
if [ "$wa" -gt 20 ]; then
echo "⚠️ 警告: IO等待时间过高,可能存在磁盘瓶颈"
fi
if [ "$swpd" -gt 1000 ]; then
echo "⚠️ 警告: 交换空间使用过高,可能存在内存不足"
fi
# 脚本2:系统基准测试
echo ""
echo "=== 系统基准测试 ==="
echo "运行基准测试30秒..."
# 创建临时文件记录vmstat输出
TEMP_FILE=$(mktemp)
vmstat -n 1 30 > "$TEMP_FILE"
# 分析结果
echo "基准测试完成,分析结果:"
# 计算平均值
AVG_R=$(awk 'NR>2 {sum+=$1} END {print sum/(NR-2)}' "$TEMP_FILE")
AVG_B=$(awk 'NR>2 {sum+=$2} END {print sum/(NR-2)}' "$TEMP_FILE")
AVG_US=$(awk 'NR>2 {sum+=$13} END {print sum/(NR-2)}' "$TEMP_FILE")
AVG_SY=$(awk 'NR>2 {sum+=$14} END {print sum/(NR-2)}' "$TEMP_FILE")
AVG_ID=$(awk 'NR>2 {sum+=$15} END {print sum/(NR-2)}' "$TEMP_FILE")
AVG_WA=$(awk 'NR>2 {sum+=$16} END {print sum/(NR-2)}' "$TEMP_FILE")
printf "平均运行队列: %.2f\n" "$AVG_R"
printf "平均阻塞进程: %.2f\n" "$AVG_B"
printf "平均CPU用户时间: %.2f%%\n" "$AVG_US"
printf "平均CPU系统时间: %.2f%%\n" "$AVG_SY"
printf "平均CPU空闲时间: %.2f%%\n" "$AVG_ID"
printf "平均CPU等待IO: %.2f%%\n" "$AVG_WA"
# 清理临时文件
rm -f "$TEMP_FILE"
# 脚本3:实时监控告警
echo ""
echo "=== 实时监控告警系统 ==="
echo "按Ctrl+C停止监控"
echo ""
# 设置阈值
CPU_THRESHOLD=80
MEM_THRESHOLD=90
WAIT_THRESHOLD=20
while true; do
# 获取当前状态
CURRENT=$(vmstat 1 2 | tail -1)
IFS=' ' read -r r b swpd free buff cache si so bi bo in cs us sy id wa st <<< "$CURRENT"
# 检查CPU使用率
CPU_USAGE=$((100 - id))
if [ "$CPU_USAGE" -gt "$CPU_THRESHOLD" ]; then
echo "[$(date)] ⚠️ CPU使用率过高: ${CPU_USAGE}% (us:${us}%, sy:${sy}%)"
fi
# 检查IO等待
if [ "$wa" -gt "$WAIT_THRESHOLD" ]; then
echo "[$(date)] ⚠️ IO等待过高: ${wa}%"
fi
# 检查交换空间使用
if [ "$swpd" -gt 10000 ]; then
echo "[$(date)] ⚠️ 交换空间使用过高: ${swpd}KB"
fi
# 检查运行队列
if [ "$r" -gt 10 ]; then
echo "[$(date)] ⚠️ 运行队列过长: ${r}个进程"
fi
sleep 5
done
| 指标 | 正常范围 | 可能的问题 | 解决方案 |
|---|---|---|---|
| 运行队列 (r) | < CPU核心数 | CPU瓶颈 | 升级CPU、优化进程、增加核心数 |
| 阻塞进程 (b) | 接近0 | I/O瓶颈、磁盘问题 | 优化I/O、升级磁盘、使用SSD |
| 交换空间 (swpd) | 接近0 | 内存不足 | 增加物理内存、优化应用程序内存使用 |
| 交换活动 (si/so) | 接近0 | 内存交换频繁 | 增加内存、调整swappiness参数 |
| CPU空闲 (id) | > 20% | 通常正常,过低表示CPU繁忙 | 优化CPU密集型进程、负载均衡 |
| CPU等待 (wa) | < 5% | I/O瓶颈 | 优化磁盘I/O、使用RAID、增加缓存 |
| 上下文切换 (cs) | 取决于系统负载 | 过高表示进程频繁切换 | 减少进程数、调整进程优先级 |
| 中断数 (in) | 取决于硬件 | 过高可能表示硬件问题 | 检查硬件、更新驱动程序 |
# 内存相关指标详解:
# 1. swpd: 已使用的虚拟内存(交换空间)
# - 如果swpd > 0,表示系统正在使用交换空间
# - 持续增长的swpd表示内存不足
# 2. free: 空闲内存
# - Linux会尽可能使用空闲内存作为缓存和缓冲区
# - free值低不一定表示内存不足
# 3. buff: 缓冲区内存
# - 用于存储文件系统元数据和目录信息
# - 通常占用较少内存
# 4. cache: 页面缓存
# - 用于缓存从磁盘读取的数据
# - 当应用程序需要更多内存时,这部分内存可以被释放
# 5. active/inactive: 活跃/非活跃内存(使用-a选项)
# - active: 最近被访问的内存页
# - inactive: 较少被访问的内存页
# - 当内存不足时,inactive内存会先被回收
# 计算实际可用内存:
# 可用内存 = free + buff + cache + inactive
#!/bin/bash
# 脚本1:系统性能趋势分析
echo "=== 系统性能趋势分析 ==="
echo "开始分析: $(date)"
echo ""
# 创建分析目录
ANALYSIS_DIR="/tmp/vmstat_analysis_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$ANALYSIS_DIR"
# 收集数据(30秒,每秒一次)
echo "收集性能数据(30秒)..."
vmstat -n -t 1 30 > "$ANALYSIS_DIR/raw_data.txt"
# 提取时间序列数据
echo "提取时间序列数据..."
awk 'NR>2 {print $1}' "$ANALYSIS_DIR/raw_data.txt" > "$ANALYSIS_DIR/r_series.txt"
awk 'NR>2 {print $13}' "$ANALYSIS_DIR/raw_data.txt" > "$ANALYSIS_DIR/us_series.txt"
awk 'NR>2 {print $14}' "$ANALYSIS_DIR/raw_data.txt" > "$ANALYSIS_DIR/sy_series.txt"
awk 'NR>2 {print $16}' "$ANALYSIS_DIR/raw_data.txt" > "$ANALYSIS_DIR/wa_series.txt"
# 生成统计摘要
echo "生成统计摘要..."
{
echo "性能分析报告"
echo "============="
echo "分析时间: $(date)"
echo "采样数量: 30"
echo ""
echo "运行队列统计 (r):"
echo " 最大值: $(sort -nr "$ANALYSIS_DIR/r_series.txt" | head -1)"
echo " 最小值: $(sort -n "$ANALYSIS_DIR/r_series.txt" | head -1)"
echo " 平均值: $(awk '{sum+=$1} END {print sum/NR}' "$ANALYSIS_DIR/r_series.txt")"
echo ""
echo "CPU用户时间统计 (us):"
echo " 最大值: $(sort -nr "$ANALYSIS_DIR/us_series.txt" | head -1)%"
echo " 最小值: $(sort -n "$ANALYSIS_DIR/us_series.txt" | head -1)%"
echo " 平均值: $(awk '{sum+=$1} END {print sum/NR}' "$ANALYSIS_DIR/us_series.txt")%"
echo ""
echo "CPU系统时间统计 (sy):"
echo " 最大值: $(sort -nr "$ANALYSIS_DIR/sy_series.txt" | head -1)%"
echo " 最小值: $(sort -n "$ANALYSIS_DIR/sy_series.txt" | head -1)%"
echo " 平均值: $(awk '{sum+=$1} END {print sum/NR}' "$ANALYSIS_DIR/sy_series.txt")%"
echo ""
echo "CPU等待IO统计 (wa):"
echo " 最大值: $(sort -nr "$ANALYSIS_DIR/wa_series.txt" | head -1)%"
echo " 最小值: $(sort -n "$ANALYSIS_DIR/wa_series.txt" | head -1)%"
echo " 平均值: $(awk '{sum+=$1} END {print sum/NR}' "$ANALYSIS_DIR/wa_series.txt")%"
} > "$ANALYSIS_DIR/summary_report.txt"
echo "分析完成,报告保存在: $ANALYSIS_DIR/summary_report.txt"
# 脚本2:自动性能基准测试
echo ""
echo "=== 自动性能基准测试 ==="
# 定义测试场景
declare -A TEST_SCENARIOS=(
["空闲状态"]="sleep 10"
["CPU密集型"]="dd if=/dev/zero of=/dev/null bs=1M count=1000 2>/dev/null"
["内存访问"]="stress-ng --vm 1 --vm-bytes 1G --timeout 10s 2>/dev/null || echo 'stress-ng未安装'"
["磁盘写入"]="dd if=/dev/zero of=/tmp/testfile bs=1M count=100 2>/dev/null"
)
for SCENARIO in "${!TEST_SCENARIOS[@]}"; do
echo ""
echo "测试场景: $SCENARIO"
echo "开始测试..."
# 在后台运行测试任务
eval "${TEST_SCENARIOS[$SCENARIO]}" &
TEST_PID=$!
# 监控系统性能
vmstat -n 1 10 > "/tmp/vmstat_${SCENARIO}.txt" 2>/dev/null
# 等待测试完成
wait $TEST_PID 2>/dev/null
# 分析结果
AVG_CPU_US=$(awk 'NR>2 {sum+=$13} END {print sum/(NR-2)}' "/tmp/vmstat_${SCENARIO}.txt")
AVG_CPU_WA=$(awk 'NR>2 {sum+=$16} END {print sum/(NR-2)}' "/tmp/vmstat_${SCENARIO}.txt")
echo " 平均CPU使用率: ${AVG_CPU_US}%"
echo " 平均IO等待: ${AVG_CPU_WA}%"
# 清理
rm -f "/tmp/vmstat_${SCENARIO}.txt"
done
# 清理测试文件
rm -f /tmp/testfile
echo ""
echo "基准测试完成"
# 脚本3:系统健康检查
echo ""
echo "=== 系统健康检查 ==="
# 检查点列表
CHECKS=(
"内存使用" "free -h | grep 'Mem:'"
"交换空间" "swapon --show"
"CPU信息" "lscpu | grep -E 'CPU\(s\):|Model name:'"
"磁盘空间" "df -h /"
"系统负载" "uptime"
"vmstat摘要" "vmstat -s | head -20"
)
for ((i=0; i<${#CHECKS[@]}; i+=2)); do
CHECK_NAME="${CHECKS[$i]}"
CHECK_CMD="${CHECKS[$((i+1))]}"
echo ""
echo "检查: $CHECK_NAME"
echo "----------------------------------------"
eval "$CHECK_CMD"
done
# 运行vmstat监控10秒
echo ""
echo "实时性能监控(10秒):"
vmstat -n 1 10
echo ""
echo "系统健康检查完成"
# 1. vmstat命令不存在
# 检查是否安装
which vmstat
# 安装(如果需要)
# Ubuntu/Debian: sudo apt-get install procps
# RHEL/CentOS: sudo yum install procps-ng
# 2. 输出信息不完整
# 使用宽输出模式
vmstat -w
# 检查系统/proc文件系统
ls -la /proc/stat
ls -la /proc/meminfo
# 3. 内存统计不准确
# 使用其他工具验证
free -h
cat /proc/meminfo
# 4. 磁盘统计不显示
# 需要root权限查看完整磁盘信息
sudo vmstat -d
# 检查磁盘设备权限
ls -la /dev/sd*
# 5. 采样间隔问题
# 间隔太短可能造成系统负载
# 建议最小间隔为1秒
# 6. 虚拟化环境中的问题
# 检查是否支持完整的/proc文件系统
# 某些容器环境可能限制访问
# 7. 解释输出值
# 理解各个字段的含义(参考上面的字段解析表)
# 8. 性能问题诊断
# 结合其他工具一起使用
top
iostat
sar
mpstat
# 9. 历史数据对比
# 保存不同时间点的vmstat输出进行对比
vmstat 5 10 > vmstat_before.txt
# ...进行系统变更...
vmstat 5 10 > vmstat_after.txt
diff vmstat_before.txt vmstat_after.txt
# 10. 自动化监控
# 设置cron任务定期收集vmstat数据
# 在/etc/crontab中添加:
# */5 * * * * root /usr/bin/vmstat -n 1 5 >> /var/log/vmstat.log