3
$ ls
testscript.sh  testservers.txt
$ cat testservers.txt 
serverA IMM 10.2.3.4    USERID  PASSW0RD
serverB IMM 10.2.3.5    USERID  PASSW0RD
$ 
$ 
$ cat testscript.sh 
#!/bin/bash

# test them..
egrep -vi '^#|^$' testservers.txt | while read ONELINE; do
    # variables..
    SERVER=`echo "$ONELINE" | awk 'BEGIN {FS="\t"} {print $1}'`
    RSATYPE=`echo "$ONELINE" | awk 'BEGIN {FS="\t"} {print $2}'`
    IP=`echo "$ONELINE" | awk 'BEGIN {FS="\t"} {print $3}'`
    USER=`echo "$ONELINE" | awk 'BEGIN {FS="\t"} {print $4}'`
    PWD=`echo "$ONELINE" | awk 'BEGIN {FS="\t"} {print $5}'`

if [ "$RSATYPE" = "IMM" ]; then
    # main testing part for IMM
        timeout 5 tsocks nc -z -w 3 "${IP}" 80 > /dev/null 2>&1; if [[ $? -eq 0 ]]; 
            then WEBINTOK="true"
            else WEBINTOK="false"
            fi

        IMMSSH=`(timeout 5 tsocks sshpass -p "${PWD}" ssh -l "${USER}" -o StrictHostKeyChecking=no "${IP}" exit)`
        if echo "${IMMSSH}" | grep -q "tty name check failed"; then 
            ${WEBINTOK} && echo -e "${SERVER} ${USER} - OK" || echo -e "${SERVER} ${USER} - ERROR"
        else 
            ${WEBINTOK} && echo -e "${SERVER} ${USER} - ERROR" || echo -e "${SERVER} ${USER} - ERROR"
        fi
fi

done
$ 
$ bash testscript.sh 
serverA USERID - OK
$ 

Our quesiton: why does the script only reads the first line?? It suppose to read all the lines in the testservers.txt ..

UPDATE: the testservers.txt has correct TAB's, I don't really think that is the problem :\

$ cat -vte testservers.txt
serverA^IIMM^I10.2.3.4^IUSERID^IPASSW0RD$
serverB^IIMM^I10.2.3.5^IUSERID^IPASSW0RD$
$ 
evachristine
  • 2,613

2 Answers2

4

You've got:

egrep... | while read ...; do
    ...
    ... ssh $IP exit...
    ...
  done

ssh connects to the remote host and runs the remote command and sends it what it reads from its stdin (unless passed the -n option)

In that case, ssh's stdin is the pipe from egrep, the same pipe read is reading from.

So, it will typically read all the output of egrep and send it to the exit command on $IP (the remote shell or exit doesn't read it, but ssh will have read it).

nc is another command that reads its stdin to send over the connection it establishes, but not when passed the -z option as you do here.

To avoid the problem, use the -n option to ssh or redirect ssh's stdin from /dev/null (ssh < /dev/null...).

2

Stéphane has the right answer. I'm commenting about style mostly.

To reduce the work you have to do reading variables, instead of

while read ONELINE; do
    # variables..
    SERVER=`echo "$ONELINE" | awk 'BEGIN {FS="\t"} {print $1}'`
    RSATYPE=`echo "$ONELINE" | awk 'BEGIN {FS="\t"} {print $2}'`
    IP=`echo "$ONELINE" | awk 'BEGIN {FS="\t"} {print $3}'`
    USER=`echo "$ONELINE" | awk 'BEGIN {FS="\t"} {print $4}'`
    PWD=`echo "$ONELINE" | awk 'BEGIN {FS="\t"} {print $5}'`
    # ...

do this

while IFS=$'\t' read SERVER RSATYPE IP USER PWD; do
    # ...

Instead of writing

some command 
if [[ $? -eq 0 ]]; then
    do_this
else
    do_that
fi

write

if some command; then
    do_this
else
    do_that
fi

Since this is specifcally a bash script, instead of

echo "${IMMSSH}" | grep -q "tty name check failed"

do

grep -q "tty name check failed" <<<"${IMMSSH}"

Also, get out of the habit of using ALL_CAPS_VARNAMES: one day you'll use PATH and then wonder why your script is broken when you can't find any external commands.

glenn jackman
  • 85,964