[ 살펴보기 ] PM2 - Basics
![[ 살펴보기 ] PM2 - Basics](https://cdn.hashnode.com/res/hashnode/image/upload/v1730737843945/5c3c51d5-9adc-4286-8d6d-761e93efcd9e.jpeg)
NodeJS application을 EC2와 같은 cloud server에 배포하고 Terminus, putty와 같은 SSH client tool을 통해 instance에 접속해서 Node application을 실행하면 SSH client session이 종료되기 전까지 Node application이 실행된다. 하지만 application을 실행한 SSH client sesion을 종료하면 Node application도 함께 종료된다.
SSH client session이 종료된 뒤에도 계속해서 Node application 실행 상태를 유지하기 위해 사용할 수 있는 process manager 중 하나가 PM2다.
해당 포스트를 통해 NextJS app을 PM2를 통해 실행하고 실행 상태를 유지하는 방법을 살펴보자. 테스트 환경은 Ubuntu 22.04 환경에서 진행되었다.
pm2를 설치하기 위해 npm이 필요하므로 우선 node를 설치해준다. ( node를 설치하면 npm은 default로 함께 설치된다 ) 해당 포스트에선 nvm을 통해 node를 설치하겠다. nvm은 현재 system에 여러 node version을 설치하고 사용할 수 있게 도와주는 version manager다.
nvm을 설치하기 위해서 다음 install script를 실행한다. 글을 작성하는 기준 0.40.1 version이 가장 최근 버전이지만 추후에 version이 변경될 수 있으므로 최신 version은 nvm github page를 참고하자. ( Reference - Installing and Updading )
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
그리고 script 설치로 인해 추가된 변경사항을 현재 ssh session에 적용하기 위해 다음 명령어를 실행한다.
source ~/.bashrc
이제 다음 command를 통해 설치할 수 있는 node version을 확인할 수 있다.
nvm list-remote
list에 나오는 version중 설치할 version을 다음 명령어를 통해 설치해준다.
nvm install v22.11.0
이제 다음 command를 실행하면 nvm을 통해 설치한 node version list를 확인할 수 있다.
nvm list
만약 사용하는 node version을 변경하고 싶다면 nvm use command를 통해 설치되어 있는 다른 node version으로 변경할 수 있다.
nvm use v23.1.0
이제 pm2를 설치할 준비가 되었으므로 다음 명령어를 통해 pm2를 설치한다.
npm install -g pm2@latest
그리고 NextJS가 위치한 경로로 이동해서 pm2를 통해 NextJS application을 실행해보자. NextJS를 build한 상태고 production code를 pm2으로 실행한다고 가정해보자. NextJS의 package.json script는 대부분 다음과 같을 것이다.
...
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
...
NextJS build 후 production 실행 script는 npm run start이므로 다음 command를 통해 pm2를 통해 NextJS production code를 실행할 수 있다. ( NextJS proejct가 위치하는 경로에서 아래 command를 실행해야 한다 )
pm2 start "npm run start"
위의 command를 실행한 다음 pm2 list command를 실행하면 현재 pm2로 실행 중인 application list와 pm2로 실행 중인 application의 id, name, pid, status등의 정보를 확인할 수 있다.
pm2을 통해 process를 manage할 때 사용할 수 있는 명령어는 다음과 같다.
pm2 start : pm2로 application을 실행한다. 위의 예제와 같이 npm script를 전달할 수 있고 혹은 entry point가 되는 file 이름을 전달할 수도 있다.
pm2 start "npm run start"; // NextJS와 같이 npm script를 통해 application을 실행할 때 pm2 start app.js // node app.js와 같이 entry file을 통해 node app을 실행할 때pm2 start command에 사용할 수 있는 option 중 일부는 다음과 같다.
--watch /* watch mode로 실행, project file에 변경사항이 발생하면 application을 restart한다. */ --name /* pm2로 application을 실행할 때 application 이름을 명시적으로 설정한다 ( pm2 list에서 조회되는 이름 ) */pm2 restart : pm2로 실행 중인 application을 재실행한다. pm2 application id를 전달해도 되고 name을 전달해도 된다. pm2 application의 id와 name 정보는 pm2 list command를 통해 확인할 수 있다.
pm2 restart 0;pm2 stop : pm2로 실행 중인 application을 중지한다. pm2 application id를 전달해도 되고 name을 전달해도 된다. pm2 application의 id와 name 정보는 pm2 list command를 통해 확인할 수 있다.
pm2 stop 0;pm2 delete : pm2로 실행 중인 application을 pm2 list에서 삭제한다. application id를 전달해도 되고 name을 전달해도 된다. pm2 application의 id와 name 정보는 pm2 list command를 통해 확인할 수 있다.
pm2 delete 0;pm2 monit : pm2 application이 사용하는 resource를 정보를 아래와 같은 형태로 보여준다.

pm2 show : 특정 pm2 application의 metadata를 확인할 수 있다. 예를 들어
pm2 show 0command를 실행하면 id가 0인 pm2 application의 metadata를 출력한다.
Restart Strategies
pm2는 application이 예기치 못하게 문제가 발생하여 중단되면 자동으로 application을 restart 한다. 그렇기에 특정한 문제로 인해 지나치게 잦은 restart가 발생하지 않도록 pm2을 통해 application을 실행할 때 --restart-delay option을 통해 auto restart사이의 delay를 설정해주는 것이 좋다. 아래는 restart-deplay를 3초로 지정하는 예제다.
pm2 start "npm run start" --restart-delay=3000
만약 임의로 특정한 상황에 따라 application을 restart 시키고 싶다면 적용할 수 있는 방법이 여러가지 존재한다. 아래는 documentation에서 소개하는 restart strategy 중 일부를 소개한다. ( Reference - Restart Strategy )
Cron time기반 restart
설정한 cron time마다 restart : pm2를 실행할 때 --cron-restart option을 통해 cron time을 설정하면 해당 시간마다 application이 restart된다.
pm2 start "npm run start" --cron-restart="0 0 * * *"
위의 예제는 pm2를 통해 실행하는 application을 매일 자정 ( 00 : 00 )에 restart하도록 설정하는 예제다. cron-restart option에 사용된 cron expression의 뜻은 다음과 같다.
0 - 분을 설정한다 ( 0 ~ 59 )
0 - 시간을 설정한다 ( 0 ~ 23 )
* - 일자(day of the month)를 설정한다 ( 1 ~ 31 )
*로 설정하면 any value를 뜻하며 매일 적용된다.
* - 월(month)을 설정한다 ( 1 ~ 12 )
*로 설정하면 any value를 뜻하며 매달 적용된다.
* - 요일을 나타내는 일자(day of the week)를 설정한다 ( 0 ~ 7 ),
0 또는 7이 일요일
*로 설정하면 any value를 뜻하며 어떤 요일이든 적용된다.
만약 설정한 cron-restart option을 disable 시키고 싶으면 다음 명령어를 실행한다. 아래 command에서 restart 다음에 전달하는 0은 cron-restart option을 disable 시키고 싶은 pm2 application id다.
pm2 restart 0 --cron-restart 0
File change 기반 restart
pm2로 실행하고 있는 application file에 수정이 발생하면 restart 시키고 싶다면 다음과 같이 pm2를 통해 application을 실행할 때 --watch option을 함께 전달한다.
pm2 start "npm run start" --watch
주의할 점은 pm2 stop command를 통해 application을 중단한 상태에서 file 변경이 발생해도 restart가 된다. 만약 stop 되었을 때도 watch mode를 disable하고 싶다면 다음과 같이 stop command에도 --watch option을 추가해준다.
pm2 stop 0 --watch
Persistent application
여기서 한 가지 문제가 있다. pm2를 통해 ssh client session이 종료되어도 이제 application은 정상적으로 동작하지만 application을 배포한 ec2 instance를 종료하고 다시 시작하면 pm2로 실행했던 application은 자동으로 다시 실행되지 않는다.
만약 ec2 instance가 종료되었다가 다시 시작되었을 때 pm2 application을 restart하고 싶다면 startup script를 생성해서 적용할 수 있다. ( Reference - Generating a startup script )
다음 command를 실행해보자.
pm2 startup
위의 command를 실행하면 필요한 startup script를 출력해준다. 해당 script를 copy & paste하고 실행하면 startup script가 추가된다.
또 하나 중요한 과정은 ec2가 reboot될 때 자동으로 restart하고 싶은 application을 pm2로 실행하고 다음 command을 통해 save 해주어야 한다.
pm2 save
만약 startup script를 disable 시키고 싶다면 다음 command를 실행한다.
pm2 unstartup
위의 command를 실행하면 startup script를 disable 시키기 위한 script를 출력해준다. 마찬가지로 해당 script를 copy & paste하고 실행하면 startup script가 disable된다.
![[ 살펴보기 ] RDB - Relationships](https://cdn.hashnode.com/res/hashnode/image/upload/v1739711556668/48dc9e84-a621-42aa-9c9f-5fc5c436f0ec.jpeg)
![[ 살펴보기 ] MySQL - Data types](https://cdn.hashnode.com/res/hashnode/image/upload/v1739593589113/530f8704-4d27-42c9-a451-bb5c63150b99.jpeg)
![[ 살펴보기 ] TypeORM - Transactions, Migration](https://cdn.hashnode.com/res/hashnode/image/upload/v1739106042581/980b8133-61d4-406a-a026-65be9c28eace.jpeg)
![[ 살펴보기 ] TypeORM - Relations](https://cdn.hashnode.com/res/hashnode/image/upload/v1738666874402/b688bd0b-b6bb-4f43-87d8-c1b46b59f1b7.jpeg)
![[ 살펴보기 ] TypeORM - Basics](https://cdn.hashnode.com/res/hashnode/image/upload/v1738666803591/bef5df17-7dc7-4123-ae55-004d5042df39.jpeg)