linux vmstat命令

提示:vmstat命令用于报告虚拟内存统计信息,包括进程、内存、分页、块IO、陷阱、CPU活动等,是系统性能监控的重要工具。

命令简介

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 %

使用示例

示例1:基本使用

显示虚拟内存统计信息:

# 显示一次统计信息
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:连续监控

以指定间隔连续显示统计信息:

# 每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

示例3:显示系统统计摘要

显示系统事件计数器和内存统计摘要:

# 显示系统统计摘要
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

示例4:显示磁盘统计信息

显示磁盘和分区统计信息:

# 显示磁盘统计信息
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

示例5:显示slab信息

显示内核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
# ...

示例6:显示fork数量

# 显示自系统启动以来的fork数量
vmstat -f

# 示例输出:
#       1234567 forks

示例7:指定显示单位

# 以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

示例8:在脚本中使用vmstat

#!/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

在脚本中使用vmstat的高级示例

#!/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的第一行输出显示的是自系统启动以来的平均值,后续行显示的是采样间隔内的数据
  2. 在虚拟化环境中,st(stolen time)字段表示被宿主机偷取的CPU时间
  3. si(swap in)和so(swap out)持续大于0表示系统存在内存压力
  4. wa(wait IO)值过高通常表示磁盘I/O瓶颈
  5. r(running processes)值持续高于CPU核心数表示CPU资源不足
  6. buff和cache内存会被Linux内核在需要时自动释放,不应视为内存泄漏
  7. vmstat显示的内存单位默认为KB,使用-S选项可以更改单位
  8. 某些选项(如-m、-d)可能需要root权限才能显示完整信息
  9. vmstat的采样间隔不宜设置过短,否则可能影响系统性能

故障排查

# 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

相关命令

  • top - 实时显示进程状态和系统负载
  • htop - top的增强版,交互式进程查看器
  • free - 显示内存使用情况
  • iostat - 显示CPU和I/O统计信息
  • mpstat - 显示每个CPU的使用情况
  • sar - 系统活动报告工具
  • dstat - 多功能系统资源统计工具
  • glances - 高级系统监控工具
  • nmon - 性能监控工具
  • ps - 显示当前进程状态
  • vmstat - 虚拟内存统计(本命令)
  • netstat - 显示网络连接和统计
  • ss - netstat的现代替代品