Shell脚本,而读取行循环在第一行之后停止


107

我有以下shell脚本。目的是循环遍历目标文件的每一行(其路径是脚本的输入参数),并针对每一行工作。现在,它似乎只适用于目标文件的第一行,并在该行得到处理后停止。我的脚本有什么问题吗?

#!/bin/bash
# SCRIPT: do.sh
# PURPOSE: loop thru the targets 

FILENAME=$1
count=0

echo "proceed with $FILENAME"

while read LINE; do
   let count++
   echo "$count $LINE"
   sh ./do_work.sh $LINE
done < $FILENAME

echo "\ntotal $count targets"

在中do_work.sh,我运行几个ssh命令。


1
您的脚本很好,但是do_work.sh可能有问题
sleepsort

2
是的,它可能会耗尽所有输入,或者可以将其调用为as source并直接退出或exec。但是这段代码看起来并不真实,OP会注意到echo需要-e正确显示换行符...
Michael Krelin-hacker 2012年

3
do_work.sh运行ssh任何机会?
dogbane 2012年

1
是的,do_work.sh运行几个ssh命令。有什么特别的吗?
bcbishop

1
更好地显示do_work.sh源代码并do.sh与之一起set -x进行调试。
koola 2012年

Answers:


178

问题是do_work.sh运行ssh命令,并且默认情况下ssh从输入文件stdin中读取。结果,您只看到处理的第一行,因为ssh消耗了文件的其余部分,并且while循环终止。

为防止这种情况,请将-n选项传递给ssh命令以使其从而/dev/null不是stdin 读取。


1
非常有用,它帮助我运行了zsh oneliner:同时阅读主持人; ssh $ host do_something; 完成
大鼠

3
@rat您仍然想避免没用cat您可能会想,特别是啮齿动物会对此保持警惕。
人间

while read host ; do $host do_something ; done < /etc/hosts会避免它。相当节省生命,谢谢!
大鼠

httpie这是另一个默认读取STDIN的命令,在bash或fish循环内调用时将遭受相同的行为。使用http --ignore-stdin或将标准输入设置/dev/null为如上所述。
拉曼

12

更一般而言,一种不特定于此的解决方法是ssh将标准输入重定向到任何可能会消耗while循环输入的命令。

while read -r LINE; do
   let count++
   echo "$count $LINE"
   sh ./do_work.sh "$LINE" </dev/null
done < "$FILENAME"

在这里添加</dev/null是关键点(尽管正确的引用也很重要;另请参见何时将引号括在shell变量周围?)。read -r除非特别需要没有的传统的稍微奇怪的行为,否则您将希望使用-r

某种特定的另一种解决方法ssh是确保任何ssh命令的标准输入都被绑定,例如通过更改

ssh otherhost some commands here

而是从here文档中读取命令,该文档很方便地(对于此特定方案)ssh将命令的标准输入绑定在一起:

ssh otherhost <<'____HERE'
    some commands here
____HERE

5

ssh -n选项可防止在将输出管道输送到另一个程序时使用HEREdoc时检查ssh的退出状态。因此,最好将/ dev / null用作stdin。

#!/bin/bash
while read ONELINE ; do
   ssh ubuntu@host_xyz </dev/null <<EOF 2>&1 | filter_pgm 
   echo "Hi, $ONELINE. You come here often?"
   process_response_pgm 
EOF
   if [ ${PIPESTATUS[0]} -ne 0 ] ; then
      echo "aborting loop"
      exit ${PIPESTATUS[0]}
   fi
done << input_list.txt

这没有道理。该<<EOF覆盖</dev/null重定向。之后的<<重定向done错误。
人间

1

这是发生在我身上,因为我有set -egrep在一个循环中,没有输出返回(这给出了一个非零的错误代码)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.