while 루프가 건너뛰고 첫 번째 줄만 읽는 이유는 무엇입니까?

while 루프가 건너뛰고 첫 번째 줄만 읽는 이유는 무엇입니까?
$ 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
$ 

우리의 문제:스크립트가 첫 번째 줄만 읽는 이유는 무엇입니까? testservers.txt의 모든 행을 읽었다고 가정합니다.

업데이트: testservers.txt에 올바른 탭이 있습니다. 실제로는 그것이 문제라고 생각하지 않습니다. \

$ cat -vte testservers.txt
serverA^IIMM^I10.2.3.4^IUSERID^IPASSW0RD$
serverB^IIMM^I10.2.3.5^IUSERID^IPASSW0RD$
$ 

답변1

당신은:

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

ssh원격 호스트에 연결하고 원격 명령을 실행한 후 표준 입력에서 읽은 내용을 보냅니다(해당 -n옵션이 전달되지 않는 한).

이 경우 sshstdin은 이를 읽는 파이프이며, egrepstdin을 읽는 파이프와 동일합니다.read

따라서 일반적으로 모든 출력을 읽고 이를 명령 egrep으로 보냅니다 (원격 쉘은 이를 읽지 않지만 읽습니다).exit$IPexitssh

nc표준 입력을 읽어 설정된 연결을 통해 전송하지만 -z여기와 같은 옵션을 전달하지 않는 또 다른 명령입니다.

이 문제를 방지하려면 -n옵션을 사용 ssh하거나 ( ) ssh에서 stdin을 리디렉션하세요 ./dev/nullssh < /dev/null...

답변2

스티븐은 정답을 가지고 있습니다. 내 주요 의견은 스타일입니다.

작업을 줄이려면 대신 변수를 읽어야 합니다.

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

이 작업을 수행

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

글을 쓰는 대신

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

쓰다

if some command; then
    do_this
else
    do_that
fi

이것은 bash 스크립트가 아니기 때문에

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

하다

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

PATH또한 ALL_CAPS_VARNAMES를 사용하는 습관을 버리세요. 언젠가는 외부 명령을 찾을 수 없을 때 사용 하고 스크립트가 왜 손상되었는지 궁금할 것입니다.

관련 정보