Linux服务器压力测试交互式脚本

Linux服务器压力测试交互式脚本

Kernel
2025-11-07 / 0 评论 / 3 阅读

代码

#!/bin/bash

# 服务器压力测试交互式脚本
# 支持:CPU压力测试、内存压力测试、磁盘I/O测试、网络测试、综合压力测试

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

# 检查必要工具
check_tools() {
    local missing_tools=()
    
    echo -e "${CYAN}检查必要的工具...${NC}"
    
    # 检查是否安装stress
    if ! command -v stress &> /dev/null; then
        missing_tools+=("stress")
    fi
    
    # 检查是否安装sysbench
    if ! command -v sysbench &> /dev/null; then
        missing_tools+=("sysbench")
    fi
    
    # 检查是否安装iperf3
    if ! command -v iperf3 &> /dev/null; then
        missing_tools+=("iperf3")
    fi
    
    # 检查是否安装fio
    if ! command -v fio &> /dev/null; then
        missing_tools+=("fio")
    fi
    
    # 检查是否安装htop
    if ! command -v htop &> /dev/null; then
        missing_tools+=("htop")
    fi
    
    # 检查是否安装nload
    if ! command -v nload &> /dev/null; then
        missing_tools+=("nload")
    fi
    
    if [ ${#missing_tools[@]} -gt 0 ]; then
        echo -e "${YELLOW}以下工具未安装: ${missing_tools[*]}${NC}"
        read -p "是否要安装这些工具?(y/n): " install_choice
        
        if [[ $install_choice == "y" || $install_choice == "Y" ]]; then
            install_missing_tools "${missing_tools[@]}"
        else
            echo -e "${YELLOW}部分功能可能无法使用${NC}"
        fi
    else
        echo -e "${GREEN}所有必要工具已安装${NC}"
    fi
}

# 安装缺失的工具
install_missing_tools() {
    local tools=("$@")
    
    echo -e "${CYAN}开始安装工具...${NC}"
    
    # 检测包管理器
    if command -v apt &> /dev/null; then
        sudo apt update
        sudo apt install -y "${tools[@]}"
    elif command -v yum &> /dev/null; then
        sudo yum install -y epel-release
        sudo yum install -y "${tools[@]}"
    elif command -v dnf &> /dev/null; then
        sudo dnf install -y epel-release
        sudo dnf install -y "${tools[@]}"
    else
        echo -e "${RED}无法确定包管理器,请手动安装缺失的工具${NC}"
        echo "需要安装: ${tools[*]}"
        return 1
    fi
    
    echo -e "${GREEN}工具安装完成${NC}"
}

# 显示系统信息
show_system_info() {
    echo -e "\n${CYAN}========== 系统信息 ==========${NC}"
    
    # CPU信息
    echo -e "${GREEN}CPU信息:${NC}"
    echo -e "  型号: $(lscpu | grep "Model name" | cut -d':' -f2 | xargs)"
    echo -e "  核心数: $(nproc)"
    echo -e "  线程数: $(lscpu | grep "^CPU(s):" | awk '{print $2}')"
    
    # 内存信息
    echo -e "${GREEN}内存信息:${NC}"
    free -h | awk 'NR==1{print "  "$0} NR==2{print "  "$0}'
    
    # 磁盘信息
    echo -e "${GREEN}磁盘信息:${NC}"
    df -h / | awk 'NR==1{print "  "$0} NR==2{print "  "$0}'
    
    # 系统负载
    echo -e "${GREEN}系统负载:${NC}"
    uptime | awk -F'load average:' '{print "  "$2}'
}

# CPU压力测试
cpu_stress_test() {
    echo -e "\n${CYAN}========== CPU压力测试 ==========${NC}"
    
    read -p "请输入CPU核心数(默认全部): " cpu_cores
    if [ -z "$cpu_cores" ]; then
        cpu_cores=$(nproc)
    fi
    
    read -p "请输入测试时间(秒,默认60): " duration
    if [ -z "$duration" ]; then
        duration=60
    fi
    
    read -p "请输入负载类型 (1:计算 2:浮点 3:混合,默认3): " load_type
    case $load_type in
        1) stress_args="--cpu $cpu_cores --cpu-method matrixprod" ;;
        2) stress_args="--cpu $cpu_cores --cpu-method fft" ;;
        *) stress_args="--cpu $cpu_cores" ;;
    esac
    
    echo -e "${YELLOW}开始CPU压力测试,持续 ${duration} 秒...${NC}"
    echo -e "使用核心数: ${cpu_cores}"
    
    # 显示测试前CPU信息
    echo -e "\n${GREEN}测试前CPU使用率:${NC}"
    mpstat 1 1 | tail -2
    
    # 开始压力测试
    stress $stress_args --timeout ${duration}s &
    stress_pid=$!
    
    # 监控CPU使用率
    echo -e "\n${GREEN}测试中监控(每秒刷新):${NC}"
    for ((i=1; i<=duration; i++)); do
        if ps -p $stress_pid > /dev/null; then
            echo -ne "\r测试进行中: ${i}/${duration}秒 - CPU使用率: "
            top -bn1 | grep "Cpu(s)" | awk '{printf "%.1f%%", $2}'
            sleep 1
        else
            break
        fi
    done
    
    wait $stress_pid
    echo -e "\n${GREEN}CPU压力测试完成${NC}"
}

# 内存压力测试
memory_stress_test() {
    echo -e "\n${CYAN}========== 内存压力测试 ==========${NC}"
    
    # 获取可用内存
    total_mem=$(free -m | awk '/^Mem:/{print $2}')
    available_mem=$(free -m | awk '/^Mem:/{print $7}')
    
    echo -e "总内存: ${total_mem}MB"
    echo -e "可用内存: ${available_mem}MB"
    
    read -p "请输入要测试的内存大小(MB,默认可用内存的80%): " mem_size
    if [ -z "$mem_size" ]; then
        mem_size=$((available_mem * 80 / 100))
    fi
    
    if [ $mem_size -gt $available_mem ]; then
        echo -e "${RED}警告: 请求的内存超过可用内存,将使用可用内存的90%${NC}"
        mem_size=$((available_mem * 90 / 100))
    fi
    
    read -p "请输入测试时间(秒,默认30): " duration
    if [ -z "$duration" ]; then
        duration=30
    fi
    
    echo -e "${YELLOW}开始内存压力测试...${NC}"
    echo -e "测试内存: ${mem_size}MB"
    echo -e "持续时间: ${duration}秒"
    
    # 显示测试前内存信息
    echo -e "\n${GREEN}测试前内存使用:${NC}"
    free -m
    
    # 开始内存压力测试
    stress --vm 1 --vm-bytes ${mem_size}M --vm-keep --timeout ${duration}s &
    stress_pid=$!
    
    # 监控内存使用
    echo -e "\n${GREEN}测试中内存监控:${NC}"
    for ((i=1; i<=duration; i+=5)); do
        if ps -p $stress_pid > /dev/null; then
            echo -e "时间: ${i}秒"
            free -m | grep "^Mem:"
            sleep 5
        else
            break
        fi
    done
    
    wait $stress_pid
    echo -e "\n${GREEN}内存压力测试完成${NC}"
    echo -e "${GREEN}测试后内存使用:${NC}"
    free -m
}

# 磁盘I/O测试
disk_io_test() {
    echo -e "\n${CYAN}========== 磁盘I/O测试 ==========${NC}"
    
    echo -e "${GREEN}可用磁盘:${NC}"
    df -h | grep -v tmpfs
    
    read -p "请输入测试目录路径(默认/tmp): " test_dir
    if [ -z "$test_dir" ]; then
        test_dir="/tmp"
    fi
    
    if [ ! -d "$test_dir" ]; then
        echo -e "${RED}目录不存在,使用/tmp${NC}"
        test_dir="/tmp"
    fi
    
    # 创建测试文件路径
    test_file="${test_dir}/io_test_${RANDOM}.dat"
    
    echo -e "\n请选择测试类型:"
    echo "1) 顺序读写测试"
    echo "2) 随机读写测试"
    echo "3) 混合读写测试"
    read -p "请选择 (默认1): " test_type
    
    read -p "请输入文件大小(默认1GB): " file_size
    if [ -z "$file_size" ]; then
        file_size="1G"
    fi
    
    read -p "请输入测试时间(秒,默认30): " duration
    if [ -z "$duration" ]; then
        duration=30
    fi
    
    echo -e "${YELLOW}开始磁盘I/O测试...${NC}"
    
    case $test_type in
        2)
            # 随机读写
            fio_cmd="--name=random_test --filename=${test_file} --size=${file_size} --readwrite=randrw --rwmixread=50 --bs=4k --direct=1 --numjobs=1 --time_based --runtime=${duration} --group_reporting"
            ;;
        3)
            # 混合读写
            fio_cmd="--name=mixed_test --filename=${test_file} --size=${file_size} --readwrite=rw --rwmixread=70 --bs=16k --direct=1 --numjobs=4 --time_based --runtime=${duration} --group_reporting"
            ;;
        *)
            # 顺序读写
            fio_cmd="--name=seq_test --filename=${test_file} --size=${file_size} --readwrite=readwrite --bs=1M --direct=1 --numjobs=1 --time_based --runtime=${duration} --group_reporting"
            ;;
    esac
    
    # 执行fio测试
    echo -e "${GREEN}执行命令: fio ${fio_cmd}${NC}"
    fio $fio_cmd
    
    # 清理测试文件
    if [ -f "$test_file" ]; then
        rm -f "$test_file"
    fi
    
    echo -e "\n${GREEN}磁盘I/O测试完成${NC}"
}

# 网络测试
network_test() {
    echo -e "\n${CYAN}========== 网络测试 ==========${NC}"
    
    echo -e "1) 带宽测试(需要iperf3服务器)"
    echo -e "2) 延迟和丢包测试"
    echo -e "3) 路由跟踪"
    echo -e "4) 网速监控"
    read -p "请选择测试类型(默认2): " net_test_type
    
    case $net_test_type in
        1)
            read -p "请输入iperf3服务器地址: " server_addr
            if [ -z "$server_addr" ]; then
                echo -e "${RED}需要服务器地址${NC}"
                return
            fi
            
            read -p "请输入测试时间(秒,默认10): " duration
            if [ -z "$duration" ]; then
                duration=10
            fi
            
            echo -e "${YELLOW}开始带宽测试到 ${server_addr}...${NC}"
            iperf3 -c $server_addr -t $duration
            ;;
        3)
            read -p "请输入目标地址(默认8.8.8.8): " target_addr
            if [ -z "$target_addr" ]; then
                target_addr="8.8.8.8"
            fi
            
            echo -e "${YELLOW}开始路由跟踪到 ${target_addr}...${NC}"
            traceroute -n $target_addr
            ;;
        4)
            echo -e "${YELLOW}开始网速监控(按q退出)...${NC}"
            nload
            ;;
        *)
            read -p "请输入测试地址(默认8.8.8.8): " ping_addr
            if [ -z "$ping_addr" ]; then
                ping_addr="8.8.8.8"
            fi
            
            read -p "请输入测试次数(默认10): " ping_count
            if [ -z "$ping_count" ]; then
                ping_count=10
            fi
            
            echo -e "${YELLOW}开始ping测试 ${ping_addr}...${NC}"
            ping -c $ping_count $ping_addr
            
            echo -e "\n${YELLOW}开始mtr测试 ${ping_addr}...${NC}"
            if command -v mtr &> /dev/null; then
                mtr -n -r -c 10 $ping_addr
            else
                echo -e "${YELLOW}mtr未安装,使用traceroute替代${NC}"
                traceroute -n $ping_addr
            fi
            ;;
    esac
}

# 系统监控仪表板
system_monitor() {
    echo -e "\n${CYAN}========== 系统监控仪表板 ==========${NC}"
    echo -e "监控中... 按 Ctrl+C 退出"
    echo -e "${PURPLE}------------------------------------------------${NC}"
    
    while true; do
        clear
        
        # CPU信息
        echo -e "${GREEN}====== CPU信息 ======${NC}"
        echo -e "负载: $(uptime | awk -F'load average:' '{print $2}')"
        echo -e "使用率: $(top -bn1 | grep "Cpu(s)" | awk '{print $2}')%"
        
        # 内存信息
        echo -e "\n${GREEN}====== 内存信息 ======${NC}"
        free -h | awk 'NR==1{print $0} NR==2{printf "Mem: %s/%s (%.1f%%)\n", $3, $2, $3/$2*100}'
        
        # 磁盘信息
        echo -e "\n${GREEN}====== 磁盘信息 ======${NC}"
        df -h / | awk 'NR==2{printf "%s: %s/%s (%.1f%%)\n", $1, $3, $2, $5}'
        
        # 网络连接
        echo -e "\n${GREEN}====== 网络连接 ======${NC}"
        echo -e "TCP连接数: $(netstat -tun | grep 'tcp' | wc -l)"
        echo -e "ESTABLISHED连接: $(netstat -tun | grep 'ESTABLISHED' | wc -l)"
        
        # 进程信息
        echo -e "\n${GREEN}====== 进程信息 ======${NC}"
        echo -e "总进程数: $(ps aux | wc -l)"
        echo -e "CPU使用前5:"
        ps aux --sort=-%cpu | head -6 | tail -5 | awk '{printf "  %s (%.1f%%)\n", $11, $3}'
        
        echo -e "\n${PURPLE}------------------------------------------------${NC}"
        echo -e "刷新间隔: 5秒 | 按 Ctrl+C 退出"
        
        sleep 5
    done
}

# 综合压力测试
comprehensive_test() {
    echo -e "\n${CYAN}========== 综合压力测试 ==========${NC}"
    echo -e "${RED}警告: 这将同时测试CPU、内存和磁盘I/O${NC}"
    echo -e "${RED}可能会对系统性能造成显著影响${NC}"
    
    read -p "是否继续?(y/n): " confirm
    if [[ $confirm != "y" && $confirm != "Y" ]]; then
        return
    fi
    
    read -p "请输入测试时间(秒,默认60): " duration
    if [ -z "$duration" ]; then
        duration=60
    fi
    
    # 获取系统信息
    cpu_cores=$(nproc)
    total_mem=$(free -m | awk '/^Mem:/{print $2}')
    test_mem=$((total_mem * 50 / 100)) # 使用50%的内存
    
    echo -e "\n${YELLOW}开始综合压力测试...${NC}"
    echo -e "CPU核心: ${cpu_cores}"
    echo -e "测试内存: ${test_mem}MB"
    echo -e "持续时间: ${duration}秒"
    
    # 创建测试目录
    test_dir="/tmp/stress_test_${RANDOM}"
    mkdir -p $test_dir
    test_file="${test_dir}/test.dat"
    
    # 开始综合测试
    echo -e "\n${GREEN}启动所有压力测试组件...${NC}"
    
    # CPU压力测试
    stress --cpu $cpu_cores --timeout ${duration}s &
    cpu_pid=$!
    
    # 内存压力测试
    stress --vm 2 --vm-bytes ${test_mem}M --timeout ${duration}s &
    mem_pid=$!
    
    # 磁盘I/O测试
    fio --name=comprehensive_io --filename=${test_file} --size=500M --readwrite=randrw --rwmixread=50 --bs=4k --direct=1 --numjobs=2 --time_based --runtime=${duration} --group_reporting --output=/tmp/fio_results.txt &
    fio_pid=$!
    
    # 监控
    echo -e "\n${GREEN}综合测试监控(每5秒刷新):${NC}"
    
    for ((i=1; i<=duration; i+=5)); do
        if [ $i -lt $duration ]; then
            echo -e "\n${CYAN}=== 测试进度: ${i}/${duration}秒 ===${NC}"
            
            # CPU监控
            echo -e "${GREEN}CPU使用率:${NC}"
            mpstat 1 1 | tail -2 | awk '{print "  " $0}'
            
            # 内存监控
            echo -e "${GREEN}内存使用:${NC}"
            free -m | grep "^Mem:" | awk '{printf "  %s/%sMB (%.1f%%)\n", $3, $2, $3/$2*100}'
            
            # 磁盘监控
            echo -e "${GREEN}磁盘I/O:${NC}"
            iostat -dx 1 1 | grep -A1 "Device" | tail -n +2
            
            sleep 5
        fi
    done
    
    # 等待测试结束
    echo -e "\n${YELLOW}等待测试结束...${NC}"
    wait $cpu_pid $mem_pid $fio_pid
    
    # 清理
    rm -rf $test_dir
    rm -f /tmp/fio_results.txt
    
    echo -e "\n${GREEN}综合压力测试完成${NC}"
    show_system_info
}

# 生成测试报告
generate_report() {
    echo -e "\n${CYAN}========== 生成测试报告 ==========${NC}"
    
    report_file="/tmp/stress_test_report_$(date +%Y%m%d_%H%M%S).txt"
    
    {
        echo "服务器压力测试报告"
        echo "生成时间: $(date)"
        echo "========================================"
        echo ""
        echo "1. 系统信息"
        echo "----------------------------------------"
        echo "主机名: $(hostname)"
        echo "操作系统: $(cat /etc/os-release | grep PRETTY_NAME | cut -d'"' -f2)"
        echo "内核版本: $(uname -r)"
        echo "CPU型号: $(lscpu | grep "Model name" | cut -d':' -f2 | xargs)"
        echo "CPU核心数: $(nproc)"
        echo "总内存: $(free -h | grep "^Mem:" | awk '{print $2}')"
        echo "可用内存: $(free -h | grep "^Mem:" | awk '{print $7}')"
        echo "磁盘空间: $(df -h / | awk 'NR==2{print $4 " / " $2}')"
        echo ""
        echo "2. 当前系统状态"
        echo "----------------------------------------"
        echo "系统负载: $(uptime | awk -F'load average:' '{print $2}')"
        echo "运行时间: $(uptime -p)"
        echo ""
        echo "CPU使用率:"
        mpstat 1 1 | tail -3
        echo ""
        echo "内存使用:"
        free -h
        echo ""
        echo "磁盘使用:"
        df -h /
        echo ""
        echo "3. 测试建议"
        echo "----------------------------------------"
        echo "- CPU测试建议: 使用 $(nproc) 个核心进行测试"
        echo "- 内存测试建议: 不超过 $(free -m | grep "^Mem:" | awk '{printf "%dMB", $7*0.8}')"
        echo "- 磁盘测试建议: 在 /tmp 目录进行测试"
        echo "- 网络测试建议: 测试到 8.8.8.8 的延迟"
    } > "$report_file"
    
    echo -e "${GREEN}报告已生成: ${report_file}${NC}"
    echo -e "${YELLOW}报告内容预览:${NC}"
    head -30 "$report_file"
}

# 显示主菜单
show_menu() {
    clear
    echo -e "${PURPLE}========================================${NC}"
    echo -e "${CYAN}      服务器压力测试工具 v2.0${NC}"
    echo -e "${PURPLE}========================================${NC}"
    echo -e "${GREEN}1. 显示系统信息${NC}"
    echo -e "${GREEN}2. CPU压力测试${NC}"
    echo -e "${GREEN}3. 内存压力测试${NC}"
    echo -e "${GREEN}4. 磁盘I/O测试${NC}"
    echo -e "${GREEN}5. 网络测试${NC}"
    echo -e "${GREEN}6. 综合压力测试${NC}"
    echo -e "${GREEN}7. 系统监控仪表板${NC}"
    echo -e "${GREEN}8. 生成测试报告${NC}"
    echo -e "${GREEN}9. 检查/安装必要工具${NC}"
    echo -e "${RED}0. 退出${NC}"
    echo -e "${PURPLE}========================================${NC}"
}

# 主函数
main() {
    # 检查是否为root用户
    if [ "$EUID" -ne 0 ]; then
        echo -e "${YELLOW}提示: 某些测试可能需要root权限${NC}"
    fi
    
    # 检查必要工具
    check_tools
    
    while true; do
        show_menu
        read -p "请选择操作 (0-9): " choice
        
        case $choice in
            1) show_system_info ;;
            2) cpu_stress_test ;;
            3) memory_stress_test ;;
            4) disk_io_test ;;
            5) network_test ;;
            6) comprehensive_test ;;
            7) system_monitor ;;
            8) generate_report ;;
            9) check_tools ;;
            0)
                echo -e "${CYAN}感谢使用,再见!${NC}"
                exit 0
                ;;
            *)
                echo -e "${RED}无效选择,请重新输入${NC}"
                sleep 1
                ;;
        esac
        
        echo -e "\n${YELLOW}按回车键继续...${NC}"
        read
    done
}

# 捕获Ctrl+C
trap 'echo -e "\n${RED}检测到中断信号,退出...${NC}"; exit 1' SIGINT

# 运行主函数
main

使用说明

1. 保存脚本

将上述脚本保存为 stress-test.sh

chmod +x stress-test.sh
2. 功能特点

全面检测: 自动检查并安装必要的测试工具

多种测试:

  • CPU压力测试(支持多种负载类型)
  • 内存压力测试(智能计算可用内存)
  • 磁盘I/O测试(顺序/随机/混合读写)
  • 网络测试(带宽/延迟/路由/监控)
  • 综合压力测试(同时测试多个组件)
  • 实时监控: 系统监控仪表板
  • 报告生成: 自动生成测试报告
  • 安全保护: 防止过度使用资源

本文共10972个字符,其中有 1407 个汉字,平均阅读时长 ≈ 43分钟
0

打赏

海报

正在生成.....

网站公告

欢迎访问本站

  • 如果你有教程想要分享,请联系我们