bash 读行循环在第一行之后停止时的 Shell 脚本
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13800225/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Shell script while read line loop stops after the first line
提问by bcbishop
I have the following shell script. The purpose is to loop thru each line of the target file (whose path is the input parameter to the script) and do work against each line. Now, it seems only work with the very first line in the target file and stops after that line got processed. Is there anything wrong with my script?
我有以下 shell 脚本。目的是遍历目标文件的每一行(其路径是脚本的输入参数)并对每一行进行处理。现在,它似乎只适用于目标文件中的第一行,并在该行得到处理后停止。我的脚本有问题吗?
#!/bin/bash
# SCRIPT: do.sh
# PURPOSE: loop thru the targets
FILENAME=
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"
In do_work.sh
, I run a couple of ssh
commands.
在 中do_work.sh
,我运行了几个ssh
命令。
回答by dogbane
The problem is that do_work.sh
runs ssh
commands and by default ssh
reads from stdin which is your input file. As a result, you only see the first line processed, because ssh
consumes the rest of the file and your while loop terminates.
问题是do_work.sh
运行ssh
命令并默认ssh
从作为输入文件的 stdin 读取。结果,您只能看到处理的第一行,因为ssh
消耗了文件的其余部分并且您的 while 循环终止。
To prevent this, pass the -n
option to your ssh
command to make it read from /dev/null
instead of stdin.
为防止出现这种情况,请将-n
选项传递给您的ssh
命令以使其读取/dev/null
而不是标准输入。
回答by tripleee
More generally, a workaround which isn't specific to ssh
is to redirect standard input for any command which might otherwise consume the while
loop's input.
更一般地说,一种非特定的解决方法是ssh
重定向任何可能消耗while
循环输入的命令的标准输入。
while read -r LINE; do
let count++
echo "$count $LINE"
sh ./do_work.sh "$LINE" </dev/null
done < "$FILENAME"
The addition of </dev/null
is the crucial point here (though the corrected quoting is also somewhat important; see also When to wrap quotes around a shell variable?). You will want to use read -r
unless you specifically require the legacy slightly odd behavior you get without -r
.
的添加</dev/null
是这里的关键点(尽管更正的引用也有些重要;另请参阅何时将引号括在 shell 变量周围?)。您将要使用的read -r
,除非你特别要求传统有点奇怪的行为,你没有-r
。
Another workaround of sorts which is somewhat specific to ssh
is to make sure any ssh
command has its standard input tied up, e.g. by changing
另一种有点特定的解决方法ssh
是确保任何ssh
命令都绑定了其标准输入,例如通过更改
ssh otherhost some commands here
to instead read the commands from a here document, which conveniently (for this particular scenario) ties up the standard input of ssh
for the commands:
改为从 here 文档中读取命令,该文档方便地(对于此特定场景)绑定了ssh
命令的标准输入:
ssh otherhost <<'____HERE'
some commands here
____HERE
回答by jacobm654321
ssh -n option prevents checking the exit status of ssh when using HEREdoc while piping output to another program. So use of /dev/null as stdin is preferred.
ssh -n 选项可防止在将输出通过管道传输到另一个程序时使用 HEREdoc 时检查 ssh 的退出状态。所以使用 /dev/null 作为标准输入是首选。
#!/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