Shell 引号转义的一个坑
写一个数据库同步脚本,密码放在变量里,调用 mysql 时死活认证失败:
PASS='my#pass123'
mysql -uroot -p"$PASS" ... # OK
MYSQLCMD="mysql -uroot -p'$PASS'"
$MYSQLCMD ... # 认证失败!
排查后发现:把命令拼进字符串变量后,单引号变成了字面字符传给了 mysql,实际发送的密码变成了 'my#pass123'(带引号),当然认证失败。
解决办法
官方推荐用环境变量传密码,简单干净:
export MYSQL_PWD='my#pass123'
mysql -uroot -e "select 1"
省去了所有引号转义问题,脚本也清爽了。
经验
- 命令拼接进字符串变量是引号灾难的重灾区,能用函数就别拼字符串
- 复杂数据(含引号、特殊字符)一律用环境变量或参数数组传递
- 认证失败先 echo 一下实际发送的命令,看看引号是不是变成了字面量