Comportamento inesperado de um script de shell [duplicado]

4

Eu tenho dois scripts:

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

E agora eu os corro

$ ./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

A saída de bar.sh é surpreendente para mim. Eu esperaria que fosse o mesmo para ambos os scripts.

Por que a saída de foo.sh e bar.sh é diferente? É um bug ou um recurso?

Nota

O seguinte funciona como esperado, ou seja, a saída disso é igual à saída de foo.sh :

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

Por quê?

    
por mejem 22.02.2017 / 15:14

1 resposta

11

Em bar.sh , o two é consumido por ssh . No último exemplo, a saída completa de echo é usada por for antes de iniciar o loop.

Para evitar que ssh devore seus dados da entrada padrão, use ssh -n . Isso conectará a entrada padrão de ssh com /dev/null em vez da entrada padrão do loop while .

Isso fará o que você espera:

#!/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

Se você tivesse escrito

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

então o cat na máquina remota teria gerado two desde que sua entrada padrão tenha sido transferida para ele de ssh , que por sua vez obteve o loop e echo . Ele imprimirá two em vez de one , pois a primeira linha de entrada já foi consumida por read .

    
por 22.02.2017 / 15:32