Bash 脚本:在脚本内部使用引号内的变量运行 shell 命令

Bash 脚本:在脚本内部使用引号内的变量运行 shell 命令

我需要将数据库加载到 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;"

相关内容