1

I have the following bash script 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 contains:

53.12.45.74 my_username my_password
54.12.45.74 my_username my_password
57.12.45.74 my_username my_password
‌‌ 

From my understanding, the while read ip user pass; do […] done < servers.txt should loop over all three lines of servers.txt.

However, when I try to run it, it only performs one iteration:

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

Why?


If the loop is simply:

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

it does perform all three iterations:

ubuntu@server:~$ bash deploy.sh
53.12.45.74
54.12.45.74
57.12.45.74
ubuntu@server:~$
Franck Dernoncourt
  • 77,520
  • 72
  • 342
  • 501
  • Is that a complete script or a representative of the real script? If it's a representative, you may have overlooked a `break` statement inside the while loop. – alvits Apr 23 '16 at 00:38
  • @alvits complete script, I just changed the IPs, usernames and passwords. – Franck Dernoncourt Apr 23 '16 at 00:39
  • 1
    It would seem `sshpass` is taking control of `stdin` or possibly replacing it and causing `while` loop to lose input from redirected `stdin`. Try to run `sshpass` within a subshell like `(sshpass -p "$pass" ssh $user@$ip -o StrictHostKeyChecking=no -T " echo $pass | sudo -S sudo /etc/init.d/ganglia-monitor restart ")` and see if the problem gets resolved. – alvits Apr 23 '16 at 00:44
  • @alvits: I think that's right. Consider posting it as an answer. – John Zwinck Apr 23 '16 at 00:45

2 Answers2

4

sshpass is taking control of stdin or possibly replacing it and causing while loop to lose input from redirected stdin.

To work around this issue, avoid reading from stdin.

First, load the file into an array using a while loop.

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

Next, use for loop to parse the lines and execute sshpass within this loop.

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

The second loop doesn't read from stdin.

But I will recommend Rany Albeg Wein answer using a separate descriptor than the current 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
Community
  • 1
  • 1
alvits
  • 6,550
  • 1
  • 28
  • 28
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

So, now it works.

Franck Dernoncourt
  • 77,520
  • 72
  • 342
  • 501
Timoshenko
  • 26
  • 5