2013-07-05 108 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應該保持簡單。 –