2016-04-23 286 views
1

我有以下bash腳本deploy.sh爲什麼這個while循環不循環?

#!/usr/bin/env bash 

# Some useful resources: 
# while read ip user pass; do : http://unix.stackexchange.com/questions/92664/how-to-deploy-programs-on-multiple-machines 
# -o StrictHostKeyChecking=no: http://askubuntu.com/questions/180860/regarding-host-key-verification-failed 
# -T: http://stackoverflow.com/questions/21659637/how-to-fix-sudo-no-tty-present-and-no-askpass-program-specified-error 
# echo $pass |: http://stackoverflow.com/questions/11955298/use-sudo-with-password-as-parameter 

while read ip user pass; do 
    echo $ip 
    sshpass -p "$pass" ssh [email protected]$ip -o StrictHostKeyChecking=no -T " 
    echo 'yo' 
    " 
    echo 'done' 
done < servers.txt 

servers.txt包含:

53.12.45.74 my_username my_password 
54.12.45.74 my_username my_password 
57.12.45.74 my_username my_password 
‌‌ 

從我的理解,應該while read ip user pass; do […] done < servers.txt遍歷所有三行servers.txt

然而,當我嘗試運行它,它只能執行一次迭代:

[email protected]:~$ bash deploy.sh 
53.12.45.74 
yo 
done 
[email protected]:~$ 

爲什麼?


如果循環很簡單:

while read ip user pass; do 
     echo $ip 
done < servers.txt 

它並執行所有三個迭代:

[email protected]:~$ bash deploy.sh 
53.12.45.74 
54.12.45.74 
57.12.45.74 
[email protected]:~$ 
+0

這是一個完整的腳本還是真實劇本的代表?如果它是一個代表,你可能忽略了while循環中的break語句。 – alvits

+0

@alvits完成腳本,我只是改變了IP,用戶名和密碼。 –

+1

看起來'sshpass'正在控制'stdin'或可能替換它並導致'while'循環丟失來自重定向的'stdin'的輸入。嘗試在'(sshpass -p「$ pass」ssh $ user @ $ ip -o StrictHostKeyChecking = no -T「)子shell中運行'sshpass' echo $ pass | sudo -S sudo /etc/init.d/ganglia -monitor restart 「)'並查看問題是否得到解決。 – alvits

回答

4

sshpass是服用stdin控制或可能取代它,造成while循環失去來自重定向的輸入stdin

要解決此問題,請避免從標準輸入讀取。

首先,使用while循環將文件加載到數組中。

while read line; do 
    entries+=("$line") 
done < servers.txt 

接下來,使用for循環解析線和該環內執行sshpass

for line in "${entries[@]}"; do 
    set $line 
    ip=$1 
    user=$2 
    pass=$3 
    echo $ip 
    sshpass -p "$pass" ssh [email protected]$ip -o StrictHostKeyChecking=no -T " 
    echo 'yo' 
    " 
    echo 'done' 
done 

第二個循環不從stdin讀取。

但我會推薦Rany Albeg Weinanswer使用一個單獨的描述符比當前stdin

while read ip user pass <&3; do 
    echo $ip 
    sshpass -p "$pass" ssh [email protected]$ip -o StrictHostKeyChecking=no -T " 
    echo 'yo' 
    " 
    echo 'done' 
done 3<servers.txt 
+0

謝謝,我剛剛嘗試過,問題仍然存在:它只執行一個迭代:( –

+1

@FrankDernoncourt我在這裏回答了類似的問題http://stackoverflow.com/a/36584819/5649859 –

+0

感謝您的編輯,兩個選項很好。 –

0
#!/usr/bin/env bash 

# Some useful resources: 
# while read ip user pass; do : http://unix.stackexchange.com/questions/92664/how-to-deploy-programs-on-multiple-machines 
# -o StrictHostKeyChecking=no: http://askubuntu.com/questions/180860/regarding-host-key-verification-failed 
# -T: http://stackoverflow.com/questions/21659637/how-to-fix-sudo-no-tty-present-and-no-askpass-program-specified-error 
# echo $pass |: http://stackoverflow.com/questions/11955298/use-sudo-with-password-as-parameter 

while read ip user pass; do 

    if [ -n "$ip" ]; then 

    echo "IP[$ip] USER[$user] PASS[$pass]"; 

    # dont forget to uncomment this two lines here: 
    #sshpass -p "$pass" ssh [email protected]$ip -o StrictHostKeyChecking=no -T " 
    #echo 'yo' 

    echo ""; # Just a blank line" 
    echo "done."; 

    else 
    echo "Empty value."; 
    fi 

done < servers.txt 

所以,現在它的工作原理。

+0

謝謝,我剛剛嘗試過,問題仍然存在:它只執行一次迭代:( –