mysql 从 bash shell 连接密码时出现特殊字符错误

mysql 从 bash shell 连接密码时出现特殊字符错误
#!/bin/bash
set -x
MYSQLTEMPPWD=`grep 'temporary password' /var/log/mysqld.log | awk 'NF{ print 
$NF }'`;
MYSQLPWD=`echo "'$MYSQLTEMPPWD'"`;
echo $MYSQLPWD;
CONNINFO="mysql --host=localhost --user=root --password=$MYSQLPWD"
$CONNINFO <<EOF
ALTER USER 'root'@'localhost' IDENTIFIED BY 'Welcome!23';
show databases;
status;
EOF
set +x
exit
>  ./test.sh
++ grep 'temporary password' /var/log/mysqld.log
++ awk 'NF{ print $NF }'
+ MYSQLTEMPPWD='>fjkIyu#K7T?'
++ echo ''\''>fjkIyu#K7T?'\'''
+ MYSQLPWD=''\''>fjkIyu#K7T?'\'''
+ echo ''\''>fjkIyu#K7T?'\'''
'>fjkIyu#K7T?'
+ CONNINFO='mysql --host=localhost --user=root --password='\''>fjkIyu#K7T?'\'''
+ mysql --host=localhost --user=root '--password='\''>fjkIyu#K7T?'\'''
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
+ set +x

我遇到的问题是由于某些原因,在执行步骤期间在密码参数之前添加了单引号('--password='''>fjkIyu#K7T?'''')。

根据博客尝试了几乎所有可能的方法,但到目前为止都没有任何帮助。

有谁能给我一些建议吗?谢谢...

答案1

在以下启用了反馈的部分中set -x

'--password='\''>fjkIyu#K7T?'\'''

除两个单引号之外的所有内容都只是为了向您呈现这个字符串。这就是set -x工作原理。这只是 shell 实现执行跟踪的方式的产物;它不会改变参数最终传递给命令的方式。

mysql得到的正是:--password='>fjkIyu#K7T?'。此字符串中有两个文字单引号字符,因为添加了它们。这里:

MYSQLPWD=`echo "'$MYSQLTEMPPWD'"`

首先,echo这是一个错误。它它自身的问题但最奇怪的是,你只回显一个变量来捕获结果(使用反引号)并存储在另一个变量中。如果你想创建另一个具有相同值的变量,那么它就像这样简单:

MYSQLPWD="$MYSQLTEMPPWD"

或者如果您想在存储的字符串中添加单引号:

MYSQLPWD="'$MYSQLTEMPPWD'"

(看参数扩展和引号内的引号)。

我想我知道你为什么认为你需要这些单引号。这引出了另一个问题。你存储代码在变量中:

CONNINFO="mysql --host=localhost --user=root --password=$MYSQLPWD"

然后执行扩展的变量:

$CONNINFO …

一般来说你应该双引号。但是如果您用双引号引起来,"$CONNINFO"则会扩展为一个单词,而它不是命令。因此,您不需要引用来让单词拆分工作。但是,$MYSQLPWD扩展为(现在存储在里面CONNINFO)的任何内容都会经历单词拆分和文件名生成。我怀疑您将实际密码括在单引号中是为了防止这种情况发生。问题是,从扩展变量中出现的引号并不特殊,它们不会被 Shell 解释,也不会被删除。此时,不仅您添加的单引号不会阻止单词拆分或文件名生成;它们会mysql作为它获取的参数之一的一部分转到。

如果你让(或)shell 评估扩展(并正确双引号),这些引号就会起作用并消失$CONNINFO 再次

$CONNINFO如果您使用,当前 shell 将再次评估扩展eval "$CONNINFO",但是不要这样做$CONNINFO。如果你使用bash -c "$CONNINFO"(或或任何 shell),另一个 shell 将再次评估扩展sh -c …,它会和 一样糟糕eval

请注意,中的单引号字符$MYSQLTEMPPWD可以与您添加的开头单引号配对。再次解释时,密码的某些部分将取消引用。这可能导致语法错误、代码注入和其他缺陷。

变量根本不是用来存储代码的。为什么不让它保持简单呢?像这样:

mysql --host=localhost --user=root --password="$MYSQLTEMPPWD" <<EOF

这样,就不需要MYSQLPWDnor CONNINFO;并且应该引用的内容就会被引用。

好的,也许有问题的代码只是一个例子,你认为你真的需要在实际的、更复杂的脚本中将代码存储在变量中。那么请阅读我们如何运行存储在变量中的命令?


补充笔记:

  • 考虑小写变量名
  • 我的回答忽略了grep … | awk …可能需要改进的部分,但这是另一个故事。

相关内容