$ 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
옵션이 전달되지 않는 한).
이 경우 ssh
stdin은 이를 읽는 파이프이며, egrep
stdin을 읽는 파이프와 동일합니다.read
따라서 일반적으로 모든 출력을 읽고 이를 명령 egrep
으로 보냅니다 (원격 쉘은 이를 읽지 않지만 읽습니다).exit
$IP
exit
ssh
nc
표준 입력을 읽어 설정된 연결을 통해 전송하지만 -z
여기와 같은 옵션을 전달하지 않는 또 다른 명령입니다.
이 문제를 방지하려면 -n
옵션을 사용 ssh
하거나 ( ) ssh
에서 stdin을 리디렉션하세요 ./dev/null
ssh < /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를 사용하는 습관을 버리세요. 언젠가는 외부 명령을 찾을 수 없을 때 사용 하고 스크립트가 왜 손상되었는지 궁금할 것입니다.