파이프 명령은 어떤 순서로 실행됩니까?


89

쉘이 실제로 파이프 명령을 실행하는 방법에 대해 생각한 적이 없습니다. 나는 파이프 에 대해 생각하는 방식으로 " 한 프로그램의 stdout이 다른 프로그램 의 stdin에 파이프 된다 "고 항상 들었습니다 . 그래서 당연히 나는 A | B, A가 먼저 실행 된 다음 B는 A의 표준 출력을 가져오고 A의 표준 출력을 입력으로 사용합니다.

그러나 사람들이 ps에서 특정 프로세스를 검색 할 때 명령 끝에 grep -v "grep"을 포함하여 grep이 최종 출력에 나타나지 않도록합니다. 이것은 명령 ps aux | grep "bash"| grep -v "grep"은 ps가 grep이 실행 중임을 알고 ps의 출력에 있음을 의미합니다. 그러나 출력이 grep으로 파이프되기 전에 ps가 실행을 마치면 grep이 실행되고 있음을 어떻게 알 수 있습니까?

flamingtoast@FTOAST-UBUNTU: ~$ ps | grep ".*"
PID TTY          TIME CMD
3773 pts/0    00:00:00 bash
3784 pts/0    00:00:00 ps
3785 pts/0    00:00:00 grep

왜 대답을 받아들이지 않습니까?
törzsmókus

답변:


64

파이프 된 명령은 동시에 실행됩니다. 당신이 실행하면 ps | grep …, 그것은 추첨의 행운 (또는 커널의 창자에 깊은 스케줄러 미세 조정과 함께 쉘의 동작의 세부 사항의 문제) 여부에의 ps하거나 grep먼저 시작하고, 어떤 경우에 그들은 계속 동시에 실행하십시오.

이것은 일반적으로 첫 번째 프로그램이 작업을 완료하기 전에 두 번째 프로그램이 첫 번째 프로그램에서 나오는 데이터를 처리 할 수 ​​있도록하는 데 사용됩니다. 예를 들어

grep pattern very-large-file | tr a-z A-Z

grep큰 파일 탐색을 마치기 전에도 일치하는 줄을 대문자로 표시하기 시작 합니다.

grep pattern very-large-file | head -n 1

첫 번째 일치하는 줄을 표시 grep하고 입력 파일 읽기를 마치기 전에 처리를 중지 할 수 있습니다.

파이프 된 프로그램이 순서대로 실행되는 곳을 읽으면이 문서를 피하십시오. 파이프 된 프로그램은 동시에 실행되며 항상 있습니다.


7
그리고이 예제에서 멋진 점은 head가 필요한 한 줄을 얻었을 때 종료되고 grep 이이를 알면 아무 일도하지 않고 추가 작업을하지 않고도 종료된다는 것입니다.
Joe

파이프와 관련하여 일종의 IO 버퍼가 있다고 생각합니다 ... 바이트 크기를 어떻게 알 수 있습니까? 그것에 대해 더 배우기 위해 무엇을 읽고 싶습니까? :)
n611x007

3
@naxa 실제로 두 개의 버퍼가 있습니다. 있다 STDIO의 내부 버퍼 grep프로그램은 파이프 자체 커널이 관리하는 버퍼가있다. 후자의 경우 파이프 버퍼가 얼마나 큽니까?
Gilles

49

명령이 실제로 실행되는 순서는 중요하지 않으며 보장되지 않습니다. 비전의 내용을 차치하더라도 pipe(), fork(), dup()execve(), 쉘은 제 파이프, 프로세스 사이에 유입 될 데이터의 도관을 만든 다음 그 연결 파이프의 단부의 처리를 생성한다. 실행되는 제 1 프로세스는 제 2 프로세스로부터의 입력 대기를 차단하거나, 제 2 프로세스가 파이프로부터 데이터 판독을 시작하기를 대기하는 것을 차단할 수있다. 이러한 대기는 임의로 길 수 있으며 중요하지 않습니다. 프로세스가 실행되는 순서에 관계없이 결국 데이터가 전송되고 모든 것이 작동합니다.


5
좋은 대답이지만 OP는 프로세스가 순차적으로 실행되는 것으로 생각합니다. 여기에서 프로세스가 동시에 실행되고 파이프가 버킷 사이의 파이프와 유사하다는 것을 분명히 할 수 있습니다. 버킷은 물이 (대략) 동시에 흐르는 곳입니다.
Keith

명확하게 해 주셔서 감사합니다. 내가 읽은 소스는 파이프 된 프로그램이 동시에 실행되는 것이 아니라 순차적으로 실행되는 것처럼 보입니다.
action_potato

결정되지 않은 방식으로 시작하는 프로세스를 경험하려면이 1000 번 실행하십시오. echo -na> & 2 | echo b> & 2
Ole Tange

28

죽은 말을 때릴 위험이있는 오해는

    A | 

에 해당

    A > 임시 파일 
    B < 임시 파일 
    rm rm 임시 파일

그러나 유닉스가 만들어졌고 아이들이 공룡을 학교에 갔을 때 디스크는 매우 작았으며 파일 시스템의 모든 여유 공간을 사용하는 다소 양성 명령이 일반적이었습니다. 경우 B뭔가 것처럼 , 파이프 라인의 최종 출력은 수 많은 그 중간 파일보다 작은. 따라서 파이프는 " A를 먼저 실행 다음 A 의 출력 에서 입력으로 B 를 실행 "의 약어가 아니라 중간 파일을 동시에 저장하고 저장하지 않아도 되는 방법으로 개발 되었습니다. 디스크에.grep some_very_obscure_stringBA


2
이것은 왜 그리고 그에 따라 투표권을 얻습니다.
작은 고대의 숲 Kami

1

일반적으로 이것을 bash에서 실행하십시오. 프로세스가 동시에 작동하고 시작하지만 셸에서 동시에 실행 중입니다. 그게 어떻게 가능해?

  1. 파이프에서 마지막 명령이 아닌 경우 소켓 쌍으로 명명되지 않은 파이프를 만듭니다.
  2. 포크
  3. 자식에서 stdin / stdout이 필요한 경우 소켓에 다시 할당
  4. 자식 EXEC에서 원래 쉘 코드를 스윕하는 인수가있는 명령을 지정했지만 소켓에서 모두 열어 둡니다. 하위 프로세스 ID는 동일한 하위 프로세스이므로 변경되지 않습니다.
  5. 하위 쉘과 동시에 하위 쉘과 동시에 1 단계로 이동하십시오.

시스템은 exec가 얼마나 빨리 실행되고 지정된 명령이 시작되는지 보장하지 않습니다. 쉘과는 독립적이지만 시스템입니다. 이 때문입니다:

ps auxww| grep ps | cat

한 번 보여주기 grep및 / 또는 ps명령하고 다음으로. 시스템 실행 기능을 사용하여 커널이 실제로 프로세스를 얼마나 빨리 시작하는지에 달려 있습니다.


1
동시 실행은 두 개 이상의 프로세스가 동일한 시간 프레임 내에서 실행되며 일반적으로 프로세스간에 일종의 종속성이 있음을 의미합니다. 병렬 실행은 둘 이상의 프로세스가 동시에 실행되는 것을 의미합니다 (예 : 별도의 CPU 코어에서 동시에). 병렬 처리는이 질문과 관련이 없으며 "빠른 속도" exec()가 실행되는 것이 아니라 exec()파이프에서 프로그램 의 호출 및 실행이 인터리브되는 방식 입니다.
토마스 Nyman
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.