我有一个脚本,它循环读取管道,并在循环中运行一个 expect 脚本和一个普通的 shell 脚本。这两个脚本都运行 ssh 到另一台服务器来获取一段数据。例如:
cat /tmp/file |
while read a b c d
do
s=`expect-script server1 $b`
c=`ssh $b normal-script`
echo $s $c
done
尽管 /tmp/file 中有很多行,但脚本在处理完第一行后就退出了。我怀疑 expect 脚本吞掉了所有的 stdin,所以当它返回时,就没有什么可读取的了。我该如何避免这种情况?我不希望我调用的任何脚本从主脚本的 stdin 读取。
答案1
它实际上ssh
正在吸收 stdin。只需添加选项-n
:
c=$( ssh -n $b normal-script )
如果你不想这样做,你可以让你的 shellwhile
循环从不同的文件描述符读取,而不改变 stdin:
while read -u3 a b c d
do
s=$( expect-script server1 $b )
c=$( ssh $b normal-script )
echo $s $c
done 3< /tmp/file
(假设选项为 bash/ksh/zsh read -u
)
答案2
cat /tmp/file |
while read a b c d
do
{
s=`expect-script server1 $b`
c=`ssh $b normal-script`
echo $s $c
} < /dev/null
done
该{ command... }
语法允许您将重定向或管道应用于一系列命令。
cat
我还要指出的是,在您的示例中您不需要这样做。您可以这样做:
while read a b c d
do
...
done < /tmp/file
答案3
另外,一般来说,如果你不想使用某些命令当前的STDIN,您可以使用 为其提供不同的标准<
。
例如
s=`expect-script server1 $b < /dev/null`
会让“expect-script”从中读取它的STDIN /dev/null
(恰好返回EOF
),而不是使用当前的STDIN(来自/tmp/file
)
您还可以|
为该命令提供一些单独的 STDIN,例如
s=`cat /tmp/stdin_for_expect | expect-script server1 $b`
c=`cat /tmp/stdin_for_ssh | ssh $b normal-script`