‘하둡 클러스터의 master 서버에서 namenode가 데몬으로 실행되고, slave 서버에서 datanode와 task tacker가 데몬으로 실행된다.’
이 단 한줄의 문장을 이해하기 위해 이 포스팅을 하고있다.
사실 데몬이라는 말을 완전히 모르고 있던것은 아니다. 내가 학원에서 했던 프로젝트 중에 처음 Airflow 사용했을 때, 매번 cmd창을 두개 띄우고 aws에 접속하여 webserver와 scheduler를 켰던 적이 있다. 이때 이게 너무 불편해서 한번에 두개 다 계속 돌아가게 할 수 없나 싶어서 찾다가 알게된게 ‘nohup과 &기호로 webserver와 scheduler를 데몬으로 켜둔다’라는 내용의 블로그 글이였다. 당시에도 데몬이 뭔가 싶어서 잠깐 찾아봤는데 그냥 백그라운드로 실행되는 프로세스라고 하길래 그렇게만 알고 넘어 갔었다.
사실 맨 위의 문장을 이해하는데 ‘데몬은 백그라운드로 실행되는 프로세스다’ 이상의 더 깊은 이해가 필요할까 싶기도하다. 그래도 저번에 대충넘겼으니 그에 대한 업보(?)로써 이번엔 좀 자세히 공부하는게 맞지않나 하는 생각에 이 글을 작성하게 됐다.
1. 프로세스(포그라운드와 백그라운드)
데몬에 대한 여러가지 레퍼런스들을 찾아보면, ‘데몬은 프로세스다’라고 쓰여있는 경우들도 왕왕 목격할 수 있다. 데몬이 물론 프로세스이긴하나, 이는 반쪽짜리 정의에 불과하다.
프로세스는 간단하게 표현하면 실행 중에 있는 프로그램을 의미한다. 물론 이런 단순한 의미 이상의 깊은 메커니즘을 가지고 있지만, 어쨌든 이 프로세스라는 건 크게 포그라운드와 백그라운드로 구분이된다. 그리고 데몬은 이 중 백그라운드 프로세스의 일종이다. 그럼 포그라운드(Foreground)와 백그라운드(Background) 프로세스는 어떤 차이가 있을까?
사실 그 이름에서 어느정도 유추했듯이 ‘눈 앞에 보이냐 아니면 눈에 보지않느냐’로 프로세스가 구분된다.
포그라운드 프로세스는 사용자가 터미널, 키보드, 마우스 등과 같은 표준 입출력 장치를 통해 대화하는 프로세스를 의미한다. 좀더 linux 친화적으로 말하면 사용자가 tty나 pts를 통해 프로세스와 대화할 수 있는 프로세스를 포그라운드 프로세스라고 한다. 당장 우리 눈앞에 있는 이 엣지 브라우저부터 시작해서, 노션, 슬랙, 메모장, 카카오톡 등이 모두 포그라운드 프로세스이다.
백그라운드 프로세스는 적어도 입력장치에 대해 터미널과의 관계를 끊은 프로세스를 의미한다. 좀 더 쉽게 풀어 말하면, 실행시켜놓으면 알아서 눈에 보이지않는 백그라운드에서 스스로 동작하는 프로세스가 백그라운드 프로세스다.
2. 백그라운드 프로세스
사실 데몬을 백그라운드 프로세스 그 자체라고 헷갈려하는 경우가 많다. 나도 이전의 경험속에서 데몬은 백그라운드 프로세스라고 이해하고 있었다. 하지만 엄격히 백그라운드 프로세스와 데몬은 구분된다. 그 구분을 위해 백그라운드 프로세스에 대해 좀 더 알아보도록 하겠다.
(앞으로의 내용은 데몬(daemon) 프로세스란 무엇인가? (blogger.pe.kr)의 내용을 따라서 진행한 내용이다. )
개인 windows PC에서 GCP의 인스턴스로 SSH접속을 하는 상황을 가정해보자. 우선 cmd 창을 열것이고 ssh 명령어로 GCP 인스턴스에 접속을 해야한다.
ssh 명령어를 사용하는 순간까지는 내 윈도우 pc에서 실행된 cmd의 화면이다. cmd는 C:\Users와 같이 표현되는 프롬프트를 표시하고, 나는 cmd 창에서 ssh 명령어를 키보드로 입력한다. 따라서 cmd는 포그라운드 프로세스이다.
이번엔 다음 라인에 표시되는 Last login: Wed Oct … 에 대해서 알아보자.
cmd는 내가 입력한 ssh명령어를 해석해 PC에 있는 ssh 명령을 실행하고 뒤에 입력받은 GCP 인스턴스의 퍼블릭 IP로의 접속을 시도한다. 그리고 해당 인스턴스에서 실행되고 있는 ssh 데몬(sshd)과 세션을 맺은 후 ssh 데몬(sshd)이 보여주고자 하는 ‘사용자가 인스턴스에 접속한 마지막 시간과 접속 IP’를 전달받아 화면에 출력해준다.
즉, ssh 명령도 화면에 sshd로 부터 전달받은 내용을 표시하고 키보드를 통해 입력한 ssh 명령어를 GCP 인스턴스에 전달하므로 포그라운드 프로세스다.
지금까지 우리는 cmd와 ssh 명령이라는 두 개의 포그라운드 프로세스에 대해 이해했다. 그러면 뒤에 ‘[won21yuk@instance-1]$’ 이라고 표시된건 뭘까?
$는 리눅스의 쉘임을 나타내는 기호이다. 우리는 ssh명령어를 통해 GCP 인스턴스에 접속했고 그 GCP 인스턴스는 linux OS이기 때문에 cmd창에 $라는 기호가 생겨난 것이다. 그럼 sshd가 $를 화면에 띄워주고 사용자의 입력을 기다리므로 sshd는 포그라운드 프로세스일까?
결론부터 말하자면 sshd는 포그라운드 프로세스가 아니다. 그 이유는 sshd의 역할에 있다.
sshd는 ssh를 통해 내 로컬에 가지고 있는 공개키와 GCP 인스턴스에 등록된 공개키가 같은지 확인하고 일치하는 경우 접속을 허용하여 해당 계정에 할당된 bash를 실행시킨 후 뒤로 물러난다.
따라서 화면에 표시된 $ 기호는 sshd가 출력한게 아니라 sshd가 실행시킨 bash가 출력한 것이다. 결국 sshd 그 자체는 사용자로부터 어떠한 입력을 받지도 않고 직접 무언가를 출력하지도 않았다.
이를 좀더 자세히 보기위해 프로세스들간의 관계를 살펴보도록 하겠다.
1
2
3
4
5
6
7
8
9
10
# ps -ef
PID PPID
root 1168 1 0 12:07 ? 00:00:00 /usr/sbin/sshd -D
.
.
.
root 1642 1168 1 12:58 ? 00:00:00 sshd: won21yuk [priv]
won21yuk 1645 1642 0 12:58 ? 00:00:00 sshd: won21yuk@pts/0
won21yuk 1646 1645 0 12:58 pts/0 00:00:00 -bash
[won21yuk@instance-1 ~]$
위의 내용은 GCP 인스턴스에서 ps -ef명령어로 실행되고있는 프로세스 목록을 출력한 것이다. 여기서 중요하게 봐야할 건 PID와 PPID이다.
- PID
- Process ID의 줄임말이다. Linux 운영체제에서 프로세스를 식별하기 위해 부여한 번호이다.
- PPID
- Parent Process ID의 줄임말이다. 부모 프로세스의 PID를 의미한다. 만약 부모 프로세스가 자식 프로세스보다 일찍 종료되는 경우 자식 프로세스는 고아 프로세스가 되어 PPID 로 init process 의 PID, 1을 가지게 된다.
맨 첫단에 보면 root 계정으로 실행된 sshd -D 프로세스(PID 1168)를 확인할 수 있다. 그리고 아래에 PPID가 1168인 sshd(PID 1642)가 보인다. 그 아래에는 won21yuk 계정으로 실행된 sshd 프로세스(PID 1645)가 있고 PPID는 1642이다. 마지막으로 bash 프로세스(PID 1646)가 있고 PPID는 1645다.
이 관계는 root 계정에서 실행된 sshd(PID 1168)가 won21yuk 계정에서 실행되는 sshd를 실행하고 그 sshd가 bash를 실행했음을 보여준다. 그리고 마지막으로 실행된 bash가 앞서 봤던 $기호를 화면에 출력한 것이다.
따라서 sshd는 사용자와 직접 대화하지 않는 백그라운드 프로세스임을 알 수 있다. 반면, 마지막에 실행된 bash는 사용자와 대화를 하기 위해 프롬프트를 띄우고 키보드로부터의 입력을 기다리고 있으므로 포그라운드 프로세그가 된다.
3. 데몬 프로세스
지난 단락에서 백그라운드 프로세스를 이해했다면, 이제는 진짜 데몬 프로세스가 무엇인지 알아볼 차례이다.
데몬 프로세스는 앞서도 언급했지만, 백그라운드 프로세스의 일종이다. 그럼 백그라운드 프로세스가 어떤 특성을 가질 때 데몬프로세스가 되는걸까?
결론부터 말하자만 아주 간단하다. 백그라운드 프로세스 중 PPID가 1이나 다른 데몬 프로세스인 경우에 이를 데몬 프로세스라고 한다.
그런데 말은 엄청 간단한데, 사실 이해하기는 상당히 어렵다. 어쨌든 데몬 프로세스가 백그라운드 프로세스 중 하나인데, PPID가 1이든 데몬프로세스든 도대체 뭔 상관인지 쉽게 납득이 안간다.
이를 위해 크게 일반 백그라운드 프로세스와 데몬프로세스가 어떤 차이가 있는지와 데몬 프로세스의 대표적인 예는 무엇이 있는지를 알아보도록 하겠다.
백그라운드 프로세스와 데몬프로세스의 차이
백그라운드 프로세스와 데몬프로세스의 차이는 프로세스를 실행한 bash가 종료되었을 때, bash를 통해 실행한 다른 백그라운드 프로세스가 종료되는가에 있다. 이를 예시로 설명해 보도록 하겠다.
위의 화면은 포그라운드 프로세스 중 하나인 vim 문서편집기를 &기호를 통해 강제로 백그라운드로 실행시킨 것이다.
이 상태에서 ps -ef 명령어로 프로세스 목록을 확인해보면,
1
2
3
4
5
6
# ps -ef
PID PPID
.
.
won21yuk 2462 2461 0 14:26 pts/0 00:00:00 -bash
won21yuk 2487 2462 0 14:26 pts/0 00:00:00 vim
vim은 bash(PID 2462)를 부모프로세스로 가진 채 실행되고 있다. 물론 vim은 입출력장치와의 연결이 끊겨서 아무것도 할수는 없지만 어쨌든 백그라운드 프로세스로 실행되고 있다. 여기서 ssh접속을 exit으로 끊어버린다면 vim 프로세스는 어떻게 될까?
우리는 앞서 ssh 명령으로 bash가 실행된다는 것을 알았다. 그럼 ssh 접속을 exit으로 끊는다는건, bash도 꺼진다는 것을 의미한다. 따라서 exit명령이 수행되면 bash(PID 2462)와 bash를 PPID로 갖는 vim(PID 2487)가 자동으로 종료되게 된다.
실제로 재접속 후, 프로세스 목록을 확인해보면 위와같이 vim 프로세스가 없어진것을 확인할 수 있다. 뿐만 아니라 bash, sshd도 모두 종료가 됐다. 이는 bash의 PID를 보면 보면 알 수 있는데, bash의 PID가 2462에서 2568로 변경됐다는 것이 bash가 꺼졌다가 켜졌다는 것을 의미하기 때문이다. (프로세스들은 꺼졌다 다시 켜면 새로운 PID를 받는다는 특징이 있다)
여기서 알 수 있는건 sshd, bash, vim은 모두 백그라운드 프로세스로 실행되었지만, 데몬 프로세스는 아니라는 것이다. 데몬이 되기위해서는 백그라운드 프로세스가 PPID를 1혹은 다른 데몬 프로세스를 가져야하기 때문이다.
대표적인 데몬 프로세스
데몬 프로세스는 보통 {suffix} + ‘d’의 구조로 네이밍 되어있다. 가령 앞서 본 sshd부터 해서 익숙한 mongod, mysqld 그리고 다음 설명을 위해 사용할 예제인 httpd 등이 있다.
이러한 데몬 프로세스 중 가장 대표적인건 웹서버 데몬이다. 웹서버 데몬 프로세스는 터미널을 통해 실행될 수 있지만, 보통 터미널을 통해 사용자와 대화할 필요가 없기때문에 백그라운드 프로세스로 생성하도록 되어있다.
즉, 프로그램의 소스 안에서 fork 함수를 통해 자식을 생성하고 부모는 죽는다. 그리고 생성된 자식은 부모프로세스를 1(init)로 변경한 뒤 실제로 서비스를 수행할 자식(손자에 해당) 프로세스를 여러개 fork한다. 그리고 그 자식(손자) 프로세스들은 계정을 setuid 함수를 이용해 웹서버가 실행되도록 설정된 계정으로 바꾼다.
- fork()
- 리눅스에서 fork함수는 현재 프로세스에 대해 자식 프로세스를 생성하는 함수이다.
위의 그림은 apache http webserver를 데몬으로 실행시킨 후, ps -ef 명령어로 관련 프로세스 목록을 확인한 결과이다.
이렇게 PPID가 1인 httpd 프로세스와 PPID가 1인 프로세스(PID 2973)를 PPID로 갖는 5개의 httpd 프로세스가 바로 데몬 프로세스이다.
맨 위의 httpd(PID 2973)는 PPID가 1이다. 그리고 root 계정으로 실행됐다. 이는 웹서버를 root 계정에서 실행시키기 때문인데, 그 이유는 TCP 1024 포트 이하는 root에서만 바인딩(Binding)이 가능하기 때문이다. (apache http webserver의 기본 포트는 80이다.)
그리고 PPID를 2973으로 갖는 httpd 프로세스가 5개가 있고 실행계정은 apache로 설정되어 있다. root가 아닌 apache로 변경한 데는 보안상의 이유가 있다.
PPID가 1인 httpd는 실제 웹브라우저의 요청을 처리하는 웹서버 데몬이 아니다. 대신 사용자의 접속이 많아 웹서버 데몬이 더 이상 사용자의 접속요청을 처리할 수 없을 때, 자식을 fork해주는 역할만 수행한다. 실제로 웹브라우저의 요청을 처리하는 웹서버 데몬은 apache 계정이 실행계정으로 되어있는 나머지 5개의 웹서버 데몬이다. 이는 만약 root 계정으로 실행중인 웹서버가 해킹을 당할경우, 해커는 곧바로 서버의 관리자 권한인 root 권한을 얻게 되는 것을 방지하기 위한 설계이다.
이 데몬 프로세스들은 로그인한 ssh 접속을 exit 명령어로 끊더라도 종료되지 않고 계속 웹 서비스를 제공한다.
위의 사진에서 볼 수 있듯, exit명령어를 실행한 후 다시 ssh로 접속을 해서 httpd 프로세스를 확인하니 여전히 프로세스가 동작 중인 것을 확인할 수 있다.
마지막으로 만약 httpd 프로세스를 전체 종료하고 싶다면, PPID인 2973을 kill해주면 모든 httpd 프로세스를 종료 시킬 수 있다. 다른 데몬 프로세스의 경우에도 이와 같이 부모 프로세스를 kill해주면 모든 관련 프로세스를 종료시킬 수 있다.
4. 데몬의 실행방법
데몬 프로세스를 실행하는 방법에는 Stand-alone과 Inetd 두가지가 있다.
우선, Stand-alone 방식은 보통 부팅 시에 실행되어 해당 프로세스가 메모리에 계속 상주하면서 클라이언트의 서비스 요청을 처리하는 방식을 말한다. 주로 httpd와 같은 웹서버 데몬처럼 클라이언트의 요청이 잦은 경우 이 방식으로 실행된다. Stand-alone 방식은 요청에 따른 응답속도는 빠르지만, 항상 대기해야한다는 점에서 메모리 효율이 좋지 않다는 단점이 있다.
Stand-alone 방식은 /etc/init.d나 /etc/rc.d/init.d에 있는 스크립트 파일로 실행된다. ‘해당 프로세스 절대 경로 + start/stop/status’나 ‘service + 프로세스 이름 + start/stop/status’의 방식으로 명령어를 입력하면 된다.
보통 후자의 형태로 많이 쓰는 것 같은데, 특히 나는 mysql과 mongodb을 linux에서 처음 구축했을 때 실행법을 후자로 배워서 더욱 익숙하다. 또한, service 대신 systemctl을 사용하는 경우도 있는데 이에 대해 찾아봤더니 내용이 좀 긴거같아서 이는 별도의 포스팅을 작성하도록 하겠다.
1
2
3
4
5
6
7
/etc/init.d/sshd start
/etc/init.d/sshd stop
/etc/init.d/sshd status
service mysqld start
service mysqld stop
service mysqld status
Inetd 방식은 프로세스가 메모리에 항상 상주하는 것이 아니라, 클라이언트의 요청이 들어올 때 관련 프로세스를 실행시키고 접속 종료 후에는 자동으로 프로세스를 종료시키는 방식을 말한다. 이를 위해 inted라는 슈퍼 데몬이 존재하고, 이 슈퍼 데몬은 시스템에서 대기하고 있다가 클라이언트의 요청이 들어오면, 관련 데몬 프로세스를 실행시키게 된다. (참고로 inted 자체는 stand-alone방식으로 작동하고 있다)
inetd 방식은 stand-alone 방식보다는 응답속도가 느리지만, 메모리 효율은 그에 비해 훨씬 좋다. 그래서 요청빈도가 적은 서비스들은 inetd방식이 유리하다. 요즘은 보안적인 기능들이 업데이트 된 xinetd를 사용하고 있다.
5. 서비스와 데몬
약간 번외 개념으로써 언급하고 넘어가고자 해당 단락을 추가했다. 솔직히 그다지 중요한 파트로 느껴지진 않지만, 그래도 눈에 들어왔으니 정리는 해놔야겠다 싶어서 적기로 마음 먹었다. 나중에라도 필요한 순간이 올 수도 있으니 말이다.
(출처 : Service와 Daemon의 차이 (tistory.com))
보통 window OS와 Linux OS에서 서버 관리 등의 용도로 사용되는 백그라운드 프로세스를 부르는 명칭이 다르다. 리눅스는 이제껏 봐왔듯 데몬이라고 부르고, 윈도우에서는 서비스(service)라고 부른다. 이는 어느정도 용어가 혼용되어 사용되는 경향이 있지만, 절대 동의어는 아니다.
윈도우에서는 서비스를 본질적인 기능이라기 보단, 특정한 기능으로 취급한다. 그래서 프로세스와 서비스는 단순 1:1 관계가 아니고, 한 프로세스에서 여러개의 서비스를 실행할 수 있도록 되어있다. 이로인해 서비스는 단순히 실행파일에만 국한되지않고 dll도 서비스로 구동한다. 결국 윈도우에서의 서비스는 프로세스보단 작은 단위로 취급한다.
반면 리눅스에서는 데몬은 프로세스와 1:1 관계다. 한 프로세스 아래에서 둘 이상의 데몬이 실행되지 않는다는 뜻이다. 그래서 리눅스에서는 실행파일만 데몬으로 구동한다. 이는 리눅스에서의 데몬은 일반적인 프로세스의 일종이기 때문이다.
기능적으로는 완전히 일치하는 서비스와 데몬이라는 두 개념이 어디서부터 차이가 발생했을까? 사실 데스크탑에서는 사용자가 임의로 작성한 기능이 백그라운드에서 특정 사용자가 로그아웃한 후에도 동작해야하는 경우는 드물다. 따라서 윈도우에서의 서비스는 단순 프로세스 관리가 아닌, 말 그대로 백그라운드 서비스 관리만을 위해 특화된 기능을 추가해야만 하는 상황이였을 것이다.
반면, Unix의 영향을 많이 받은 linux에서는 특정 사용자가 구현한 기능을 해당 사용자의 로그인 여부와 관계없이 백그라운드에서 오랜 시간 실행하는 것이 특이한 요구사항이 아니였을 것이다. 이러한 환경적 요인이 두 개념이 미묘하게 달라지게 되는 계기가 되었을지도 모른다.