0

Consider the below scenario

2 vms - 192.168.229.131, 192.168.229.132

Both the vms has it's ip as 192.168.229.151 & 192.168.229.152 in it's /etc/hosts file

Say there are around 50 vms like I said above. But as of now, I am considering only the above 2.

I saved ips of the 2 vms in a file named server

#cat server
192.168.229.131
192.168.229.132

Below is the script

#!/bin/bash
cat server | while read line
do
/usr/bin/sshpass -e ssh -t -q -o StrictHostKeyChecking=no root@$line << EOF
echo successfully logged in $line
MYIP=$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p')
for i in 151 152
do
echo 192.168.229.\$i >> errips
done
for data in `cat errips`
do
echo data currently has $data
grep $data /etc/hosts
if [ $? -eq 0 ]
then
sed -i "s/$data/$MYIP/g" /etc/hosts
echo "completed"
unset MYIP
rm -rf errips
exit 0
fi
done
EOF
done

Below is the output

root@master:~# ./script
cat: errips: No such file or directory
successfully logged in 192.168.229.131
cat: errips: No such file or directory
successfully logged in 192.168.229.132

Why does the for loop after logging in the server is getting executed before logging in?

I tried using the below instead of 'for'

cat errips |while read line
echo line currently has $line

In this case, I found that line is still taking the IP from server file in localhost, whereas it should read it from errips file of the server i remotely logged in.

Output was

line currently has 192.168.229.131
line currently has 192.168.229.132

whereas I expected that it should read the values in file "errips" and output should be something like below

line currently has 192.168.229.151
line currently has 192.168.229.151

Now, I tried below command

cat errips |while read data
echo data currently has $data

In this case, the output was empty for the value data

data currently has 
data currently has

How would I read the file "errips" in my remote server line by line, and grep for the line in /etc/hosts and then execute the if loop, which will replace the wrong ip with right ip?

1

You need to single quote your here document limit string, otherwise parameter substitution will be enabled. This should work:

#!/bin/bash
cat server | while read line
do
  /usr/bin/sshpass -e ssh -t -q -o StrictHostKeyChecking=no root@$line <<'EOF'
  echo successfully logged in $line
  MYIP=$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p')
  for i in 151 152
  do
    echo 192.168.229.$i >> errips
  done
  for data in `cat errips`
  do
    echo data currently has $data
    grep $data /etc/hosts
    if [ $? -eq 0 ]
    then
      sed -i "s/$data/$MYIP/g" /etc/hosts
      echo "completed"
      unset MYIP
      rm -rf errips
      exit 0
    fi
  done
EOF
done

Notice the single quotes around EOF. To further illuminate, try the following:

/usr/bin/sshpass -e ssh -t -q -o StrictHostKeyChecking=no root@<your_ip> 'k=1; echo $k'
/usr/bin/sshpass -e ssh -t -q -o StrictHostKeyChecking=no root@<your_ip> "k=1; echo $k"
/usr/bin/sshpass -e ssh -t -q -o StrictHostKeyChecking=no root@<your_ip> "k=1; echo \$k"
  • Awesome.. it worked... so, behavior is same when using either double quotes or no quotes.. I tried the 3 commands you have given and found that when I am using double or no quotes, it's taking the value of k as stored in my server and not as i have declared in the command before it.. Thank you so much – Being Gokul Oct 18 '14 at 14:48
  • single quoting is not necessary - any quoting works. <<"EOF" or <<\EOF work just as well. – mikeserv Oct 18 '14 at 15:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.