bcb*_*hop 86 ssh bash shell 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++
echo "$count $LINE"
sh ./do_work.sh $LINE
done < $FILENAME
echo "\ntotal $count targets"
Run Code Online (Sandbox Code Playgroud)
在do_work.sh,我运行了几个ssh命令.
dog*_*ane 154
问题是do_work.sh运行ssh命令并默认ssh从stdin读取,这是您的输入文件.因此,您只看到处理的第一行,因为ssh使用了文件的其余部分并且while循环终止.
要防止这种情况,请将-n选项传递给您的ssh命令,使其从/dev/nullstdin而不是stdin 读取.
tri*_*eee 21
更一般地说,一种非特定的解决方法是ssh重定向任何可能消耗while循环输入的命令的标准输入。
while read -r LINE; do
let count++
echo "$count $LINE"
sh ./do_work.sh "$LINE" </dev/null
done < "$FILENAME"
Run Code Online (Sandbox Code Playgroud)
的添加</dev/null是这里的关键点(尽管更正的引用也有些重要;另请参阅何时将引号括在 shell 变量周围?)。您将要使用的read -r,除非你特别要求传统有点奇怪的行为,你没有-r。
另一种有点特定的解决方法ssh是确保任何ssh命令都绑定了其标准输入,例如通过更改
ssh otherhost some commands here
Run Code Online (Sandbox Code Playgroud)
改为从 here 文档中读取命令,该文档方便地(对于此特定场景)绑定了ssh命令的标准输入:
ssh otherhost <<'____HERE'
some commands here
____HERE
Run Code Online (Sandbox Code Playgroud)
cmo*_*cmo 10
一个非常简单的和鲁棒的解决方法是改变文件描述符从该read命令接收输入。
这是通过两个修改来实现的:-u参数 toread和重定向运算符 for < $FILENAME。
在 BASH 中,默认的文件描述符值(即-uin 的值read)是:
所以只需选择一些其他未使用的文件描述符,就像9只是为了好玩。
因此,以下将是解决方法:
while read -u 9 LINE; do
let count++
echo "$count $LINE"
sh ./do_work.sh $LINE
done 9< $FILENAME
Run Code Online (Sandbox Code Playgroud)
注意两个修改:
read 变成 read -u 9< $FILENAME 变成 9< $FILENAME作为最佳实践,我对while我用 BASH 编写的所有循环都这样做。如果您使用 嵌套循环read,请为每个循环使用不同的文件描述符(9,8,7,...)。
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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
49347 次 |
| 最近记录: |