我需要将数据库加载到 mysql 服务器中,并且以下命令在 shell 中运行:
从 shell
mysql -h "172.17.0.2" -u "root" -p"mypasswd" -Bse "create database mydb;"
但不是从脚本中获取的,其中 ip 和密码是作为参数传递的变量:
剧本:
#!/bin/bash
set -e
sqlname=$1
sqlpass=$2
sqlip=$3
...
set -x
echo "Creating the database..."
mysql -h $sqlip -u "root" -p$sqlpass -Bse "create database mydb;"
脚本的结果:
./myscript.sh mysql1 mypasswd 172.17.0.2
创建数据库...
+ mysql -h 172.17.0.2 -u root -pmypasswd -Bse 'create database mydb;'
错误 2003 (HY000): 无法连接到‘172.17.0.2’上的 MySQL 服务器 (111)
-- 开始编辑
双引号内的变量结果相同:
#!/bin/bash
...
mysql -h "$sqlip" -u root -p"$sqlpass" -Bse "create database mydb;"
+ echo '正在创建数据库...' 正在创建数据库...
+ mysql -h 172.17.0.2 -u root -pmypasswd -Bse '创建数据库 mydb;' 错误 2003 (HY000):无法连接到 '172.17.0.2' 上的 MySQL 服务器 (111)
-- 结束编辑
脚本内部带有变量的双引号和单引号让我感到困惑。
我在这里遗漏了一些关于在内部和引号中使用变量的明显内容。
有什么提示吗?
答案1
使用引号是为了阻止 shell 解释某些标点符号,例如空格(参数分隔符)、>
(输出重定向)、*
(文件掩码中的通配符)等。
单引号会阻止对所引用文本的所有解释,而双引号则允许$
扩展(以及其他一些)。脚本中的命令与在交互式提示中输入的命令没有区别。
IP 地址没有 shell 特定字符,也没有root
,因此无需将它们括起来。如果您的密码包含 shell 特定字符(例如空格),则需要将其括起来,并且由于需要$
扩展,因此它们需要双引号。该-Bse
参数既有空格又有;
,因此需要将其括起来,但两者都可以,因为没有$
扩展。
您正在扩展的变量$sqlip
需要$sqlpass
在执行脚本的子 shell 中定义,因此需要在子 shell 中设置它们或者export
在调用 shell 中设置它们。
答案2
密码变量中可能有一些被 shell 特殊处理的字符。
一般来说,最佳做法是总是引用 shell 变量以避免不必要的副作用,例如标记拆分和通配符扩展。请参阅什么时候需要双引号?来自 Unix 和 Linux Stack Exchange。
mysql -h "$sqlip" -u root -p"$sqlpass" -Bse "create database mydb;"