쉘 스크립트의 예기치 않은 동작

쉘 스크립트의 예기치 않은 동작

두 개의 스크립트가 있습니다.

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.sh소비 two됩니다 ssh. 마지막 예에서는 echo루프를 시작하기 전에 from의 전체 출력이 사용됩니다.for

sshstdin에서 데이터를 먹는 것을 방지하려면 를 사용하십시오. 이렇게 하면 루프의 stdin이 아닌 with 의 stdin이 ssh -n연결됩니다 .ssh/dev/nullwhile

이렇게 하면 예상한 대로 작동합니다.

#!/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출력됩니다 . 입력의 첫 번째 줄이 소비되었기 때문에 대신 인쇄됩니다 .twosshechotwooneread

관련 정보