경우에 따라 출력을 리디렉션할 수 없는 이유는 무엇입니까?

경우에 따라 출력을 리디렉션할 수 없는 이유는 무엇입니까?

예를 들어

# this line should output ssh banner
nc localhost 22
# this line should output the same string expect the replacements
nc localhost 22|sed 's/SSH/XXX/g'

nc localhost 22 > foo # after killing the process, I can see the banner in file `foo`
nc localhost 22|sed 's/SSH/XXX/g' > foo # however I see nothing when sed is used

sed언급한 대로 파이프 nc출력을 사용하는 경우 sed출력을 파일로 리디렉션할 수 없습니다.

또한 결과를 전달하기 위해 다른 명령도 시도했습니다(예 grep: tr동일한 결과).

그러나 cat결과는 파일로 파이프될 수 있습니다. 이상한..

nc localhost 22|cat > foo

그렇다면 왜 이런 일이 발생합니까? cat이 경우와 다른 명령의 차이점은 무엇입니까? sed출력을 파일로 어떻게 리디렉션할 수 있나요 cat?

답변1

$ 고양이 | sed -e 's/foo/bar/' > 출력.txt
부자
^C
$catoutput.txt
[아무것도 없습니다]

하지만:

$ 고양이 | sed -e 's/foo/bar/' > 출력.txt
부자
^D
$catoutput.txt
술집

파일에 쓰기(터미널에는 아님)는 일반적으로 C 라이브러리(stdio 함수)에 의해 몇 킬로바이트 단위로 버퍼링됩니다. 파이프를 종료하기 위해 Ctrl-C를 누르면 sed파이프가 종료되기 전에 버퍼를 쓸 시간이 없으므로 결과 출력 파일은 비어 있게 됩니다. (이것은 종료 신호를 포착하지 못하는 C 라이브러리의 버그라고 말할 수 있지만 실제로는 그렇습니다.)

Plain은 cat아마도 라인과 같은 복잡한 것을 처리하지 않기 때문에 stdio를 사용하지 않을 것입니다. 그런 부분은 cat -n다를 수도 있고 아닐 수도 있습니다.

파이프를 종료하기 위해 Ctrl-C를 사용할 필요 없이 파이프 자체가 완료되도록 배열할 수 있습니다. 적어도 내에서는 nc-qN옵션을 사용하여 다음 후에 종료하도록 지시합니다.질소stdin이 닫힌 후의 시간(초)입니다. 예를 들면 다음과 같습니다.

$ printf '' | nc -q0 localhost 22 | sed 's/SSH/FOO/' > output.txt 
$ cat output.txt 
FOO-2.0-OpenSSH_7.4p1 Debian-10+deb9u7

또는 버퍼링을 끄는 방법이 최소한 몇 가지 있습니다. 파이프라인에서 버퍼링 끄기그리고 stdout 버퍼를 제거하려면 "unbuffer" 또는 "stdbuf"를 사용하시겠습니까?

GNU sed에는 -u/ --unbuffered스위치 도 있습니다

입력 파일에서 최소한의 데이터를 로드하고 출력 버퍼를 더 자주 플러시합니다.

관련 정보