Por que o ciclo while pula e só lê a primeira linha?

2
$ 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
$ 

Nossa quesiton : por que o script só lê a primeira linha ?? Suponha que leia todas as linhas no servidor de testes.txt.

UPDATE: o servidor de testes.txt tem as tabs corretas, eu realmente não acho que é o problema: \

$ cat -vte testservers.txt
serverA^IIMM^I10.2.3.4^IUSERID^IPASSW0RD$
serverB^IIMM^I10.2.3.5^IUSERID^IPASSW0RD$
$ 
    
por evachristine 13.08.2014 / 19:08

2 respostas

4

Você tem:

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

ssh conecta-se ao host remoto e executa o comando remoto e envia o que lê de seu stdin (a menos que tenha passado a opção -n )

Nesse caso, o stdin de ssh é o canal de egrep , o mesmo canal read está lendo.

Portanto, ele normalmente lerá toda a saída de egrep e a enviará para o comando exit em $IP (o shell remoto ou exit não o lê, mas ssh terá lido isso.

nc é outro comando que lê seu stdin para enviar a conexão que ele estabelece, mas não quando passou a opção -z como você faz aqui.

Para evitar o problema, use a opção -n para ssh ou redirecione o status de ssh de /dev/null ( ssh < /dev/null... ).

    
por 13.08.2014 / 22:53
2

Stéphane tem a resposta certa. Estou comentando sobre o estilo principalmente.

Para reduzir o trabalho que você tem que fazer lendo variáveis, em vez de

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}''
    # ...

faça isso

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

Em vez de escrever

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

escreva

if some command; then
    do_this
else
    do_that
fi

Como isso é especificamente um script bash, em vez de

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

faça

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

Além disso, tire o hábito de usar ALL_CAPS_VARNAMES: um dia você usará PATH e, em seguida, perguntará por que seu script está corrompido quando você não encontrar nenhum comando externo.

    
por 13.08.2014 / 23:02