$ 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
相同的管道。read
因此,它通常会读取 的所有输出egrep
并将其发送到exit
上的命令$IP
(远程 shell 或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}"
另外,改掉使用 ALL_CAPS_VARNAMES 的习惯:有一天,PATH
当您找不到任何外部命令时,您会使用它,然后想知道为什么您的脚本被破坏了。