cat 명령을 사용하여 파이프 파손을 방지하는 방법은 무엇입니까?

cat 명령을 사용하여 파이프 파손을 방지하는 방법은 무엇입니까?

Emacs 쉘(eshell)을 사용할 때 이 간단한 명령이 실패하는 이유는 무엇입니까?

cat file.txt | wc 

10241줄을 포함하는 파일이 있습니다. 한 줄에 50자 미만입니다. 이 명령을 실행하면 약 90%의 시간 동안 행 개수와 같은 잘못된 결과가 나타납니다. 그래도 오류 메시지는 표시되지 않습니다.

파이프 파열이 흔한 주제인 것 같은데 합리적인 설명을 찾지 못했습니다. 게다가 누구도 해결 방법을 제시하지 못했습니다. 이 간단한 명령을 어떻게 안정적으로 작동시킬 수 있습니까?

물론 그냥 도망칠 수도 있다 wc file.txt. 그러나 저는 모든 도구가 Piped cat: 에서 잘 작동하는 보다 일반적인 솔루션을 찾고 있습니다 cat file.txt | any_tool_here.

세부 사항

CentOS 5를 사용하고 있습니다. 이 문제는 다음을 사용할 때 발생합니다.eshell (이맥스 쉘). 저는 GNU Emacs 24.5.2를 사용하고 있습니다.

실험

결과 예 cat file.txt | wc(예상: 첫 번째 열은 항상 10241임)

  1. 8568 25706 110571
  2. 9837 29513 126947
  3. 5395 16187 69615
  4. 9202 27608 118757
  5. 7299 21899 94199
  6. 9837 29513 126947

다음을 사용한 결과 예 wc file.txt:

  1. 10241 30723 132156
  2. 10241 30723 132156
  3. 10241 30723 132156
  4. 10241 30723 132156
  5. 10241 30723 132156
  6. 10241 30723 132156

cat 명령 자체는(혼자 실행될 때) 잘 작동합니다. 다음 명령을 사용하여 여러 번 확인했습니다 cat file.txt > file2.txt. 그런 다음 두 파일을 비교했는데 동일합니다.

답변1

사용된 쉘( )에 대한 정보로 볼 때 eshell, 해당 쉘의 스트림 처리 측면이 원인인 것으로 보입니다. 일반적으로 파이프는 파이프 + 포크/exec의 양쪽 끝을 여는 것을 의미하므로 파이프 파일 설명자를 공유하는 두 프로세스를 얻게 되며 통신은 커널을 통해 직접 진행됩니다. 이렇게 하면 아무것도 손실되지 않습니다. 안전이 보장됩니다(비록 관련 파이프나 스트림이 버퍼링된 경우 스트림의 마지막 청크를 플러시하기 전에 첫 번째 프로세스가 정상적으로 종료될 때까지 기다려야 할 수도 있습니다).

발췌로 판단하면전자 인클로저 브로셔:

Eshell은 bash 또는 zsh와 같은 시스템 쉘을 대체할 수 없습니다. Emacs와 외부 프로세스 간에 텍스트를 이동하려면 Eshell을 사용하십시오. 하나의 외부 프로세스에서 다른 프로세스로(그리고 다른 프로세스로) 출력을 파이프하려는 경우에는 시스템 쉘을 사용하십시오. 왜냐하면 Emacs의 IO 시스템은 버퍼-이기 때문입니다. 스트림 지향이 아닌 지향적이며 이러한 작업에서는 매우 비효율적입니다. Eshell에서 쉘 스크립트를 작성하려면 그렇게 하지 마십시오. elisp 라이브러리를 작성하거나 시스템 쉘을 사용하십시오.

일반적인 방법으로 이 작업을 수행하는 대신 eshell은 "버퍼"(열린 파일에 대한 emacs의 표현)를 데이터의 중간 저장소로 사용하여 파이프를 가짜로 만듭니다 wc. read, 버퍼를 채우기 위해 첫 번째 프로그램에서 추가 입력을 기다리는 대신 emacs빈 블록으로 응답( read스트림의 끝을 나타 내기 위해 0 반환)으로 끝납니다. 그렇다면 eshell은 비효율적일 뿐만 아니라 파이프를 다룰 때에도 결함이 있다는 뜻이다.

관련 정보