而循环在Bash的第一行之后停止读取
我有下面的shell脚本。其目的是循环遍历目标文件的每一行(其路径是脚本的输入参数),并针对每一行执行操作。现在,它似乎只适用于目标文件中的第一行,并在该行被处理后停止。我的剧本有什么问题吗而循环在Bash的第一行之后停止读取,bash,shell,ssh,while-loop,Bash,Shell,Ssh,While Loop,我有下面的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++ e
#!/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"
#/bin/bash
#脚本:do.sh
#目的:循环通过目标
文件名=$1
计数=0
echo“继续使用$FILENAME”
读行时;做
算了吧++
回显“$count$LINE”
sh./do_work.sh$行
完成<$FILENAME
echo“\n总计$count个目标”
在
do_-work.sh
中,我运行了两个ssh
命令。问题是do_-work.sh
运行ssh
命令,默认情况下ssh
从输入文件stdin读取。因此,您只能看到处理的第一行,因为ssh
占用了文件的其余部分,而while循环终止
要防止这种情况,请将
-n
选项传递给您的ssh
命令,使其从/dev/null
而不是stdin读取。问题是do\u work.sh
运行ssh
命令,并且默认情况下ssh
从作为输入文件的stdin读取。因此,您只能看到处理的第一行,因为ssh
占用了文件的其余部分,而while循环终止
要防止出现这种情况,请将
-n
选项传递给您的ssh
命令,使其从/dev/null
而不是stdin读取。ssh-n选项防止在将输出传输到另一个程序时使用herdoc检查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
#/bin/bash
读一行的时候;做
sshubuntu@host_xyzssh-n选项防止在将输出传输到另一个程序时使用herdoc检查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
#/bin/bash
读一行的时候;做
sshubuntu@host_xyz这发生在我身上是因为我有set-e
,循环中的grep
返回时没有输出(这会产生非零错误代码)。这发生在我身上是因为我有set-e
,循环中的grep
返回时没有输出(这会产生非零错误代码)
while read -r LINE; do
let count++
echo "$count $LINE"
sh ./do_work.sh "$LINE" </dev/null
done < "$FILENAME"
要从here文档中读取命令,该文档方便地(对于此特定场景)绑定命令的标准输入ssh
:
ssh otherhost <<'____HERE'
some commands here
____HERE
ssh otherhost更一般地说,不是特定于ssh
的一种解决方法是重定向任何命令的标准输入,否则这些命令可能会在循环时使用
while read -r LINE; do
let count++
echo "$count $LINE"
sh ./do_work.sh "$LINE" </dev/null
done < "$FILENAME"
要从here文档中读取命令,该文档方便地(对于此特定场景)绑定命令的标准输入ssh
:
ssh otherhost <<'____HERE'
some commands here
____HERE
ssh otherhost一个非常简单而健壮的解决方法是更改read
命令接收输入的文件描述符
这是通过两个修改完成的:-u
参数到read
,以及<$FILENAME
的重定向操作符
在BASH中,默认的文件描述符值(即读取中-u
的值)是:
- 0=stdin
- 1=标准输出
- 2=标准差
所以只需选择一些其他未使用的文件描述符,比如9
,只是为了好玩
因此,以下是解决方法:
while read -u 9 LINE; do
let count++
echo "$count $LINE"
sh ./do_work.sh $LINE
done 9< $FILENAME
读取时-u9行;做
算了吧++
回显“$count$LINE”
sh./do_work.sh$行
完成9<$FILENAME
请注意两个修改:
read
变为read-u9
<$FILENAME
变为9<$FILENAME
作为一种最佳实践,我在BASH中编写的
循环中对所有的都这样做。
如果有使用read
的嵌套循环,请为每个循环(9,8,7,…)使用不同的文件描述符。一个非常简单而可靠的解决方法是更改read
命令接收输入的文件描述符
这是通过两个修改完成的:-u
参数到read
,以及<$FILENAME
的重定向操作符
在BASH中,默认的文件描述符值(即读取中-u
的值)是:
- 0=stdin
- 1=标准输出
- 2=标准差
所以只需选择一些其他未使用的文件描述符,比如9
,只是为了好玩
因此,以下是解决方法:
while read -u 9 LINE; do
let count++
echo "$count $LINE"
sh ./do_work.sh $LINE
done 9< $FILENAME
读取时-u9行;做
算了吧++
回显“$count$LINE”
sh./do_work.sh$行
完成9<$FILENAME
请注意两个修改:
read
变为read-u9
<$FILENAME
变为9<$FILENAME
作为一种最佳实践,我在BASH中编写的
循环中对所有的都这样做。
如果您有使用read
的嵌套循环,请为每个循环使用不同的文件描述符(9,8,7,…)。您的脚本很好,但do_work可能有问题。shYes,它可能会耗尽所有输入,或者可以作为源调用,只需退出或exec
。但是这段代码看起来不是真的,OP会注意到echo需要-e
来正确显示换行符…是否do_工作。sh
运行ssh
?是的,do_工作。sh运行两个ssh命令。有什么特别的吗?最好显示do_work.sh
源代码,并使用set-x
运行do.sh
进行调试。您的脚本很好,但do_work可能有问题。是的