ls -ail | grep w 같은 것은 어떻게 동작할까요? 중간에 있는 | 를 리눅스 파이프 명령어라고 이야기 하는데요. 어떻게 동작하는지 보고, 한 가지 명령어에 대해서 왜 이렇게 동작하는지 간략하게 해석해 보도록 하겠습니다.
| 명령어는 어떻게 동작하는가?
./1 | wc를 입력하였습니다. ./1은 무한 루프를 도는 프로그램이고, wc는 단어 수를 세는 명령어입니다. ./1 프로세스의 pid는 2138, wc의 pid는 2139번입니다.
먼저, ./1을 실행한 프로세스 2138번을 보겠습니다. fd는 열려 있는 파일 디스크립터를 의미하는데요. 1번이 pipe와 연결되어 있음을 볼 수 있습니다.
그림으로 그리면, 이렇게 그려집니다. 이제, 2139번을 보겠습니다.
이번에는, 0번 디스크립터가 가리키는 것이 바뀌었음을 알 수 있는데요. stdin 대신에, pipe:[31804]를 가리키고 있음을 볼 수 있어요.
상황이 위와 같이 그려집니다. 여기서 정리를 해 보면, 리눅스 파이프 명령어는 어떤 명령어의 결과를 stdout 으로 내보내는 대신, 다른 프로세스의 input 으로 보내기 위해 쓴다는 것을 알 수 있습니다. 이를 수행하기 위한 중간자를 pipe로 둔 것일 뿐입니다.
예제 명령어로 이해해 보기
이 상황을 예제 명령어로 설명해 보도록 하겠습니다. 많이 쓰시는 예문 중, cat과 grep을 pipe로 연결하는 경우가 많아요. 특히, grep은 단독으로 쓰이는 경우가 잘 없고요. pipe 후행 연산으로, 매우 높은 빈도로 자주 쓰게 됩니다.
cat 1.txt | grep 1을 입력해 봅시다. 선행 명령어는 cat 1.txt이고, 후행은 grep입니다. grep은, 특정 패턴을 찾는 알고리즘으로, grep 1의 경우 line에 1이라는 패턴이 있는지 찾게 됩니다. 있다면, 그 줄을 출력하게 됩니다.
이 결과에서는 1이 나왔네요.
1.txt의 내용을 보니, 1, 2, 3, 4, 5 이렇게 5개의 줄이 있습니다. 이제, grep 1 명령어를 입력해 보겠습니다.
grep 1을 입력하면 왠 빈 창만 나옵니다. 제가 1, 2, 3, 4, 5 등을 입력했을 때 계속 진행되게 되는데요. 이는, grep이 stdin에서 받았기 때문입니다. 1을 입력했을 때, 1이 뜬 것은 당연하게도, 문자열 1에서 패턴 1을 찾을 수 있었기 때문입니다.
grep 1과 cat 1.txt 명령어를 알았습니다. cat 1.txt | grep 1은 무엇을 의미할까요?
cat 1.txt의 1번 디스크립터가 stdout 대신에 pipe로 바뀝니다. cat 1.txt가 출력할 때 쓰는 파일이 stdout 대신에 pipe로 바뀌었다는 의미입니다.
이제 grep 1은, 입력을 받을 때, stdin에서 받는 것이 아니라 pipe 에서 받게 됩니다. cat 1.txt와 grep 1이 공통으로 보고 있는 pipe 입니다. 만약에, cat 1.txt가 1…5를 파이프에 출력했다면, grep 1은 1…5가 있는 파이프로부터 입력을 받습니다. 이제, grep 1은 이 입력으로부터 처리를 해서 stdout에 출력하게 됩니다. cat 1.txt | grep 1 명령어를 입력했을 때 어떤 상황이 벌어졌는지 정리해 봅시다.
- cat 1.txt은, 1.txt에 있는 내용을 출력하는데요. stdout 대신 pipe에 출력합니다.
- 후행 명령어 grep 1이 cat 1.txt의 결과를 받았습니다. stdin 대신 pipe를 통해서.
- 파일 안에 있는 line들 중에 1이 있는 줄을 찾게 됩니다.
결국, cat 1.txt와 grep 1은 파이프를 매개로 통신을 한 셈이 됩니다.