파이프라인(Pipeline)
파이프라인은 리디렉션에서 한걸을 더 나아간 기능이다. 리디렉션이 프로세스 스트림과 파일 간의 상호작용이라면 파이프라인은 프로세스 스트림 간의 상호작용이다.
파이프라인의 개념과 사용법
어떤 작업을 하는데 여러 프로세스가 상호작용해야 하는 상황을 생각해 보자. 예를 들어, ls로 /etc 디렉터리의 파일 중 'corn'이라는 단어가 포함된 파일 목록을 조회해야 한다고 해보자. 리디렉션으로 이 작업을 수행하려면 어떻게 해야 할까?
일반적으로 임시 파일을 사용한다. ls 명령어로 /etc 디렉터리의 파일 목록을 조회해서 result 파일에 저장한다.
$ ls /etc > result
다음은 grep 명령어로 result 파일의 내용 중 'cron'이라는 단어가 포함된 파일 이름을 찾는다.
$ grep cron result
원하는 파일을 찾았으니 result 파일을 삭제한다. 이처럼 임시 파일을 이용하면 작업이 끝났을 때 이를 바로 지워야 한다. 귀찮기도 하고, 깜박 잊고 지우지 않을 확률이 높다.
$ rm result
임시 파일을 이용하는 대신, here strings를 이용하면 명령한 줄로 작업을 수행할 수 있다. ls /etc 명령의 실행 결과를 grep의 입력 스트림으로 리디렉션 한다.
$ grep cron <<< $(ls /etc)
here strings를 이용하는 방법이 임시 파일을 이용하는 방법보다 간편하기는 하다. 하지만 파이프라인보다는 복잡하다. 리디렉션은 스트림과 파일의 상호작용이라서 두 프로세스가 상호작용하려면 중간에 파일이 포함될 수밖에 없다. 파일을 거치지 않고 프로세스 간에 상호작용을 할 때 필요한 것이 바로 파이프라인이다. 파이프라인은 스트림과 스트림을 직접 연결해 준다.
세 프로세스 간 상호작용을 나타낸다. 먼저 프로세스1은 표준 입력(stdin)으로 키보드 입력을 받는다. 그리고 표준 에러(stderr)를 화면에 출력한다. 눈여겨볼 부분은 프로세스1의 표준 출력(stdout)이다. 프로세스1의 표준 출력(stdout)은 프로세스2의 표준 입력(stdin)과 연결되어 있다. 여기가 파이프라인으로 연결된 부분이다. 마찬가지로 프로세스2의 표준 출력(stdout) 이 프로세스3의 표준 입력 (stdin)과 연결되어 있다.
파이프라인의 사용형식은 다음과 같다.
$ command1 | command2 [| command3] ...
$ command1 |& command2 [|& command3] ...
파이프라인은 파이프(|) 기호로 표시한다. 명령과 명령 사이에 |를 배치하면 앞 명령으로 생성된 프로세스의 표준 출력을 뒤 명령으로 생성된 프로세스의 표준 입력으로 연결한다. | 대신 |&를 사용하면 표준 출력과 표준 에러 모두 파이프라인이 된다.
$ ls /etc | grep cron
파이프라인의 프로세스 종료 코드
파이프라인은 앞 명령을 실행하는 프로세스의 표준 출력을 뒤 명령을 실행하는 프로세스의 표준 입력에 연결한다. 이때 두 프로세스는 서로 다른 프로세스라는 점에 유의해야 한다.
프로세스는 종료될 때 종료 상태를 종료 코드로 남긴다. 파이프라인을 사이에 두고 실행되는 두 프로세스도 각각 종료 코드를 남긴다. 그런데 파이프라인은 한 줄로 명령을 내린다. 이 명령은 어떤 프로세스의 종료 코드를 받아오게 될까? 파이프라인은 마지막에 실행된 명령의 프로세스 종료 코드를 받아오게 된다.
$ cat lyrics | grep you
$ echo &?
$ cat lyrics | grep kimchi
$ echo &?
grep 명령 뒤에 파이프라인으로 wc 명령을 연결한다. 그러면 wc 명령의 결과가 명령 전체의 결과가 된다. grep 명령이 실패하더라도 그 뒤에 있는 wc 명령이 성공했기 때문에 전체 실행 결과는 성공이다.
$ cat lyrics | grep kimchi | wc
$ echo $?
파이프라인을 사용할 때 여러 프로세스가 생성되고, 프로세스는 종료 코드를 각각 반환한다. 파이프라인을 포함하는 명령을 내린 셸 입장에서는 프로세스의 종료 상태를 결정하기 위해 여러 종료 코드 중 하나를 선택할 수밖에 없다.
여러 프로세스 중 하나라도 실패하면 전체를 실패로 봐야 하는 게 아닐까?라는 생각을 할 수도 있다. pipefail 옵션을 활성화하면 파이프라인을 실행하는 중에 실패하는 프로세스가 있으면 종료 코드를 실패로 설정한다.
$ set -o pipefail
$ shopt -o pipefail
pipefail 옵션을 활성화시키고 위에서 입력한 명령어를 다시 입력하면 다른 결과를 확인할 수 있다.
$ cat lyrics | grep kimchi | wc
$ echo $?
이제 grep 명령어가 실패한 종료 코드 1이 출력된다.
함께 읽으면 좋은 글
리눅스(Linux) 리디렉션(Redirection)을 알아보자
리디렉션(Redirection)리디렉션(redirection)의 사전적 의미는 '방향 전환'이다. '스트림을 리디렉션 한다'라고 하면 스트림을 어느 방향으로 보내는 것일까? 정답은 파일이다. 리눅스의 리디렉션은 스
jettstream.tistory.com
'프로그래밍 > 리눅스' 카테고리의 다른 글
리눅스(Linux) &>와 2>&1 차이점에 대해서 (0) | 2025.02.10 |
---|---|
리눅스 필수 커맨드라인 툴 grep (0) | 2025.02.10 |
리눅스(Linux) 리디렉션(Redirection)을 알아보자 (0) | 2025.02.09 |
리눅스(Linux) IPC의 종류에 대해서 알아보자 (0) | 2025.02.04 |
리눅스(Linux) 포어그라운드 프로세스와 백그라운드 프로세스 (0) | 2025.02.04 |
댓글