#!/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
…
这样,就不需要MYSQLPWD
nor CONNINFO
;并且应该引用的内容就会被引用。
好的,也许有问题的代码只是一个例子,你认为你真的需要在实际的、更复杂的脚本中将代码存储在变量中。那么请阅读我们如何运行存储在变量中的命令?
补充笔记:
- 考虑小写变量名。
- 我的回答忽略了
grep … | awk …
可能需要改进的部分,但这是另一个故事。