腳本化運維 MySQL 時,mysql -e 與 <<EOF 是兩大核心範式。本文系統對比適用場景、參數傳遞、變量插值、多語句執行、退出碼捕獲、安全性六個維度,給出選型決策表與最佳實踐模板。
# 基礎用法
mysql -uroot -p'PassW0rd' -e "CREATE DATABASE dbtest;"
# 多語句(分號分隔,需加引號)
mysql -uroot -p'PassW0rd' -e "CREATE DATABASE dbtest; USE dbtest; CREATE TABLE t1 (id INT PRIMARY KEY);"
# 變量插值(Shell 變量 → SQL)
DB="db_$(date +%Y%m)"
mysql -uroot -p'PassW0rd' -e "CREATE DATABASE \`$DB\`;"
# 捕獲退出碼
mysql -uroot -p'PassW0rd' -e "SELECT 1;"
if [ $? -ne 0 ]; then echo "SQL 執行失敗"; exit 1; fi
# 標準模板
mysql -uroot -p'PassW0rd' <<'EOF'
CREATE DATABASE dbtest;
USE dbtest;
CREATE TABLE t1 (
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL
);
INSERT INTO t1 VALUES (1, 'test');
EOF
# 帶變量插值(去掉 EOF 引號)
TABLE_PREFIX="t_$(date +%s)"
mysql -uroot -p'PassW0rd' <
| 維度 | -e 參數 | Here Document |
|---|---|---|
| 語句長度 | 短(< 1000 字符) | 任意長(含存儲過程、觸發器) |
| 多語句 | 分號分隔,單行難讀 | 原生換行,結構清晰 |
| 變量插值 | 雙引號內直接 $VAR | 無引號 EOF 直接 $VAR,引號 EOF 需 \$VAR |
| 特殊字符轉義 | 雙重轉義(Shell+SQL) | 僅 SQL 層轉義,較簡單 |
| 密碼安全 | 命令行明文(ps 可見) | 同樣風險,建議均用 --defaults-extra-file |
| 退出碼 | 直接 $? | 同樣 $?,但管道場景需 PIPESTATUS |
| 交互式體驗 | 無 | 可配合 tee 記錄輸出 |
# 1. 創建客戶端配置文件(權限 600)
cat > ~/.my.cnf <<'EOF'
[client]
user=root
password=PassW0rd
host=127.0.0.1
port=3306
EOF
chmod 600 ~/.my.cnf
# 2. 腳本中無需指定 -u/-p
mysql -e "SELECT VERSION();"
mysql <<'EOF'
SHOW DATABASES;
EOF
#!/bin/bash
set -euo pipefail
LOG="/var/log/mysql_ops_$(date +%F).log"
exec > >(tee -a "$LOG") 2>&1
run_sql() {
local sql="$1" desc="$2" max_retry=3 interval=5
for i in $(seq 1 $max_retry); do
echo "[$(date)] $desc (嘗試 $i/$max_retry)"
if mysql --defaults-extra-file=/root/.my.cnf -e "$sql"; then
echo "[$(date)] 成功"
return 0
fi
sleep $interval
done
echo "[$(date)] 失敗:$desc" >&2
return 1
}
# 使用示例
run_sql "CREATE DATABASE IF NOT EXISTS \`biz_$(date +%Y%m)\`;" "創建月度業務庫"
run_sql "SOURCE /backup/schema_latest.sql;" "導入表結構"
--defaults-extra-file 隔離憑證,禁用命令行密碼掌握兩大範式的邊界與組合,能將 MySQL 運維腳本從「能跑」進化為「可讀、可維、可審、可安」。