2014-03-06 89 views
1

我每天工作在一個特定的客戶環境上,由5個AIX服務器組成,有時我需要在所有5個AIX服務器上發出相同的命令。Shell腳本調用ssh:如何解釋遠程服務器上的通配符

所以我建立了基於SSH密鑰的認證服務器之間,並颳起了該廣播命令所有的人一點點的ksh腳本:

#!/usr/bin/ksh 

if [[ $# -eq 0 ]]; then 
     print "broadcast.ksh - broadcasts a command to the 5 XXXXXXXX environments and returns output for each" 
     print "usage:     ./broadcast.ksh command_to_issue" 
     exit 
fi 

set -A CUST_HOSTS aaa bbb ccc ddd eee 

for host in ${CUST_HOSTS[@]}; do 

     echo "============ $host ================" 

     if [[ `uname -n` = $host ]]; then 
       $* 
       continue 
     fi 

     ssh $host $* 

done 

echo "=========================================" 
echo "Finished" 

現在,這個工作得很好,直到我想使用通配符在遠端,是這樣的:

./broadcast.ksh ls -l java* 

因爲「*」是本地系統上展開,而不是遙控器。

現在,如果使用ssh遠程命令,我可以解決這個問題,通過使用單引號:

ssh [email protected] ls -l java* <-- will _not_ work as expected, since asterisk will be interpreted locally 
ssh [email protected] 'ls -l java*' <-- _will_ work as expected, since asterisk will be interpreted on the remote end 

現在,我試圖將此主題融入我的腳本,並試圖創建一個$命令變量由單引號包圍的$ *內容組成,但在ksh中逃避反斜槓和串聯嘗試的海洋中淹沒了,無濟於事。

我確定有一個簡單的解決方案,但我沒有發現它,所以認爲我會出來問。

感謝,

詹姆斯

+0

將增加一倍報價工作更好? AFAIK他們將保留通配符,但仍然擴大$。 – Holloway

+0

謝謝,@Trengot,但他們沒有。這是我測試過的東西之一,但爲了以防萬一,我繼續進行重新測試。它仍然解釋本地系統上的星號。 – James

+1

@James這可能不會回答你的問題,但可以給你一個想法,而不是從頭開始創建自己的腳本。有一個名爲[** dsh **]的工具(http://www.netfort.gr.jp/~dancer/software/dsh.html.en),它是一個將多個shell命令執行到遠程主機的包裝器。此外,你可能想檢查[**本網站**](https://www.ibm.com/developerworks/aix/library/au-aix-run-commands/)關於如何使用* *並行SSH ** –

回答

1

當你發現,經過一個星號作爲參數傳遞給你的腳本不能正常工作,因爲shell擴展它被處理的參數之前。嘗試雙引號$*,並在腳本調用中用反斜槓或星號引用該命令來轉義星號/分號等。

for host in ${CUST_HOSTS[@]}; do 
    echo "============ $host ================" 
    if [[ `uname -n` = $host ]]; then 
     "$*" 
     continue 
    fi 
    ssh $host "$*" 
done 

$ ./broadcast.ksh ls -l java\* 

$ ./broadcast.ksh 'ls -l java*; ls -l *log' 
+0

謝謝喬希的建議,但都沒有工作。星號仍然在本地系統中解釋。 – James

+1

@詹姆斯解決方法可以避免通配符...我知道,我知道,根本不是優雅的:-p 像'$ ./broadcast.ksh'ls -l |我相信,grep^java''應該可以工作。 –

+0

是@jim,當我決定將它帶入SO社區時,並不是我所希望的......但我必須承認這個想法的一些優點。 :-) – James

1

我想發表評論,但仍然太低,但喬希的單引號建議應該工作。

  • 我打滑了幾個虛擬機的每2個文件在/ tmp目錄:/ tmp目錄/ foo1和/ tmp目錄/ foo2的
  • 然後使用你的腳本的變化
[email protected]:~# cat foo.sh 
#!/usr/bin/ksh 

if [[ $# -eq 0 ]]; then 
     print "broadcast.ksh - broadcasts a command to the 5 XXXXXXXX environments and returns output for each" 
     print "usage:     ./broadcast.ksh command_to_issue" 
     exit 
fi 

set -A CUST_HOSTS jdsdropfed1 jdsdropfed2-2 

for host in ${CUST_HOSTS[@]}; do 

     echo "============ $host ================" 

     if [[ `uname -n` = $host ]]; then 
       $* 
       continue 
     fi 

     ssh $host $* 

done 

echo "=========================================" 
echo "Finished" 
[email protected]:~# ./foo.sh 'ls /tmp/foo*' 
============ jdsdropfed1 ================ 
/tmp/foo1 
/tmp/foo2 
============ jdsdropfed2-2 ================ 
/tmp/foo1 
/tmp/foo2 
========================================= 
Finished 
[email protected]:~# ssh jdsdropfed1 "ls /tmp/foo*" 
/tmp/foo1 
/tmp/foo2 
[email protected]:~# ssh jdsdropfed2-2. "ls /tmp/foo*" 
/tmp/foo1 
/tmp/foo2 
相關問題