Неожиданное поведение сценария оболочки

У меня есть два сценария:

foo.sh:

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

bar.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 Вывод этого будет таким же, как вывод foo.sh :

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

Зачем?

В bar.sh two используются ssh . В последнем примере полный вывод из echo используется for того, чтобы он начинал цикл.

Чтобы избежать слияния ваших данных со стандартного ввода, используйте ssh -n . Это приведет к подключению стандартного ввода ssh с /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 .