-1

这是我第一次使用真正的 bash 脚本,我在扩展和引用方面遇到了很大的麻烦。

如果给定参数-t,我正在编写一个测试ssh连接和一些远程mysql命令的脚本,如果给定参数-r,则在真正的远程服务器上使用它们。我想将 ssh 和 mysql 命令的选项存储到变量中,因此当给出 -r 或 -t 时,它使用相同的例程。

长话短说,脚本看起来或多或少是这样的:

sql="SELECT id FROM user WHERE (email LIKE '%a@b.com' OR email LIKE '%c@d.com');"

case "$1" in
  -t )
      ssh_opts=(localhost -i ~/.ssh/id_rsa)
      mysql_opts=(-u root --password=password test);;

  -r )
      ssh_opts=("-oCheckHostIP no" "-oCompression yes" "-oProtocol 2" "-oProxyCommand connect -4 -S localhost:9050 $(tor-resolve remoteip localhost:9050) 22" remoteip -i ~/.ssh/id_rsa -l httpd)
      mysql_opts=('-h mysqlserver' '-P 3306' '-u user' '--password=password' database) -t );;
esac


read -a ids < <(ssh "${ssh_opts[@]}" \"mysql "${mysql_opts[@]" --disable-column-names -B -e \"$'${sql}'\""\")
csv_ids=$(IFS=,; echo "${ids[*]}")

正如您可能已经注意到的那样,我此时非常迷茫,而且我觉得这变得太复杂了。任何人都可以分享一些关于如何正确执行此操作的提示吗?

谢谢

4

1 回答 1

2

在这部分之前,你的表现还不错:

read -a ids < <(ssh "${ssh_opts[@]}" \"mysql "${mysql_opts[@]" --disable-column-names -B -e \"$'${sql}'\""\")

要生成 mysql 命令,请使用printf %q引用它们,然后使用printf %q正确引用的字符串:

printf -v mysql_opts_str '%q ' "${mysql_opts[@]}"
ssh "${ssh_opts[@]}" "mysql $mysql_opts_str ..."

原始形式不起作用,因为\"foo bar\"它被解析为两个参数:"foo, 和bar"; 转义时,引号被视为数据,而不是语法。


也就是说——bash 通常是用于与 SQL 交互的错误工具;它不提供用于解析任意表内容的工具(因此您最终会对查询结果做出假设),也不提供用于将任意字符串作为绑定变量传递的工具。(我曾经写过一个支持这种支持的命令行 Oracle 客户端,旨在供 shell 脚本使用,但它从未公开发布过)。您应该认真考虑使用更适合这项工作的工具。

于 2013-07-05T04:13:23.107 回答