本文目录导读:

我来提供一个自动配置MySQL主从复制的Shell脚本,这个脚本可以自动配置主库和从库。
脚本代码
#!/bin/bash
# MySQL主从复制自动配置脚本
# 使用方法:
# 主库: ./mysql_replication.sh master
# 从库: ./mysql_replication.sh slave master_ip
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# 配置参数 - 请根据实际情况修改
MYSQL_ROOT_PASSWORD="your_root_password" # MySQL root密码
REPLICATION_USER="repl" # 复制用户
REPLICATION_PASSWORD="repl_password" # 复制用户密码
MYSQL_DATA_DIR="/var/lib/mysql" # MySQL数据目录
MYSQL_CONF_DIR="/etc/mysql/mysql.conf.d" # MySQL配置目录
BINLOG_FILE="" # 主库binlog文件名(从库使用)
BINLOG_POS=0 # 主库binlog位置(从库使用)
# 日志函数
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
# 检查是否为root用户
check_root() {
if [[ $EUID -ne 0 ]]; then
log_error "请使用root用户运行此脚本"
exit 1
fi
}
# 检查MySQL是否安装
check_mysql() {
if ! command -v mysql &> /dev/null; then
log_error "MySQL未安装,请先安装MySQL"
exit 1
fi
if ! systemctl is-active --quiet mysql; then
log_error "MySQL服务未运行"
exit 1
fi
}
# 检查防火墙是否阻止MySQL连接
check_firewall() {
if command -v ufw &> /dev/null; then
ufw status | grep -q "active" && {
log_warn "防火墙已开启,请确保端口3306已开放"
echo " 执行: ufw allow 3306"
}
fi
}
# 配置主库
configure_master() {
log_info "开始配置MySQL主库..."
# 创建配置备份
local conf_file="${MYSQL_CONF_DIR}/mysql.cnf"
if [[ ! -f "$conf_file" ]]; then
conf_file="/etc/mysql/my.cnf"
fi
cp "$conf_file" "${conf_file}.backup.$(date +%Y%m%d_%H%M%S)"
# 检查是否已配置
if grep -q "server-id" "$conf_file"; then
log_warn "server-id已配置,跳过配置添加"
else
# 添加主库配置
cat >> "$conf_file" << EOF
# 主从复制配置
[mysqld]
# 主从复制配置
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
binlog_do_db = your_database_name # 需要复制的数据库,多个用空格分隔
binlog_ignore_db = mysql # 不需要复制的数据库
binlog_ignore_db = information_schema
binlog_ignore_db = performance_schema
binlog_ignore_db = sys
# 可选配置
expire_logs_days = 7
max_binlog_size = 100M
binlog_format = ROW
EOF
fi
# 重启MySQL服务
log_info "重启MySQL服务..."
systemctl restart mysql
sleep 3
# 创建复制用户
log_info "创建复制用户..."
mysql -u root -p"${MYSQL_ROOT_PASSWORD}" << EOF
CREATE USER IF NOT EXISTS '${REPLICATION_USER}'@'%' IDENTIFIED BY '${REPLICATION_PASSWORD}';
GRANT REPLICATION SLAVE ON *.* TO '${REPLICATION_USER}'@'%';
FLUSH PRIVILEGES;
EOF
# 获取主库状态
log_info "获取主库状态..."
local master_status=$(mysql -u root -p"${MYSQL_ROOT_PASSWORD}" -e "SHOW MASTER STATUS\G" 2>/dev/null)
local binlog_file=$(echo "$master_status" | grep "File:" | awk '{print $2}')
local binlog_pos=$(echo "$master_status" | grep "Position:" | awk '{print $2}')
log_info "主库配置完成!"
log_info "== 主库状态信息 =="
log_info "Binlog文件: ${binlog_file}"
log_info "Binlog位置: ${binlog_pos}"
log_info "复制用户: ${REPLICATION_USER}"
log_info "复制密码: ${REPLICATION_PASSWORD}"
echo ""
log_info "请在从库上执行以下命令:"
echo " $0 slave ${MASTER_IP}"
echo ""
log_info "或手动配置从库:"
echo " CHANGE MASTER TO"
echo " MASTER_HOST='${MASTER_IP}',"
echo " MASTER_USER='${REPLICATION_USER}',"
echo " MASTER_PASSWORD='${REPLICATION_PASSWORD}',"
echo " MASTER_LOG_FILE='${binlog_file}',"
echo " MASTER_LOG_POS=${binlog_pos};"
}
# 配置从库
configure_slave() {
local master_ip=$1
if [[ -z "$master_ip" ]]; then
log_error "请提供主库IP地址"
echo "使用方法: $0 slave master_ip_address"
exit 1
fi
log_info "开始配置MySQL从库..."
log_info "主库IP: ${master_ip}"
# 创建配置备份
local conf_file="${MYSQL_CONF_DIR}/mysql.cnf"
if [[ ! -f "$conf_file" ]]; then
conf_file="/etc/mysql/my.cnf"
fi
cp "$conf_file" "${conf_file}.backup.$(date +%Y%m%d_%H%M%S)"
# 检查是否已配置
if grep -q "server-id" "$conf_file"; then
log_warn "server-id已配置,跳过配置添加"
else
# 生成随机server-id
local server_id=$((RANDOM % 100 + 2))
# 添加从库配置
cat >> "$conf_file" << EOF
# 主从复制配置
[mysqld]
# 主从复制配置
server-id = ${server_id}
relay-log = /var/log/mysql/mysql-relay-bin.log
log_bin = /var/log/mysql/mysql-bin.log
binlog_do_db = your_database_name # 需要复制的数据库,与主库一致
# 可选配置
read_only = 1
skip-slave-start = 0
slave-skip-errors = 1062,1032,1452
EOF
fi
# 重启MySQL服务
log_info "重启MySQL服务..."
systemctl restart mysql
sleep 3
# 配置复制
log_info "配置主从复制..."
# 如果提供了binlog信息,使用提供的;否则从主库获取
if [[ -n "$BINLOG_FILE" && "$BINLOG_POS" -gt 0 ]]; then
log_info "使用提供的binlog信息"
else
# 尝试从主库获取状态
log_info "尝试从主库获取binlog信息..."
local master_status=$(mysql -u root -p"${MYSQL_ROOT_PASSWORD}" \
-h "${master_ip}" \
-e "SHOW MASTER STATUS\G" 2>/dev/null)
if [[ $? -eq 0 ]]; then
BINLOG_FILE=$(echo "$master_status" | grep "File:" | awk '{print $2}')
BINLOG_POS=$(echo "$master_status" | grep "Position:" | awk '{print $2}')
else
log_error "无法从主库获取binlog信息"
log_info "请在主库执行: SHOW MASTER STATUS;"
read -p "请输入Binlog文件名: " BINLOG_FILE
read -p "请输入Binlog位置: " BINLOG_POS
fi
fi
# 停止之前的复制
mysql -u root -p"${MYSQL_ROOT_PASSWORD}" -e "STOP SLAVE;" 2>/dev/null || true
# 配置主从复制
mysql -u root -p"${MYSQL_ROOT_PASSWORD}" << EOF
CHANGE MASTER TO
MASTER_HOST='${master_ip}',
MASTER_USER='${REPLICATION_USER}',
MASTER_PASSWORD='${REPLICATION_PASSWORD}',
MASTER_LOG_FILE='${BINLOG_FILE}',
MASTER_LOG_POS=${BINLOG_POS},
MASTER_CONNECT_RETRY=10;
START SLAVE;
EOF
sleep 2
# 检查复制状态
log_info "检查复制状态..."
local slave_status=$(mysql -u root -p"${MYSQL_ROOT_PASSWORD}" -e "SHOW SLAVE STATUS\G" 2>/dev/null)
local slave_io=$(echo "$slave_status" | grep "Slave_IO_Running:" | awk '{print $2}')
local slave_sql=$(echo "$slave_status" | grep "Slave_SQL_Running:" | awk '{print $2}')
local seconds_behind=$(echo "$slave_status" | grep "Seconds_Behind_Master:" | awk '{print $2}')
if [[ "$slave_io" == "Yes" && "$slave_sql" == "Yes" ]]; then
log_info "主从复制配置成功!"
log_info "IO线程状态: ${slave_io}"
log_info "SQL线程状态: ${slave_sql}"
log_info "延迟: ${seconds_behind}秒"
else
log_error "主从复制配置可能存在问题"
log_info "IO线程状态: ${slave_io}"
log_info "SQL线程状态: ${slave_sql}"
local last_error=$(echo "$slave_status" | grep "Last_Error:" | awk '{print $2}')
if [[ -n "$last_error" ]]; then
log_error "错误信息: ${last_error}"
fi
fi
}
# 检查复制状态
check_status() {
log_info "检查主从复制状态..."
# 检查主库状态
log_info "=== 主库状态 ==="
mysql -u root -p"${MYSQL_ROOT_PASSWORD}" -e "SHOW MASTER STATUS\G" 2>/dev/null || log_error "无法获取主库状态"
# 检查从库状态
log_info "=== 从库状态 ==="
mysql -u root -p"${MYSQL_ROOT_PASSWORD}" -e "SHOW SLAVE STATUS\G" 2>/dev/null || log_error "无法获取从库状态"
}
# 停止复制
stop_replication() {
log_info "停止主从复制..."
mysql -u root -p"${MYSQL_ROOT_PASSWORD}" -e "STOP SLAVE;" 2>/dev/null || true
log_info "复制已停止"
}
# 启动复制
start_replication() {
log_info "启动主从复制..."
mysql -u root -p"${MYSQL_ROOT_PASSWORD}" -e "START SLAVE;" 2>/dev/null || true
log_info "复制已启动"
}
# 重置复制
reset_replication() {
log_info "重置主从复制..."
mysql -u root -p"${MYSQL_ROOT_PASSWORD}" -e "STOP SLAVE; RESET SLAVE;" 2>/dev/null || true
log_info "复制已重置"
}
# 显示帮助信息
show_help() {
echo "MySQL主从复制自动配置脚本"
echo ""
echo "使用方法:"
echo " $0 master - 配置为主库"
echo " $0 slave master_ip - 配置为从库"
echo " $0 status - 检查复制状态"
echo " $0 start - 启动复制"
echo " $0 stop - 停止复制"
echo " $0 reset - 重置复制"
echo " $0 help - 显示帮助信息"
echo ""
echo "示例:"
echo " $0 master # 在主库上执行"
echo " $0 slave 192.168.1.100 # 在从库上执行"
}
# 主函数
main() {
check_root
check_mysql
check_firewall
case "$1" in
master)
configure_master
;;
slave)
configure_slave "$2"
;;
status)
check_status
;;
start)
start_replication
;;
stop)
stop_replication
;;
reset)
reset_replication
;;
help|--help|-h)
show_help
;;
*)
log_error "未知命令: $1"
show_help
exit 1
;;
esac
}
# 执行主函数
main "$@"
使用说明
保存脚本
将上述脚本保存为 mysql_replication.sh
添加执行权限
chmod +x mysql_replication.sh
在主库上执行
# 在主库服务器上运行 ./mysql_replication.sh master
在从库上执行
# 在从库服务器上运行,替换master_ip为主库的实际IP ./mysql_replication.sh slave 192.168.1.100
其他管理命令
# 检查复制状态 ./mysql_replication.sh status # 停止复制 ./mysql_replication.sh stop # 启动复制 ./mysql_replication.sh start # 重置复制 ./mysql_replication.sh reset # 查看帮助 ./mysql_replication.sh help
注意事项
-
修改配置参数:脚本开头的
MYSQL_ROOT_PASSWORD等变量需要根据实际情况修改 -
数据库权限:确保复制用户有足够的权限
-
网络连通性:确保主从库之间网络互通,防火墙允许3306端口
-
数据一致性:配置前需要确保主从库数据一致
-
配置文件路径:不同发行版可能路径不同,根据实际情况修改
-
MySQL版本:建议主从库使用相同版本的MySQL
这个脚本会自动完成大部分配置工作,但在生产环境中使用前请仔细测试。