shell 脚本的意外行为

shell 脚本的意外行为

我有两个脚本:

foo.sh:

#!/bin/bash
echo -e "one\ntwo" |
while read line; do
    cat not-existing
    echo hello $line
done

酒吧.sh:

#!/bin/bash
echo -e "one\ntwo" |
while read line; do
    ssh user@machine 'cat not-existing' # Here is the only difference
    echo hello $line
done

现在我运行它们

$ ./foo.sh 
cat: not-existing: No such file or directory
hello one
cat: not-existing: No such file or directory
hello two

$ ./bar.sh 
cat: not-existing: No such file or directory
hello one

的输出bar.sh令我惊讶。我希望这两个脚本是相同的。

foo.sh为什么和的输出bar.sh不同?这是一个错误还是一个功能?


笔记

以下内容按我的预期工作,即其输出与 的输出相同foo.sh

#!/bin/bash
for line in `echo -e "one\ntwo"`; do
    ssh user@machine 'cat not-existing'
    echo hello $line
done

为什么?

答案1

在 中bar.shtwo被 消耗ssh。在最后一个示例中,在开始循环之前echo使用了from 的完整输出。for

为了避免ssh从标准输入中吞噬数据,请使用ssh -n.这将连接sshwith的标准输入/dev/null,而不是while循环的标准输入。

这将执行您期望的操作:

#!/bin/bash
echo -e "one\ntwo" |
while read line; do
    ssh -n user@machine 'cat not-existing' # Here is the only difference
    echo hello $line
done

如果你写过

#!/bin/bash
echo -e "one\ntwo" |
while read line; do
    ssh user@machine 'cat'
    echo hello $line
done

那么cat远程机器上的 就会输出,two因为它的标准输入被传递给它,ssh而 又从循环中得到它echo。它将打印two而不是one因为第一行输入已被 消耗read

相关内容