当前位置: 代码网 > it编程>前端脚本>Powershell > Linux使用pt-slave-restart监控多个从库的Shell脚本案例

Linux使用pt-slave-restart监控多个从库的Shell脚本案例

2025年10月22日 Powershell 我要评论
我来为您编写一个使用pt-slave-restart监控多个从库的shell脚本,支持灵活的传参功能。脚本代码#!/bin/bash# pt-slave-restart监控脚本# 用于监控多个mysq

我来为您编写一个使用pt-slave-restart监控多个从库的shell脚本,支持灵活的传参功能。

脚本代码

#!/bin/bash

# pt-slave-restart监控脚本
# 用于监控多个mysql从库的复制状态并在出错时自动重启

# 默认配置
default_user="monitor_user"
default_socket="/tmp/mysql.sock"
default_errors="1062,1032,1205,1158,1159,1007,1008,1050,1051,1054,1060,1061,1094,1213,1169,1232"
default_max_cycle=10
default_sleep=300
default_log_file="/var/log/pt-slave-restart.log"
config_file="/etc/pt-slave-restart.conf"

# 显示用法
usage() {
    cat << eof
用法: $0 [选项] [实例...]

选项:
    -u, --user user         mysql用户名 (默认: $default_user)
    -p, --password pass     mysql密码
    -s, --socket socket     默认socket文件 (默认: $default_socket)
    -h, --host host         主机名 (默认使用socket)
    -p, --port port         端口号
    -e, --errors errors     跳过的错误代码 (默认: $default_errors)
    -m, --max-cycle cycle   最大重启循环次数 (默认: $default_max_cycle)
    -s, --sleep seconds     检查间隔秒数 (默认: $default_sleep)
    -l, --log file          日志文件 (默认: $default_log_file)
    -c, --config file       配置文件 (默认: $config_file)
    -d, --daemon            以守护进程模式运行
    -v, --verbose           详细输出
    --help                  显示此帮助信息

实例格式:
    host:port:socket:user:password
    host:port
    socket
    别名 (需要在配置文件中定义)

配置文件格式 ($config_file):
    # 每行定义一个mysql实例
    # 格式: 别名|host:port|user|password|socket
    slave1|192.168.1.101:3306|monitor|password123|/tmp/mysql1.sock
    slave2|192.168.1.102:3307|monitor|password123|/tmp/mysql2.sock
    slave3||monitor|password123|/tmp/mysql3.sock

示例:
    $0 -u monitor -p pass123 slave1 slave2
    $0 -d -s 60 192.168.1.101:3306 /tmp/mysql.sock
    $0 --verbose --errors "1062,1032" slave1
eof
}

# 日志函数
log() {
    local level=$1
    shift
    local message="$*"
    local timestamp=$(date '+%y-%m-%d %h:%m:%s')
    
    echo "[$timestamp] [$level] $message" | tee -a "$log_file"
    
    if [[ "$verbose" == "true" && "$level" != "debug" ]]; then
        echo "[$timestamp] [$level] $message"
    fi
}

# 读取配置文件
read_config() {
    local alias=$1
    if [[ -f "$config_file" ]]; then
        while ifs='|' read -r config_alias config_host_port config_user config_password config_socket; do
            if [[ "$config_alias" == "$alias" ]]; then
                host=${config_host_port%:*}
                port=${config_host_port#*:}
                user=$config_user
                password=$config_password
                socket=$config_socket
                return 0
            fi
        done < <(grep -v '^#' "$config_file" | grep -v '^$')
    fi
    return 1
}

# 解析实例参数
parse_instance() {
    local instance=$1
    local parsed_host parsed_port parsed_socket parsed_user parsed_password
    
    # 重置为默认值
    parsed_host=$host
    parsed_port=$port
    parsed_socket=$socket
    parsed_user=$user
    parsed_password=$password
    
    # 检查是否是配置文件中定义的别名
    if read_config "$instance"; then
        return 0
    fi
    
    # 解析 host:port:socket:user:password 格式
    if [[ "$instance" =~ : ]]; then
        ifs=':' read -r -a parts <<< "$instance"
        case ${#parts[@]} in
            2)
                parsed_host=${parts[0]}
                parsed_port=${parts[1]}
                parsed_socket=""
                ;;
            3)
                parsed_host=${parts[0]}
                parsed_port=${parts[1]}
                parsed_socket=${parts[2]}
                ;;
            4)
                parsed_host=${parts[0]}
                parsed_port=${parts[1]}
                parsed_socket=${parts[2]}
                parsed_user=${parts[3]}
                ;;
            5)
                parsed_host=${parts[0]}
                parsed_port=${parts[1]}
                parsed_socket=${parts[2]}
                parsed_user=${parts[3]}
                parsed_password=${parts[4]}
                ;;
            *)
                log "error" "无效的实例格式: $instance"
                return 1
                ;;
        esac
    else
        # 如果只提供socket路径
        if [[ "$instance" =~ \.sock ]]; then
            parsed_socket=$instance
            parsed_host=""
            parsed_port=""
        else
            # 尝试作为别名从配置文件中读取
            if ! read_config "$instance"; then
                log "error" "未知的实例别名且不是有效的socket路径: $instance"
                return 1
            fi
        fi
    fi
    
    host=$parsed_host
    port=$parsed_port
    socket=$parsed_socket
    user=$parsed_user
    password=$parsed_password
}

# 构建连接参数
build_connection_args() {
    local connect_args=""
    
    if [[ -n "$socket" ]]; then
        connect_args="--socket=$socket"
    elif [[ -n "$host" && -n "$port" ]]; then
        connect_args="--host=$host --port=$port"
    elif [[ -n "$host" ]]; then
        connect_args="--host=$host"
        if [[ -n "$port" ]]; then
            connect_args="$connect_args --port=$port"
        fi
    else
        connect_args="--socket=$default_socket"
    fi
    
    if [[ -n "$user" ]]; then
        connect_args="$connect_args --user=$user"
    fi
    
    if [[ -n "$password" ]]; then
        connect_args="$connect_args --password=$password"
    fi
    
    echo "$connect_args"
}

# 监控单个实例
monitor_instance() {
    local instance_name=$1
    local connect_args=$2
    
    log "info" "开始监控实例: $instance_name"
    
    local pt_command="pt-slave-restart $connect_args"
    pt_command="$pt_command --error-numbers=$errors"
    pt_command="$pt_command --max-cycle=$max_cycle"
    pt_command="$pt_command --sleep=$sleep"
    pt_command="$pt_command --log=$log_file"
    pt_command="$pt_command --verbose"
    pt_command="$pt_command --skip-count=0"
    pt_command="$pt_command --always"
    
    if [[ "$daemon" == "true" ]]; then
        pt_command="$pt_command --daemonize"
        log "info" "以守护进程模式启动: $pt_command"
        eval $pt_command
    else
        log "info" "执行命令: $pt_command"
        eval $pt_command
    fi
    
    local exit_code=$?
    if [[ $exit_code -eq 0 ]]; then
        log "info" "实例 $instance_name 监控启动成功"
    else
        log "error" "实例 $instance_name 监控启动失败,退出码: $exit_code"
    fi
    
    return $exit_code
}

# 主函数
main() {
    # 设置默认值
    user=$default_user
    socket=$default_socket
    errors=$default_errors
    max_cycle=$default_max_cycle
    sleep=$default_sleep
    log_file=$default_log_file
    daemon="false"
    verbose="false"
    
    # 解析命令行参数
    while [[ $# -gt 0 ]]; do
        case $1 in
            -u|--user)
                user="$2"
                shift 2
                ;;
            -p|--password)
                password="$2"
                shift 2
                ;;
            -s|--socket)
                socket="$2"
                shift 2
                ;;
            -h|--host)
                host="$2"
                shift 2
                ;;
            -p|--port)
                port="$2"
                shift 2
                ;;
            -e|--errors)
                errors="$2"
                shift 2
                ;;
            -m|--max-cycle)
                max_cycle="$2"
                shift 2
                ;;
            -s|--sleep)
                sleep="$2"
                shift 2
                ;;
            -l|--log)
                log_file="$2"
                shift 2
                ;;
            -c|--config)
                config_file="$2"
                shift 2
                ;;
            -d|--daemon)
                daemon="true"
                shift
                ;;
            -v|--verbose)
                verbose="true"
                shift
                ;;
            --help)
                usage
                exit 0
                ;;
            -*)
                echo "未知选项: $1"
                usage
                exit 1
                ;;
            *)
                break
                ;;
        esac
    done
    
    # 检查是否安装了pt-slave-restart
    if ! command -v pt-slave-restart &> /dev/null; then
        echo "错误: 未找到 pt-slave-restart 命令,请先安装 percona toolkit"
        exit 1
    fi
    
    # 获取实例列表
    if [[ $# -eq 0 ]]; then
        # 如果没有提供实例参数,从配置文件读取所有实例
        if [[ -f "$config_file" ]]; then
            instances=()
            while ifs='|' read -r alias host_port user password socket; do
                if [[ -n "$alias" && ! "$alias" =~ ^# ]]; then
                    instances+=("$alias")
                fi
            done < <(grep -v '^#' "$config_file" | grep -v '^$')
            
            if [[ ${#instances[@]} -eq 0 ]]; then
                echo "错误: 配置文件中没有定义实例,且未提供实例参数"
                usage
                exit 1
            fi
        else
            echo "错误: 未提供实例参数且配置文件不存在: $config_file"
            usage
            exit 1
        fi
    else
        instances=("$@")
    fi
    
    log "info" "开始监控 ${#instances[@]} 个实例"
    log "info" "跳过错误代码: $errors"
    log "info" "最大重启循环: $max_cycle"
    log "info" "检查间隔: $sleep 秒"
    log "info" "日志文件: $log_file"
    
    # 监控每个实例
    for instance in "${instances[@]}"; do
        # 保存原始值
        original_host=$host
        original_port=$port
        original_socket=$socket
        original_user=$user
        original_password=$password
        
        # 解析实例参数
        if ! parse_instance "$instance"; then
            log "error" "解析实例失败: $instance"
            continue
        fi
        
        # 构建连接参数
        connect_args=$(build_connection_args)
        
        # 生成实例显示名称
        if [[ -n "$socket" ]]; then
            instance_name="socket:$socket"
        elif [[ -n "$host" && -n "$port" ]]; then
            instance_name="$host:$port"
        else
            instance_name="$instance"
        fi
        
        # 启动监控
        monitor_instance "$instance_name" "$connect_args" &
        
        # 恢复原始值
        host=$original_host
        port=$original_port
        socket=$original_socket
        user=$original_user
        password=$original_password
    done
    
    # 如果不是守护进程模式,等待所有子进程
    if [[ "$daemon" == "false" ]]; then
        wait
    else
        log "info" "所有监控进程已在后台启动"
    fi
}

# 运行主函数
main "$@"

配置文件示例

创建配置文件 /etc/pt-slave-restart.conf

# 格式: 别名|host:port|user|password|socket
slave1|192.168.1.101:3306|monitor|password123|/tmp/mysql1.sock
slave2|192.168.1.102:3307|monitor|password123|/tmp/mysql2.sock
slave3||monitor|password123|/tmp/mysql3.sock
slave4|192.168.1.104:3306|monitor|password123|

使用示例

1. 基本用法

# 使用配置文件中的实例
./pt-slave-monitor.sh slave1 slave2

# 直接指定实例
./pt-slave-monitor.sh 192.168.1.101:3306 /tmp/mysql.sock

2. 指定连接参数

# 指定用户名和密码
./pt-slave-monitor.sh -u monitor -p password123 slave1 slave2

# 指定错误代码和检查间隔
./pt-slave-monitor.sh -e "1062,1032" -s 60 slave1

3. 守护进程模式

# 后台运行
./pt-slave-monitor.sh -d -l /var/log/mysql-monitor.log slave1 slave2 slave3

4. 详细输出

# 显示详细日志
./pt-slave-monitor.sh -v --errors "1062,1032,1205" slave1

脚本特点

  1. 灵活的实例定义:支持别名、host:port、socket等多种格式
  2. 配置文件支持:可以预定义实例配置
  3. 参数覆盖:命令行参数可以覆盖配置文件中的设置
  4. 错误处理:完善的错误处理和日志记录
  5. 守护进程模式:支持后台运行
  6. 多实例监控:同时监控多个从库实例
  7. 自定义错误代码:可配置需要跳过的复制错误

安装和使用步骤

  1. 保存脚本为 pt-slave-monitor.sh
  2. 添加执行权限:chmod +x pt-slave-monitor.sh
  3. 创建配置文件(可选)
  4. 安装percona toolkit:yum install percona-toolkit 或 apt-get install percona-toolkit
  5. 运行脚本监控从库

这个脚本提供了灵活的配置选项和强大的监控功能,可以方便地管理多个mysql从库的复制状态监控。

以上就是linux使用pt-slave-restart监控多个从库的shell脚本案例的详细内容,更多关于linux t-slave-restart监控从库的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com