2015-02-04 20 views
1

語境循環停止隨EVAL和工藝替代

功能後,我有一個腳本,在一個列表上循環。在每次迭代時,它都需要調用一個函數來構造一個'diff'命令來通過'eval'比較兩個遠程文件。

'diff'命令通過兩個進程替換獲取其輸入,其中每個進程通過執行無密碼身份驗證(通過公鑰/私鑰)的'ssh'來俘獲遠程文件。

'diff'和'ssh'執行已經經過腳本測試,並且工作正常。

代碼

這裏我發表我的劇本很短的版本,但是產生了同樣的問題:

#!/bin/bash 
func(){ 
    NUM=$1 
    echo "func $NUM" 
    COMMAND="diff <(ssh [email protected] 'cat file1') <(ssh [email protected] 'cat file2')" 
    eval "${COMMAND}" 1>/dev/null 
    RESULT=$? 
} 

LIST="1 
2 
3 
4 
5" 

echo "$LIST" | while read NUM ; do 
    echo "main $NUM" 
    func $NUM 
done 

預期結果

main 1 
func 1 
main 2 
func 2 
main 3 
func 3 
main 4 
func 4 
main 5 
func 5 

問題

腳本的第一個迭代後停止:

main 1 
func 1 

問題

你知道爲什麼循環停止?以及如何解決它?

回答

1

這不是評估或過程替代。這是ssh

ssh默認將stdin傳遞到它在遠程服務器上運行的命令(並從遠程命令傳回stdout)。這使得它可以在流水線中使用。但是,在這種情況下,您不希望ssh觸摸stdin,因爲您正在自行使用該循環。

你可以很容易地得到ssh不,無論是使用-n命令行選項,或通過重新使用stdinstdin/dev/null

ssh -n [email protected] 'cat file1' 
ssh [email protected] 'cat file1' < /dev/null 

後者也將在調用函數工作:

echo "$LIST" | while read NUM ; do 
    echo "main $NUM" 
    func $NUM < /dev/null 
done 

我想你不想要演講eval的邪惡,但是我覺得有必要提及以這種方式使用eval可能是不必要的。我認爲你正在這樣做,以建立一個使用過程替代的命令。相反,您可以使用exec建立一個包含進程替換的環境,例如:

exec 10< <(ssh -n [email protected] 'cat file1') 
+0

感謝四位關於exec的良好解釋和建議。 – Manolo