본문 바로가기
  • 오늘도 한걸음. 수고많았어요.^^
  • 조금씩 꾸준히 오래 가자.ㅎ
IT기술/리눅스

[linux] 표준 입출력, 파이프 | 알아보기

by 미노드 2023. 7. 5.

리눅스를 사용하다보면 파이프( | )를 사용해 명령어를 조합하는 내용을 자주 볼 수 있다.

단순하게 명령어 하나만 사용하면 얼마나 좋을까...
그러면 참 편할텐데, 

리눅스는 이정도 수고로움은 감수하는 것을 권고하고있다.
유용한 기능이 될 수 있는 부분이라 그런 것으로 보인다.

파이프( | )를 이해하기 위한 사전 내용을 정리해보자.

1. 리눅스 쉘(shell) 이해하기

사용자는 리눅스 커널(Kernel)과 통신하기 위해 쉘을 사용합니다.
* 커널은 리눅스 운영체제가 동작하는데 있어 중요한 역할을 합니다.
어플리케이션이 동작하는데 있어 커널이 CPU, 메모리 등 자원을 할당합니다.
사진으로 보면 다음처럼 됩니다.

어플리케이션을 실행시키기 위해 메모리 cpu 같은 자원을 할당해야 하는데,
윈도우 기준으론 exe파일 같은 실행파일을 클릭하면 되는데,,,
실행파일을 클릭하려면 필요한 것이 있습니다.
 - 바탕화면에서 경로를 열어 클릭한다.
 - command 에서 경로를 찾아가 실행시킨다.

리눅스에선 이를 쉘이 대신한다고 보면 이해가 쉽습니다.
 - 쉘에서 경로를 찾아가 실행시킨다.

쉘을 통해 경로에 접근하고 명령어를 수행할 수 있습니다.(바탕화면의 역할을 대신합니다.)
특이하게도 쉘의 종류는 한가지가 아니며, 여러가지 쉘들 중에 선택해서 사용할 수 있습니다.
대중적으로 bash쉘을 많이 사용합니다.

2. 리눅스 파이프

파이프(Pipe)란 프로세스간 통신을 할때 사용하는 커뮤니케이션의 한 방법입니다.
프로세스간 연결해주는 통로를 의미하기에 파이프( | ) 라고 부릅니다.

ls 하나를 실행시킨다면 다음의 과정이 이루어집니다.
* 터미널에서 'ls' 라는 명령어를 입력
* 자식프로세스 1개가 fork되어 백그라운드에서 부모프로세스의 정보를 기준으로 해당 명령어 즉, stdin을 통해 정보를 입력받음
* stdout을 통해 ls 명령어를 호출한 터미널로 정보를 반환.

만약 ls | sort | less 명령어를 입력한다면? (파이프로 여러 명령어를 조합)
* ls가 실행되고 나온 output을 sort에 넣어준다.
* sort가 실행되고 나온 output을 less에 넣어준다.
이렇게 됩니다.

즉, 입력과 출력을 다루는데 있어 프로세스의 결과를 입력값으로 사용할 수 있는 기능입니다.

※ 참고, 표준 입력과 표준 출력

리눅스에서는 표준 입력과 표준 출력이라는 이름의 데이터 흐름을 사용한다.
입력은 특정 프로그램으로 들어오는 값을 말하고, 출력은 특정 프로그램에서 나오는 값이다.
입력 장치에는 키보드, 파일, 스캐너 등이 해당되고, 출력 장치에는 모니터, 프린터, 파일 등이 해당된다.
다양한 입출력장치 중에서 기준이 되는 입력을 
표준 입력이라고 하는데 키보드를 말하고, 기준이 되는 출력을 표준 출력이라고 하는데 화면(모니터)이 이에 해당한다.

※ 참고, 리다이렉션

표준 입출력다른 입출력으로 변경할 때 사용하는 기능이 리다이렉션 이다.
> : 프로세스의 출력을 표준 출력에서 다른 출력으로 변경한다.
>> : 프로세스의 출력을 지정한 출력(보통 파일)에 추가한다.
< : 프로세스의 입력을 표준 입력에서 다른 입력으로 변경한다.
<< : 기호 뒤에 지정한 문자열을 입력으로 받아 해당 문자열이 나오기 전까지를 표준 입력을 삼아 해당 내용을 출력한다.

3. 파이프로 조합할  수 있는 형식을 이해해야 한다.

만약 다음 명령어를 친다면 ls의 결과는 출력되지 않습니다.

ls | sort | cd /tmp/sample

* 현재 경로에서 ls | sort의 output 값이 나온다.
* 해당 output값이 어떻든 /tmp/sample 경로로 이동할 것 이다.
로 예측할 수 있으며, 경로이동은 되나 그걸로 끝납니다.

원인 1
- 보통 터미널을 실행시켜 명령을 수행하는데, 터미널 또한 프로세스입니다.
터미널(부모프로세스)에서 명령어를 실행하게되면, 터미널의 자식프로세스로써 명령이 수행됩니다.
fork 방식으로 별도의 자식프로세스로써 명령이 수행되는 것을 이해해야합니다.

원인 2
ls | sort의 output -> cd /tmp/sample 의 input이 되는 건데,
ls | sort의 output의 stdout동작은 cd /tmp/sample 프로세스의 내부에서 동작하고 끝난 것 입니다.
터미널(부모프로세스)에서 stdout이 일어나지 않고  cd /tmp/sample(자식프로세스) 에서 동작되고 끝나버린 것 입니다.

※중요

부모 프로세스(터미널)에서 fork로 인해 자식프로세스들이 생기면 자식 프로세스들은 모두 병렬로 처리되게 됩니다.
또한 모든 프로세스는 exec 방식으로 호출되어 프로세스 PID는 모두 동일하게 갖게 됩니다.
프로세스들은 stdin, stdout 방식으로 A | B | C 가 호출된다면,
A의 stdout을 B는 stdin으로 읽어들어오며 C 또한 마찬가지로 동작하게 됩니다.
그리고 A의 stdout을 받기 전까지 프로세스는 B프로세스는 wait 상태가 되며, C또한 마찬가지 상태가 됩니다.

이를 그림으로 보면 

이런식으로 진행되게 됩니다.

만약 ls | sort 의 결과를 출력하면서 cd /tmp/sample 도 이행하려면
이를 파이프로 묶어 하나의 프로세스로 처리할게 아니라
동시 동작을 지원하는 스레드로 묶어야 합니다.
다음 명령어를 수행하면 되겠네요.

ls | sort && cd /tmp/sample

이상 파이프에 대한 설명과 예시를 들어봤습니다.