#!/bin/bash # MySQL二进制包安装脚本 # 作者: emotion-museum # 日期: 2025-07-21 # 功能: 使用二进制包安装MySQL,保留现有数据 set -e REMOTE_HOST="root@47.111.10.27" MYSQL_PACKAGE="/data/package/mysql-8.0.24-linux-glibc2.12-x86_64.tar.xz" MYSQL_INSTALL_DIR="/usr/local/mysql" MYSQL_DATA_DIR="/data/programs/mysql" MYSQL_ROOT_PASSWORD="EmotionMuseum2025*#" # 颜色输出 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" } log_error() { echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" } # 检查SSH连接 check_connection() { log_info "检查远程服务器连接..." if ssh -o ConnectTimeout=10 "$REMOTE_HOST" "echo 'SSH连接成功'" > /dev/null 2>&1; then log_success "远程服务器连接正常" else log_error "无法连接到远程服务器: $REMOTE_HOST" exit 1 fi } # 备份数据文件 backup_data_files() { log_info "备份MySQL数据文件..." ssh "$REMOTE_HOST" " echo '📦 备份数据文件...' BACKUP_DIR=\"/data/backups/mysql_binary_\$(date +%Y%m%d_%H%M%S)\" mkdir -p \"\$BACKUP_DIR\" # 备份数据目录 if [ -d '$MYSQL_DATA_DIR' ]; then cp -r $MYSQL_DATA_DIR \"\$BACKUP_DIR/\" echo \"✅ 数据文件已备份到: \$BACKUP_DIR\" else echo '⚠️ 数据目录不存在: $MYSQL_DATA_DIR' fi # 导出数据库(如果Docker容器还在运行) if docker ps | grep -q emotion-mysql; then echo '📤 导出数据库...' docker exec emotion-mysql mysqldump -u root -p'$MYSQL_ROOT_PASSWORD' --all-databases --routines --triggers > \"\$BACKUP_DIR/all_databases.sql\" 2>/dev/null || echo '数据库导出失败' fi " log_success "数据文件备份完成" } # 停止现有服务 stop_existing_services() { log_info "停止现有MySQL服务..." ssh "$REMOTE_HOST" " echo '🛑 停止Docker MySQL容器...' docker stop emotion-mysql 2>/dev/null || echo 'MySQL容器已停止' docker rm emotion-mysql 2>/dev/null || echo 'MySQL容器已删除' echo '🛑 停止系统MySQL服务...' systemctl stop mysqld 2>/dev/null || echo 'mysqld服务未运行' systemctl stop mysql 2>/dev/null || echo 'mysql服务未运行' service mysqld stop 2>/dev/null || echo 'mysqld服务未运行' service mysql stop 2>/dev/null || echo 'mysql服务未运行' echo '🔍 检查MySQL进程...' if pgrep -f mysqld > /dev/null; then echo '强制停止MySQL进程...' pkill -f mysqld || true sleep 3 fi echo '✅ 现有服务已停止' " log_success "现有服务停止完成" } # 解压并安装MySQL二进制包 install_mysql_binary() { log_info "解压并安装MySQL二进制包..." ssh "$REMOTE_HOST" " echo '📦 解压MySQL二进制包...' cd /tmp # 解压MySQL包 tar -xJf $MYSQL_PACKAGE # 检查解压结果 if [ -d 'mysql-8.0.24-linux-glibc2.12-x86_64' ]; then echo '✅ MySQL包解压成功' else echo '❌ MySQL包解压失败' exit 1 fi echo '📁 移动到安装目录...' # 备份现有安装目录 if [ -d '$MYSQL_INSTALL_DIR' ]; then mv $MYSQL_INSTALL_DIR $MYSQL_INSTALL_DIR.bak.\$(date +%Y%m%d_%H%M%S) fi # 移动到安装目录 mv mysql-8.0.24-linux-glibc2.12-x86_64 $MYSQL_INSTALL_DIR echo '👤 创建mysql用户...' # 创建mysql用户和组 groupadd mysql 2>/dev/null || echo 'mysql组已存在' useradd -r -g mysql -s /bin/false mysql 2>/dev/null || echo 'mysql用户已存在' echo '🔗 创建符号链接...' # 创建符号链接到系统路径 ln -sf $MYSQL_INSTALL_DIR/bin/mysql /usr/local/bin/mysql ln -sf $MYSQL_INSTALL_DIR/bin/mysqld /usr/local/bin/mysqld ln -sf $MYSQL_INSTALL_DIR/bin/mysqladmin /usr/local/bin/mysqladmin ln -sf $MYSQL_INSTALL_DIR/bin/mysqldump /usr/local/bin/mysqldump echo '✅ MySQL二进制包安装完成' " log_success "MySQL二进制包安装完成" } # 配置MySQL configure_mysql() { log_info "配置MySQL..." ssh "$REMOTE_HOST" " echo '⚙️ 创建MySQL配置文件...' cat > /etc/my.cnf << 'EOF' [mysqld] # 基本设置 user = mysql port = 3306 basedir = /usr/local/mysql datadir = /data/programs/mysql socket = /tmp/mysql.sock pid-file = /var/run/mysqld/mysqld.pid # 网络配置 bind-address = 0.0.0.0 max_connections = 200 # 字符集配置 character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci # 认证插件 default-authentication-plugin = mysql_native_password # 日志配置 log-error = /var/log/mysqld.log slow_query_log = 1 slow_query_log_file = /var/log/mysql-slow.log long_query_time = 2 # InnoDB配置 innodb_buffer_pool_size = 512M innodb_log_file_size = 128M innodb_flush_log_at_trx_commit = 1 innodb_lock_wait_timeout = 50 # 二进制日志 log-bin = mysql-bin binlog_format = ROW expire_logs_days = 7 # 安全配置 skip-name-resolve sql_mode = STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO [mysql] default-character-set = utf8mb4 socket = /tmp/mysql.sock [client] default-character-set = utf8mb4 socket = /tmp/mysql.sock EOF echo '📁 设置目录权限...' # 设置安装目录权限 chown -R root:root $MYSQL_INSTALL_DIR chown -R mysql:mysql $MYSQL_INSTALL_DIR/data 2>/dev/null || true # 设置数据目录权限 chown -R mysql:mysql $MYSQL_DATA_DIR chmod -R 750 $MYSQL_DATA_DIR # 创建必要的目录 mkdir -p /var/run/mysqld mkdir -p /var/log chown mysql:mysql /var/run/mysqld touch /var/log/mysqld.log chown mysql:mysql /var/log/mysqld.log echo '✅ MySQL配置完成' " log_success "MySQL配置完成" } # 创建systemd服务文件 create_systemd_service() { log_info "创建systemd服务文件..." ssh "$REMOTE_HOST" " echo '📝 创建systemd服务文件...' cat > /etc/systemd/system/mysqld.service << 'EOF' [Unit] Description=MySQL Server Documentation=man:mysqld(8) Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html After=network.target After=syslog.target [Install] WantedBy=multi-user.target [Service] User=mysql Group=mysql Type=notify TimeoutSec=0 PermissionsStartOnly=true ExecStartPre=/usr/local/mysql/bin/mysqld_safe_helper ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf Restart=on-failure RestartPreventExitStatus=1 Environment=MYSQLD_PARENT_PID=1 PrivateTmp=false EOF echo '🔄 重新加载systemd...' systemctl daemon-reload echo '✅ systemd服务文件创建完成' " log_success "systemd服务文件创建完成" } # 启动MySQL服务 start_mysql_service() { log_info "启动MySQL服务..." ssh "$REMOTE_HOST" " echo '🚀 启动MySQL服务...' # 直接启动mysqld nohup $MYSQL_INSTALL_DIR/bin/mysqld --defaults-file=/etc/my.cnf --user=mysql > /var/log/mysqld.log 2>&1 & # 等待MySQL启动 echo '⏳ 等待MySQL启动...' sleep 15 # 检查MySQL进程 if pgrep -f mysqld > /dev/null; then echo '✅ MySQL进程启动成功' else echo '❌ MySQL进程启动失败' tail -20 /var/log/mysqld.log exit 1 fi # 检查端口监听 echo '🔍 检查端口监听...' sleep 5 if netstat -tlnp | grep :3306 > /dev/null; then echo '✅ MySQL端口3306正在监听' else echo '⚠️ MySQL端口3306未监听,可能还在启动中' fi " log_success "MySQL服务启动完成" } # 验证数据完整性 verify_data_integrity() { log_info "验证数据完整性..." ssh "$REMOTE_HOST" " echo '🔍 等待MySQL完全启动...' sleep 10 echo '🔍 尝试连接MySQL...' # 使用现有密码连接 if $MYSQL_INSTALL_DIR/bin/mysql -u root -p'$MYSQL_ROOT_PASSWORD' -e 'SELECT VERSION();' > /dev/null 2>&1; then echo '✅ MySQL连接成功,密码正确' else echo '⚠️ 使用现有密码连接失败,尝试无密码连接...' if $MYSQL_INSTALL_DIR/bin/mysql -u root -e 'SELECT VERSION();' > /dev/null 2>&1; then echo '✅ 无密码连接成功,设置密码...' $MYSQL_INSTALL_DIR/bin/mysql -u root << 'EOSQL' ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '$MYSQL_ROOT_PASSWORD'; CREATE USER IF NOT EXISTS 'root'@'%' IDENTIFIED WITH mysql_native_password BY '$MYSQL_ROOT_PASSWORD'; GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION; FLUSH PRIVILEGES; EOSQL echo '✅ 密码设置完成' else echo '❌ MySQL连接失败' tail -20 /var/log/mysqld.log exit 1 fi fi echo '🔍 检查数据库列表...' $MYSQL_INSTALL_DIR/bin/mysql -u root -p'$MYSQL_ROOT_PASSWORD' -e 'SHOW DATABASES;' echo '🔍 检查emotion_museum数据库...' if $MYSQL_INSTALL_DIR/bin/mysql -u root -p'$MYSQL_ROOT_PASSWORD' -e 'USE emotion_museum; SHOW TABLES;' > /dev/null 2>&1; then echo '✅ emotion_museum数据库存在' $MYSQL_INSTALL_DIR/bin/mysql -u root -p'$MYSQL_ROOT_PASSWORD' -e 'USE emotion_museum; SHOW TABLES;' else echo '⚠️ emotion_museum数据库不存在或无法访问' fi " log_success "数据完整性验证完成" } # 检查最终状态 check_final_status() { log_info "检查最终状态..." ssh "$REMOTE_HOST" " echo '📊 MySQL服务状态:' echo '==================' # 检查进程 echo -n 'MySQL进程: ' if pgrep -f mysqld > /dev/null; then echo '✅ 运行中' ps aux | grep mysqld | grep -v grep | head -1 else echo '❌ 未运行' fi # 检查端口监听 echo -n 'MySQL端口(3306): ' if netstat -tlnp | grep :3306 | grep -v docker > /dev/null; then echo '✅ 监听中' else echo '❌ 未监听' fi echo '' echo '🔍 安装目录:' ls -la $MYSQL_INSTALL_DIR | head -5 echo '' echo '🔍 数据目录:' ls -la $MYSQL_DATA_DIR | head -5 echo '' echo '🔍 配置文件:' ls -la /etc/my.cnf 2>/dev/null || echo '配置文件不存在' " log_success "状态检查完成" } # 主函数 main() { log_info "🚀 开始使用二进制包安装MySQL..." echo "⚠️ 此操作将:" echo " 1. 备份现有MySQL数据文件" echo " 2. 停止现有MySQL服务" echo " 3. 解压并安装MySQL二进制包" echo " 4. 配置MySQL使用现有数据" echo " 5. 启动MySQL服务" echo " 6. 验证数据完整性" echo "" echo "⚠️ 数据文件将被保留" echo "" echo "是否继续?(y/N)" read -r confirm if [[ ! "$confirm" =~ ^[Yy]$ ]]; then log_warning "操作已取消" exit 0 fi check_connection backup_data_files stop_existing_services install_mysql_binary configure_mysql create_systemd_service start_mysql_service verify_data_integrity check_final_status log_success "🎉 MySQL二进制包安装完成!" echo "" echo "📋 安装结果:" echo " ✅ MySQL 8.0.24已从二进制包安装" echo " ✅ 现有数据文件已保留" echo " ✅ 服务正常运行" echo "" echo "📋 连接信息:" echo " 主机: localhost 或 47.111.10.27" echo " 端口: 3306" echo " 用户: root" echo " 密码: $MYSQL_ROOT_PASSWORD" echo " 数据库: emotion_museum" echo "" echo "📋 安装路径:" echo " 安装目录: $MYSQL_INSTALL_DIR" echo " 数据目录: $MYSQL_DATA_DIR" echo " 配置文件: /etc/my.cnf" echo "" echo "🔧 下一步:" echo " 1. 测试应用连接" echo " 2. 重启微服务: cd backend && ./deploy-remote.sh" } # 执行主函数 main "$@"