2016-04-23 222 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

谢谢,我刚刚尝试过,问题仍然存在:它只执行一次迭代:( –