为什么while循环不循环?

时间:2016-04-23 00:25:35

标签: bash loops

我有以下bash脚本deploy.sh

#!/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 $user@$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的所有三行。

但是,当我尝试运行它时,它只执行一次迭代:

ubuntu@server:~$ bash deploy.sh
53.12.45.74
yo
done
ubuntu@server:~$

为什么?

如果循环只是:

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

它确实执行了所有三次迭代:

ubuntu@server:~$ bash deploy.sh
53.12.45.74
54.12.45.74
57.12.45.74
ubuntu@server:~$

2 个答案:

答案 0 :(得分:4)

sshpass正在控制stdin或可能替换它并导致while循环丢失重定向stdin的输入。

要解决此问题,请避免从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 $user@$ip  -o StrictHostKeyChecking=no -T "
  echo 'yo'
  "
  echo 'done'
done

第二个循环不会从stdin读取。

但我会建议使用与当前stdin不同的描述符Rany Albeg Wein answer

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

答案 1 :(得分: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 $user@$ip  -o StrictHostKeyChecking=no -T "
    #echo 'yo'

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

  else
    echo "Empty value.";
  fi

done < servers.txt

所以,现在它有效。