Doputer

데몬 프로세스에 대한 이해😈

웹 서버를 배포할 때 데몬 프로세스의 개념이 등장한다. 물론 패키지를 이용하면 데몬 프로세스에 대한 이해 없이 손쉽게 배포할 수 있지만 원리를 알고 있는 것도 중요하다고 생각한다. 데몬 프로세스에 대해 작성하면서 이와 관련된 포그라운드 프로세스와 백그라운드 프로세스까지 함께 정리해보려고 한다.

 

Node.js로 웹 서버를 배포하는 시나리오를 가정했다.

 

포그라운드 프로세스(Foreground Process)

Node.js로 프로젝트를 마친 뒤 서비스로 운영하기 위해서 클라우드 서버에 올렸다고 해보자. 서버 프로세스를 실행하기 위해서 node app.js 명령어를 입력하면 마무리될 것 같지만 여러 가지 문제가 발생한다.

 

node app.js 명령어는 프로세스를 포그라운드로 실행하기 때문에 프로세스가 실행 중인 터미널에서 다른 명령어를 이용할 수 없다. 포그라운드 프로세스는 터미널과 키보드를 통해 사용자와 대화하는데 입력한 명령이 실행되고 결과가 출력될 때까지 기다리기 때문이다.

$ node app.js
server is running...

 

프로세스가 끝나지 않고 동작 중이기 때문에 다른 명령어를 입력할 수 없다. 뿐만 아니라 터미널이 종료되거나 접속 세션이 끊기면 프로세스가 종료된다.

 

백그라운드 프로세스(Background Process)

그렇다면 프로세스를 포그라운드와 반대로 백그라운드로 실행한면 어떨까? 백그라운드 프로세스는 터미널과 관계를 끊고 독립적으로 동작하기 때문에 프로세스가 실행 중이어도 다른 명령어를 입력할 수 있다.

 

앞서 실행한 명령어 뒤에 &(ampersand)를 붙여주면 백그라운드로 실행할 수 있다. 이제 node app.js & 명령어를 통해서 프로세스를 실행해보자.

$ node app.js &
[1] 40313
$

 

이어서 $ 프롬프트가 나오는 것을 볼 수 있는데 이어서 다른 명령어를 입력할 수 있다. 이제 서버 프로세스를 백그라운드로 실행해놓고 끝내고 싶지만 다른 문제가 발생한다. 백그라운드 프로세스도 마찬가지로 터미널이 종료되거나, 접속 세션이 끊기면 프로세스도 종료된다.

 

프로세스가 종료되는 이유

터미널이 종료되거나 접속 세션이 끊기면 프로세스가 종료되는 이유가 무엇일까? 터미널을 종료하거나 접속 세션이 끊어지면 Bash에게 SIGHUP 시그널이 전달되고, Bash는 관리 중인 모든 프로세스 그룹에 SIGHUP 시그널을 전송한 뒤 종료된다. 시그널을 받은 프로세스 그룹은 고아 프로세스 그룹이 되고, 이 그룹에 속한 프로세스는 마찬가지로 SIGHUP 시그널을 받고 종료된다.

 SIGNUP(HUP)은 전화선이 끊어졌을 때 발생하는 시그널인데 기본 동작(default action)이 종료이다. 이 때문에 별다른 설정을 하지 않고, 이 시그널을 받는 프로세스는 종료된다.

 

정리하자면 터미널이 종료되거나 접속 세션이 끊긴 경우 프로세스가 종료 시그널을 받게 되므로 기본 동작에 따라 프로세스가 종료된다.

 

데몬 프로세스(Daemon Process)

데몬 프로세스는 백그라운드 프로세스 중 하나이다. 정확히는 PPID가 1이거나 부모 프로세스가 데몬 프로세스인 프로세스를 말한다. 그렇다면 데몬 프로세스와 백그라운드 프로세스의 차이는 무엇일까? 결정적으로 터미널이 종료되었을 때 터미널에서 실행한 프로세스가 함께 종료되는가이다.

 

PPID가 1이라는 의미는 무엇일까? PID가 1인 프로세스는 시스템 부팅 과정 중 생성되는 최초의 프로세스(Init Process)시스템이 종료될 때까지 유지되는 프로세스이다. 부모 프로세스가 자식 프로세스를 만든 후에 죽게 되면 자식 프로세스는 고아 프로세스(Orphan Process)가 되는데 이때 부모 프로세스를 Init Process로 지정하면 시스템이 종료될 때까지 유지되는 데몬 프로세스가 된다.

 

PID와 PPID

PID: PID(Process Identifier, 프로세스 식별자)는 운영 체제에서 프로세스 각각을 구분하기 위해 부여하는 값이다.

PPID: PPID(Parent Process Identifier, 부모 프로세스 식별자)는 프로세스를 생성한 부모 프로세스의 PID를 나타낸다.

쉘 프롬프트에서 프로세스를 생성한 경우 쉘이 부모 프로세스가 되고, 생성된 프로세스는 자식 프로세스가 되어서 쉘의 PID를 PPID로 갖는다.

 

이 부분을 가시적으로 확인하기 위해서 터미널에서 ps 명령어를 이용하면 된다. Process Status를 확인할 수 있는 명령어로 확인에 필요한 일부 옵션만 사용하려고 한다.

$ ps --help all

Usage:
ps [options]

Basic options:
-A, -e                all processes

Output formats:
-f                    full-format, including command lines

 

백그라운드 프로세스를 실행 한 뒤 ps -ef 명령어를 통해서 PID와 PPID를 확인해보자 결과가 여러 개 나오기 때문에 grep 명령어를 함께 이용했다.

$ node app.js &
[1] 40313

$ ps -ef | grep 30473
UID   PID  PPID C  STIME     TTY    TIME         CMD
501 30473 30472 0 4:36AM ttys001 0:03.87 -zsh
501 40313 30473 0 4:40AM ttys002 0:01.26 node app.js

 

결과를 확인해보면 node app.js PPID가 이 프로세스를 실행한 -zsh 쉘의 PID와 동일한 것을 볼 수 있다.

 

nohup과 PM2

nohup"no hang up" 이라는 의미로 앞서 설명한 HUP을 무시하도록 해주는 명령어이다. 엄밀하게 말하면 데몬 프로세스를 만들어주는 것은 아니고 데몬 프로세스처럼 동작하게 해준다. 터미널이 종료될 때 보내는 SIGHUP 신호를 거부한다.

$ nohup node app.js &
[1] 43330

$ ps -ef | grep 40967
UID   PID  PPID C  STIME     TTY    TIME           CMD
501 42967 42966 0 6:18PM ttys001 0:00.44 -zsh
501 43330 42967 0 6:18PM ttys001 0:01.00 node app.js &

 

반면에 PM2는 데몬 프로세스로 만들어준다.

$ pm2 start app.js
$ ps -ef | grep 873
   UID    PID PPID C STIME TTY     TIME                                        CMD
ubuntu    873    1 0  2021   ? 00:46:23 PM2 v5.1.0: God Daemon (/home/ubuntu/.pm2)
ubuntu 196447  873 0  2021   ? 00:54:10 node app.js

 

부모 프로세스가 PPID 1을 가지는 데몬 프로세스이므로 자식도 데몬 프로세스이다.

반응형

'아티클' 카테고리의 다른 글

OAuth 2.0이란?🔑  (2) 2022.01.02
NestJS에서 FTP 사용하기📦  (0) 2022.01.02
PM2로 Node.js 서비스 운영하기🚙  (0) 2022.01.02
GitHub Actions로 AWS S3 배포 자동화 하기⚙️  (0) 2022.01.02
Github 프로필 꾸미기 👑  (2) 2021.05.08

이 글의 태그

블로그의 정보

Doputer

#김도현

활동하기