2013-07-05 63 views
-1

这是我第一次使用真正的bash脚本,并且在扩展和引用方面遇到了相当大的麻烦。BASH:在变量中存储嵌套命令参数

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

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

sql="SELECT id FROM user WHERE (email LIKE '%[email protected]' OR email LIKE '%[email protected]');" 

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[*]}") 

正如你可能已经注意到,我很在这一点上失去了,我觉得这是越来越太复杂了。任何人都可以分享一些关于如何正确执行此操作的技巧

谢谢

+0

我......并不感到惊讶,你遇到麻烦了。考虑使用SSH隧道,而不是通过SSH运行命令。 –

+0

是的,或者也可以放弃使脚本如此动态的想法。毕竟,如果我明确地写出这些命令,那么一切正常。 –

+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\"被解析为两个参数的原始形式没有工作:"foobar";引号在转义时被视为数据而不是语法。


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

+0

谢谢!尽管我去了一个Ruby脚本。这太艰难了。我猜Bash应该保持简单。 –