Bash脚本从CSV读取密码执行mysqldump的转义问题
解决Bash脚本中mysqldump密码转义问题
你的核心问题是对mysqldump的密码传递方式理解有误,加上脚本里的几个细节问题导致转义失效,下面直接给出修正方案和解释:
问题分析
${PASSWORD@Q}会给密码添加单引号(比如把abc!123转成'abc!123'),但mysqldump会把引号当成密码的一部分,直接导致认证失败。cat DB.csv | while read会创建子shell,属于不良写法,虽不影响当前脚本,但可能限制后续扩展。- 变量未用双引号包裹,当内容包含空格、特殊字符时会被Bash错误解析。
最优解决方案(安全且无转义问题)
推荐用MYSQL_PWD环境变量传递密码,这是官方认可的安全方式——密码不会出现在进程列表(ps命令无法查看),同时完全避免转义问题:
#!/bin/bash DATE=$(date "+%Y%m%d") # 提前创建备份目录,避免路径不存在报错 mkdir -p ../../backupDB # 直接读取CSV文件,避免子shell;-r参数防止反斜杠被解析为转义符 while IFS=";" read -r HOST DB USER PASSWORD; do # 跳过空行或不完整的配置行 [[ -z "$HOST" || -z "$DB" || -z "$USER" || -z "$PASSWORD" ]] && continue FILE="../../backupDB/$DB-$DATE.sql.gz" # 用环境变量传递密码,mysqldump会自动读取该变量 MYSQL_PWD="$PASSWORD" mysqldump --no-tablespaces --host="$HOST" --user="$USER" "$DB" | gzip > "$FILE" done < DB.csv
备选方案(直接用--password参数)
如果一定要用命令行参数传递,只需去掉${PASSWORD@Q},并用双引号包裹变量即可(注意:这种方式密码会暴露在进程列表中,安全性较差):
#!/bin/bash DATE=$(date "+%Y%m%d") mkdir -p ../../backupDB while IFS=";" read -r HOST DB USER PASSWORD; do [[ -z "$HOST" || -z "$DB" || -z "$USER" || -z "$PASSWORD" ]] && continue FILE="../../backupDB/$DB-$DATE.sql.gz" # 用双引号包裹变量,避免Bash解析特殊字符 mysqldump --no-tablespaces --host="$HOST" --user="$USER" --password="$PASSWORD" "$DB" | gzip > "$FILE" done < DB.csv
额外注意事项
- 确保CSV文件每行格式严格为
HOST;DB;USER;PASSWORD,无多余空格或换行符。 - 若密码包含特殊字符(如
!、$、&等),MYSQL_PWD方案无需额外处理,会自动适配。
内容的提问来源于stack exchange,提问作者Delirium6
相关产品推荐
相关产品推荐

