如何防止脚本吞噬所有标准输入?

如何防止脚本吞噬所有标准输入?

我有一个脚本,它循环读取管道,并在循环中运行一个 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`

相关内容