为什么这个 while 循环不循环?

Fra*_*urt 2 bash loops

我有以下 bash 脚本deploy.sh

\n\n
#!/usr/bin/env bash\n\n# Some useful resources:\n# while read ip user pass; do : http://unix.stackexchange.com/questions/92664/how-to-deploy-programs-on-multiple-machines\n# -o StrictHostKeyChecking=no: http://askubuntu.com/questions/180860/regarding-host-key-verification-failed\n# -T: http://stackoverflow.com/questions/21659637/how-to-fix-sudo-no-tty-present-and-no-askpass-program-specified-error\n# echo $pass |: http://stackoverflow.com/questions/11955298/use-sudo-with-password-as-parameter\n\nwhile read ip user pass; do \n  echo $ip\n  sshpass -p "$pass" ssh $user@$ip  -o StrictHostKeyChecking=no -T "\n  echo \'yo\'\n  "\n  echo \'done\'\ndone < servers.txt\n
Run Code Online (Sandbox Code Playgroud)\n\n

servers.txt包含:

\n\n
53.12.45.74 my_username my_password\n54.12.45.74 my_username my_password\n57.12.45.74 my_username my_password\n\xe2\x80\x8c\xe2\x80\x8c \n
Run Code Online (Sandbox Code Playgroud)\n\n

根据我的理解,while read ip user pass; do [\xe2\x80\xa6] done < servers.txt应该循环servers.txt.

\n\n

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

\n\n
ubuntu@server:~$ bash deploy.sh\n53.12.45.74\nyo\ndone\nubuntu@server:~$\n
Run Code Online (Sandbox Code Playgroud)\n\n

为什么?

\n\n
\n\n

如果循环很简单:

\n\n
while read ip user pass; do \n      echo $ip\ndone < servers.txt\n
Run Code Online (Sandbox Code Playgroud)\n\n

它执行所有三个迭代:

\n\n
ubuntu@server:~$ bash deploy.sh\n53.12.45.74\n54.12.45.74\n57.12.45.74\nubuntu@server:~$\n
Run Code Online (Sandbox Code Playgroud)\n

alv*_*its 5

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

要解决此问题,请避免从 stdin 读取。

首先,使用循环将文件加载到数组中while

while read line; do
    entries+=("$line")
done < servers.txt
Run Code Online (Sandbox Code Playgroud)

接下来,使用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
Run Code Online (Sandbox Code Playgroud)

第二个循环不读取stdin.

但我会建议Rany Albeg Wein 的 答案使用一个单独的描述符而不是当前的stdin.

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
Run Code Online (Sandbox Code Playgroud)