프로세스 대체가 포함 된 출력 순서


11

이것이 내가 일반적으로 실행하는 일이다 grep하고 wc두 번 스캔 할 필요없이 파일

<file.txt  tee >(grep LITERAL) >(wc -l) >/dev/null

그러나 이것은

EXEC LITERAL
32

때때로 그리고

32
EXEC LITERAL

다른 시간에. (의 출력 은 첫 번째 인스턴스 grep의 출력보다 우선하고 wc두 번째 의 출력은 그 반대입니다.)

반면에 리디렉션 및 파일 설명자와 함께

{ { <file.txt tee /dev/fd/3 | grep LITERAL >&4; } 3>&1 | wc -l ;} 4>&1 

나는 항상 얻는 것 같다

EXEC LITERAL
32

출력 순서를 예측할 수 있지만 두 번째 접근 방식으로 보장됩니까?

답변:


4

둘다

<file.txt  tee >(grep LITERAL) >(wc -l) >/dev/null

과:

{ { <file.txt tee /dev/fd/3 | grep LITERAL >&4; } 3>&1 | wc -l ;} 4>&1

모든 tee, grep그리고 wc동시에 시작됩니다. 중요한 것은 마지막에 일어나는 일입니다.

wc표준 입력에서 파일 끝을 볼 때만 결과를 인쇄합니다. 첫 번째 경우, tee출구 가 될 때입니다. 그러면 읽고 있는 파이프의 다른 쪽 끝을 tee닫습니다 (프로세스 대체로 시작). 보장이 없어 그때까지의 모든 입력을 읽은 것입니다 혼자 (파이프 데이터의 꽤 많은 양을 저장할 수와 그 주어진 출력을 작성 내버려 것보다 더 빨리 될 것입니다 )fdwcgrepwcgrep

두 번째 경우, wc파이프에서 읽고있는 모든 작성자가 파이프의 끝을 닫으면 파일 끝이 표시됩니다. 이 경우 여러 작가가 있습니다. tee(에 미치는 FD 개방을 통해 /dev/fd/3그리고 그 전략 중 3를 통해) grep또한이 fd에 파이프 개방 3 wc(그것의 사용을 아니지만, 그것에 혼자 쓰기를하자). 내부는 {가능성도있을 것이다 별도의 서브 쉘 프로세스가 발생합니다 fd3 개방을하고 모두 대기 teegrep.

즉, 종료 wc후에 만 줄 번호를 씁니다 grep.

올바른 방법으로 작성 했습니까? 즉, 열 필요가없는 fd를 닫는 것입니다.

{ { <file.txt tee /dev/fd/3 4>&- | 
   grep LITERAL >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1

그러면 서브 쉘 프로세스를 최적화하는 쉘에서 순서가 보장되지 않았을 것입니다. 그러나, 단지 내가 즉 않습니다 알고 쉘 ksh93하지만 ksh93용도는 그래서 파이프 쌍 소켓 /dev/fd/3적어도 리눅스가 작동하지 않습니다.

실행중인 프로세스를 확인하려면 다음 grepps같이 바꾸십시오 .

$ { { <file.txt tee /dev/fd/3 4>&- | ps -H >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1
  PID TTY          TIME CMD
 8727 pts/5    00:00:00 bash
 8815 pts/5    00:00:00   bash
 8817 pts/5    00:00:00     tee
 8818 pts/5    00:00:00     ps
 8816 pts/5    00:00:00   wc

을 사용하면 bash추가 쉘 프로세스를 볼 수 있으며 fd 3에서 파이프가 다음과 같이 열려 있음을 알 수 있습니다.

$ (p=$BASHPID; { { <file.txt tee /dev/fd/3 4>&- | lsof -ag "$p" -d3 >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1)
COMMAND  PID PGID     USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
bash    9843 9842 chazelas    3w  FIFO    0,8      0t0 153304 pipe
tee     9845 9842 chazelas    3w  FIFO    0,8      0t0 153304 pipe
lsof    9846 9842 chazelas    3r   DIR    0,3        0      1 /proc

감사. "적절한 예" grep LITERAL >&4 3>&- 4>&-에서 fd 4가 사용되고 닫혀있는 것처럼 보이는 것은 무엇입니까?
iruvar

1_CR @ 후 >&4, 짧은 1>&4, grep의 동일한 자원 (쉘의 초기 표준 출력)에 1 ~ 4 포인트가 fd. grepfd 4를 열 필요가 없습니다. 그것으로 아무것도하지 않습니다, 그래서 우리는 그것을 닫습니다4>&-
Stéphane Chazelas

마지막 명령 줄은 비밀 마법입니다.

-1

예측 가능한 주문 사용을 얻으려면

(<file.txt  tee >(grep LITERAL) >(wc -l) >/dev/null)|sort

아마도 나는 충분히 명확하지 않았다. 나는 명령 출력 (즉, wc에서 출력하기 전에 grep에서 출력)의 순서로 예측 가능한 순서를 의미했습니다. 나는 결합 된 출력 정렬이 필요하지 않습니다
iruvar

gnu.org/software/bash/manual/bashref.html#Command-Grouping을 찾았 습니다 . {} 연산자를 사용하면 {} 연산자로 <file.txt tee / dev / fd / 3 | grep LITERAL> & 4; 이 작업이 완료되면 wc에 전화를 걸어 원래의 질문에 대답하십시오. 예, 이해합니다
Thorsten Staerk

1
@ThorstenStaerk 답변에 추가 정보를 추가 할 수 있습니까?
terdon

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.