#!/bin/bash
# 用法: sh deploy_mysql.sh /path/mysql-5.6.28-linux-glibc2.5-x86_64.tar.gz /mysql3306 3306
set -euo pipefail
FILENAME=$1
BASEDIR=$2
PORT=$3
# 1. 系統用戶/組
id mysql &>/dev/null || groupadd mysql
id mysql &>/dev/null || useradd -r -g mysql -s /sbin/nologin mysql
# 2. 解壓並重命名
cd /usr/local
tar zxf "$FILENAME"
PKG_NAME=$(basename "$FILENAME")
DIR_NAME=${PKG_NAME%.tar.gz} # mysql-5.6.28-linux-glibc2.5-x86_64
INST_DIR="mysql${PORT}" # mysql3306
mv "$DIR_NAME" "$INST_DIR"
cd "$INST_DIR"
# 3. 配置文件模板化處理
CONF_TEMPLATE=$(dirname "$FILENAME")/my.cnf.template
[[ -f "$CONF_TEMPLATE" ]] || { echo "ERROR: 模板 $CONF_TEMPLATE 不存在"; exit 1; }
USER_CNF="my${PORT}.cnf"
cp "$CONF_TEMPLATE" "./$USER_CNF"
# 路徑轉義技巧:將 / 替換為 |,sed 替換後再換回
ESCAPED_BASEDIR=${BASEDIR//\//|}
sed -i "s|/project/class2|$ESCAPED_BASEDIR|g" "$USER_CNF"
sed -i "s|\\||/|g" "$USER_CNF"
# 關鍵參數自動注入
SERVER_ID=$(date +%s) # 秒級時間戳,極低衝突概率
sed -i "s/^server_id.*/server_id=$SERVER_ID/" "$USER_CNF"
sed -i "s/^port.*/port=$PORT/" "$USER_CNF"
# 4. 目錄結構與權限
mkdir -p "${BASEDIR}/mysql/{run,data,log,tmp,share}"
chown -R mysql:mysql "$BASEDIR"
chown -R root:root . # 程序文件歸 root
chown -R mysql:mysql data/ # 數據目錄歸 mysql
# 5. 錯誤消息文件 (某些版本啟動依賴)
[[ -f share/english/errmsg.sys ]] && cp share/english/errmsg.sys "${BASEDIR}/mysql/share/"
# 6. 初始化數據目錄 (5.6/5.7 通用)
./scripts/mysql_install_db --user=mysql --defaults-file="./$USER_CNF" --force
# 7. 啟動實例 (後台安全模式)
./bin/mysqld_safe --defaults-file="./$USER_CNF" --user=mysql &
# 8. 註冊系統服務 (可選)
cp support-files/mysql.server "/etc/init.d/mysqld${PORT}"
sed -i "s|^basedir=.*|basedir=/usr/local/$INST_DIR|" "/etc/init.d/mysqld${PORT}"
sed -i "s|^datadir=.*|datadir=${BASEDIR}/mysql/data|" "/etc/init.d/mysqld${PORT}"
echo "✅ MySQL 實例 $PORT 部署完成"
echo " 基礎目錄: $BASEDIR"
echo " 配置文件: /usr/local/$INST_DIR/$USER_CNF"
echo " 服務名: mysqld${PORT}"
echo " 連接測試: mysql -uroot -P$PORT -h127.0.0.1 -S ${BASEDIR}/mysql/run/mysql.sock"
[mysqld] basedir=/project/class2/mysql datadir=/project/class2/mysql/data tmpdir=/tmp socket=/project/class2/mysql/run/mysql.sock pid-file=/project/class2/mysql/run/mysqld.pid log-error=/project/class2/mysql/log/alert.log slow_query_log_file=/project/class2/mysql/log/slow.log server_id=2552763370 # 將被腳本自動覆蓋 port=3306 # 將被腳本自動覆蓋 # InnoDB 核心參數 (按實例內存調整) innodb_buffer_pool_size=1G innodb_log_file_size=256M innodb_file_per_table=1 innodb_flush_log_at_trx_commit=1 # Binlog & Replication log-bin=/project/class2/mysql/log/mysql-bin binlog_format=ROW expire_logs_days=7 gtid_mode=ON enforce_gtid_consistency=ON # 安全與連接 skip-name-resolve max_connections=2000 max_connect_errors=100000
| 報錯現象 | 原因 | 腳本內修復邏輯 |
|---|---|---|
FATAL ERROR: Neither host 'xxx' nor 'localhost' could be looked up | hostname 解析失敗 | --force 強制初始化 |
Can't find messagefile '/.../share/errmsg.sys' | 語言文件缺失 | 自動 cp share/english/errmsg.sys $BASEDIR/mysql/share/ |
Can't create/write to file '/var/run/mysqld/mysqld.pid' | pid 目錄不存在/權限錯誤 | 腳本 mkdir -p .../run + chown mysql |
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' | 客戶端默認找 /tmp/mysql.sock | 連接時顯式指定 -S $BASEDIR/mysql/run/mysql.sock 或 -h 127.0.0.1 |
innodb_buffer_pool_size 總和 ≤ 物理內存 70%;cpuset 綁核 (Docker/cgroups) 物理隔離 CPU。mysqld_exporter 部署多實例採集,標籤 instance="host:port"。xtrabackup 排程,備份目錄掛載獨立存儲卷。這個腳本將「人工操作 30 分鐘、易出錯」壓縮為「一條命令 2 分鐘、標準化輸出」。核心在於:**模板化配置 + 路徑自動重寫 + 關鍵參數自動生成 + 目錄權限標準化 + 常見坑預埋修復**。團隊可在此基礎上擴展 Ansible Role、SaltStack State 或 Kubernetes Operator,實現全生命周期自動化運維。