본문 바로가기
코딩과 알고리즘

node.js with pm2 | 백그라운드 실행/중지/재시작/다중포트

인간은 호흡을 하지 않으면 살 수 없습니다.
호흡하지 않는 사람을 우리는 '죽은 사람'이라 일컫지요.
사람뿐만 아니라 모든 자연 만물은 날마다 그 호흡으로 살아 있음을 증명합니다.

재미있는 것은 IT 계에서 다루는 서버컴퓨터도 그 필요로 하는 서비스가 작동중이면 '살아있고',
서비스가 멈추면 '죽었다'고 표현합니다:)

"웹서버 죽었으니 재시작 해주세요!"


지난 스토리에서는 node.js 를 설치하는 방법에 대해 다루어 보았습니다.

https://itadventure.tistory.com/431

 

node.js in AWS | 설치 ( v14.17.5 LTS )

최근에 관심을 갖게 된 스크립트 언어가 있습니다. 바로 node.js ( 노드제이에스 ) 라는 서버 사이드 스크립트 언어인데요. 공식사이트는 아래 URL을 찾아가면 되겠습니다. 일부 페이지만 한글이고

itadventure.tistory.com

 

서버의 SSH 터미널에 접속한 다음 소스가 들어 있는 폴더에서
아래 명령을 이용하여 웹서비스를 실행할 수 있었지요.

node main.js

 

하지만 SSH 터미널을 종료하면 이윽고 웹서비스도 중지되어 버립니다.
정상적으로 작동하던 웹페이지는 결국 아래와 같은 오류 페이지를 보여주게 되지요.

 

이 문제를 해결하기 위해서는 node.js를 백그라운드로 실행해주어야 하는데요.
여러가지 방법이 있지만 여기서는 앞으로도 사용하기 용이한
pm2 ( 프로세스 매니저 ) 를 이용한 방법을 다뤄보겠습니다.

 


pm2 프로세스 매니저 설치

프로세스 매니저란 node.js 를 백그라운드로 실행할 수 있게 해주는 패키지 서비스입니다.
설치 방법은 아주 간단합니다. 리눅스 창에서 아래 명령을 실행해주면 되는데요.

npm install pm2 -g

npm 은 노드 패키지 매니저라고 해서 노드JS에 관련된 패키지 프로그램을 설치해주는 일종의 프로그램입니다.
pm2 라는 패키지 프로그램을 설치하되 -g 옵션을 주어 폴더 어디서나 실행될 수 있게 전역적으로 설치하라는 옵션입니다. 물론 지금은 ec2-user 로 로그인한 상태이기 때문에 ec2-user 권한에 국한됩니다.

어디에 설치되었는지 궁금하시다면 실행파일의 위치를 알려주는 아래 명령어를 내려주시면 됩니다.

which pm2

<결과화면예>
~/.nvm/versions/node/v14.17.5/bin/pm2

 

재미있는 사실이 있는데요. 뭐 이건 따라하실 필요는 없습니다.
npm 으로 설치한 프로그램은 node.js 로 만들어져 있기 때문에 소스 내용이 자바스크립트로 구성되어 있습니다.
일부 소스를 잠깐 보면 아래와 같지요 :)

'use strict';

process.env.PM2_USAGE = 'CLI';

var cst          = require('../../constants.js');

var commander    = require('commander');
var chalk        = require('chalk');
var forEachLimit = require('async/forEachLimit');

var debug        = require('debug')('pm2:cli');
var PM2          = require('../API.js');
var pkg          = require('../../package.json');
var tabtab       = require('../completion.js');
var Common       = require('../Common.js');
var PM2ioHandler = require('../API/pm2-plus/PM2IO');


Common.determineSilentCLI();
Common.printVersion();

var pm2 = new PM2();

PM2ioHandler.usePM2Client(pm2)

commander.version(pkg.version)
  .option('-v --version', 'print pm2 version')
  .option('-s --silent', 'hide all messages', false)
  .option('--ext <extensions>', 'watch only this file extensions')
  .option('-n --name <name>', 'set a name for the process in the process list')
           :

 

그래서 원래는 영문으로만 모든 컨텐츠 내용을 제공하지만 소스를 직접 수정하면,

<변경전>
function displayUsage() {
  console.log('Usage: pm2 [options] <command>')
  console.log('');

<변경후>
function displayUsage() {
  console.log('사용방법: pm2 [options] <command>')
  console.log('');

pm2 명령어를 사용할때 아래와 같이 내용이 변경되는 것도 가능합니다 :)
이른바 한글 패치를 만들수도 있다는 거지요!

pm2

<변경전 결과화면>
Usage: pm2 [options] <command>
    :

<변경후 결과화면>
사용방법: pm2 [options] <command>
    :

 


pm2 로 백그라운드 실행

 

이제 지난 소스를 백그라운드 모드로 실행해보겠습니다.
소스가 들어 있는 폴더로 이동한 다음에,

cd /home/nodejs1/

 

아래명령을 실행합니다.

pm2 start main.js

 

그러면 아래와 비슷한 결과 화면이 보이실텐데요.
지난번과 다르게 계속해서 리눅스 명령 프롬프트를 사용할 수 있습니다.

 

이 것으로 node.js 의 백그라운드 실행이 완료되었습니다.
어디 한번 SSH 프로그램을 아예 닫아버리고 확인해보도록 할까요?

AWS 에서 퍼블릭IP 주소를 확인해서 웹브라우저에서 "퍼블릭IP주소:8080"으로 접속하면 된다고 했었지요?


아래와 같이 웹페이지가 노출된다면 정상입니다.

 


pm2 서버 재시작/중지

 

이 것으로 백그라운드 실행은 되었습니다만,
만일 서버 소스를 수정할 경우에는 pm2 서비스를 다시 시작해주어야 하는데요.

PHP와 같은 웹서버와는 달리 node.js 는 한번 작동중인 스크립트는 기본적으로 변경된 내용을 다시 불러오지 않기 때문입니다.
( 물론 해결책은 있습니다. )

만일 main.js 소스를 아래와 같이 수정했다면 이 수정사항은 실시간으로 반영되지 않습니다.

var http = require('http');

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'});
  res.end('안녕! Node.js 행복한 시간!');
}).listen(8080);

 

그래서 서비스를 재시작해주어야 하는데요.
아래 명령을 이용하면 서비스 재시작이 가능합니다.

pm2 restart main

 

"엇, main.js 로 타이핑해야 하는데 오타 아닌가요?"

main 도 되고 main.js  도 됩니다.
pm2 매니저는 main.js 를 실행하면서 뒷 부분의 js 를 떼버리고 main 이라는 이름으로 서비스명을 등록하는데요.

아래 명령어를 사용하면, pm2 매니저에 등록된 서비스 목록을 보실수가 있지요.

pm2 list

 

그렇기 때문에 서비스를 재시작할 때는 main 만 타이핑해도 되는 것입니다.
물론 아래와 같이 사용해도 오류  없이 잘 작동합니다.

pm2 restart main.js

 

소스 수정과 서비스 재시작이 완료된 이후 웹페이지를 다시 갱신해보면 아래와 같이 변경된 것을 확인하실 수 있습니다.

 

만일 웹서비스를 중지하려면 아래와 같이 명령어를 내려주시면 되는데요.

pm2 stop main

 

결과창의 status 항목을 확인하면 서비스가 살아있나 죽어있나를 확인하실 수 있습니다.
살아있으면 online, 죽어 있으면 stopped 로 표시됩니다.

 


pm2 에서 웹소스 폴더 이동이 안되요! 버그가 있나?...

이제 두번째 작업을 하고 싶어서 /home/nodejs1/ 폴더의 내용은 그대로 두고,
/home/nodejs2/ 폴더에 main.js 파일을 복사하고 소스를 수정했다고 가정해 봅시다.

서비스를 우선 중지하고 폴더를 이동하여 서비스를 시작해보면
웬걸? 실행은 되긴 하지만 생각처럼 되지 않는 것을 알 수 있습니다.

pm2 stop main
cd /home/nodejs2/
pm2 start main.js

금방 수정한 소스가 아닌 원래 /home/nodejs1 폴더의 소스에 의한 웹페이지가 작동하는 문제를 볼 수 있는데요.
이 것 떄문에 매우 혼동을 겪을수 있습니다.

pm2 는 독특한 특징을 가지고 있습니다.
pm2 로 한번 서비스를 시작하면 해당 폴더를 서비스명이 연결하여 기억하기 때문에
다른 폴더로 이동하여, 무언가를 하려고 해도 원래폴더의 소스가 실행이 됩니다.
AWS 가상 서버 자체를 껐다 켜기 전까지는요.

pm2 에서 서비스명의 상세 정보를 보시려면 아래 명령을 내려주시면 됩니다.

pm2 show main

<결과화면 예시>
┌───────────────────┬─────────────────────────────────────────┐
│ status            │ stopped                                 │
│ name              │ main                                    │
│ namespace         │ default                                 │
│ version           │ N/A                                     │
│ restarts          │ 5                                       │
│ uptime            │ 0                                       │
│ script path       │ /home/nodejs1/main.js                   │
│ script args       │ N/A                                     │
│ error log path    │ /home/ec2-user/.pm2/logs/main-error.log │
│ out log path      │ /home/ec2-user/.pm2/logs/main-out.log   │
│ pid path          │ /home/ec2-user/.pm2/pids/main-0.pid     │
│ interpreter       │ node                                    │
│ interpreter args  │ N/A                                     │
│ script id         │ 0                                       │
│ exec cwd          │ /home/nodejs1                           │
│ exec mode         │ fork_mode                               │
│ node.js version   │ 14.17.5                                 │
│ node env          │ N/A                                     │
│ watch & reload    │ ✘                                       │
│ unstable restarts │ 0                                       │
│ created at        │ 2021-08-14T13:29:50.812Z                │
└───────────────────┴─────────────────────────────────────────┘
 Divergent env variables from local env
┌────────────────┬──────────────────────────────────────────────────────────────────────────────┐
│ XDG_SESSION_ID │ 4                                                                            │
│ SSH_CLIENT     │ 211.209.204.105 14385 22                                                     │
│ PWD            │ /home/nodejs1                                                                │
│ SSH_CONNECTION │ 211.209.204.105 14385 172.31.6.54 22                                         │
│ OLDPWD         │ /home/ec2-user/.nvm/versions/node/v14.17.5/lib/node_modules/pm2/lib/binaries │
└────────────────┴──────────────────────────────────────────────────────────────────────────────┘

 Add your own code metrics: http://bit.ly/code-metrics
 Use `pm2 logs main [--lines 1000]` to display logs
 Use `pm2 env 0` to display environment variables
 Use `pm2 monit` to monitor CPU and Memory usage main

 

무언가 대단히 긴 내용을 보여주고 있는데요.
여기서 script path 라는 부분을 보시면, /home/nodejs1/main.js 라는
스크립트 파일 위치가 기록되어 있는 것을 보실 수 있습니다.

 

이 위치를 기억하고 있기 때문에 이를 해제해주지 않으면 main 이라는 서비스는 어느 폴더에서 실행하던 간에 처음 등록한 폴더의 스크립트만 무조건 실행됩니다.

pm2 의 서비스를 헤제하는 명령은 아래와 같습니다.

pm2 delete main.js

(결과화면>

그리고 이어서 다른 폴더에서 작업을 진행해주시면 무난~ 하게 되실 겁니다.


pm2 의 다중 서비스 ( 멀티 포트 )

 

좀 더 알고 싶으시면 이 글도 참조해주시면 도움이 될것 같습니다.
pm2 는 2개 이상의 다른 서비스를 등록할 수 있습니다.

소스를 아래와 같이 2개로 구성했다고 합시다.
main.js 는 8080 포트에서 서비스하고, main2.js 는 8081 포트에서 서비스를 합니다.

main.js

var http = require('http');

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'});
  res.end('안녕! Node.js 행복한 시간!--');
}).listen(8080);

main2.js

var http = require('http');

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'});
  res.end('안녕! Node.js 건강한 마음!--');
}).listen(8081);

 

이 때 main 과 main2 는 명칭이 다르기 때문에 pm2 에서 2개 모두 운영이 가능합니다.
아래와 같이 2개 모두 서비스에 등록한 다음에,

pm2 start main.js
pm2 start main2.js

 

pm2 에서 프로세스 조회를 해보면 2개의 서비스 목록이 확인됩니다.

pm2 list

각각의 서비스명이 다를 경우 이렇게 동시 등록이 가능한 것이지요.

 

지난 게시글 내용을 참조하여 AWS 에서 8081 포트도 마져 열어준다면,


퍼블릭IP주소:8080 주소로 접속할 경우 main.js 의 결과 내용이 출력되고


퍼블릭IP주소:8081 주소로 접속할 경우 main2.js 의 결과 내용이 출력됩니다.


pm2 자동 시작?

pm2 의 서비스 내역은 서버컴퓨터를 종료했다 재시작하면 사라집니다.

pm2 매니저에서는 아래 명령어를 이용하면 설정사항 저장이 가능하다고 하지만 그렇게 해봐도,

pm2 save


AWS에서는 서버를 재시작해도 자동으로 서비스 목록이 올라오지 않습니다.

pm2 서비스 내역을 보관하려면 아래 명령을 내려주시면 됩니다.
그러면 서버 재시동시에도 자동으로 서비스가 올라옵니다.

pm2 save --force

오늘도 여기까지 읽어주셔서 감사합니다!

구독좋아요는 사랑입니다 :)


다음 스토리 : node.js with 모듈 | 모듈 설명

https://itadventure.tistory.com/433

 

node.js with module | 모듈 설명

지난 스토리에서는 node.js 를 실행했던 리눅스 터미널을 종료해도 계속해서 웹서버가 작동되게 하는 pm2 라는 백그라운드 실행에 대해 다루어 보았습니다. https://itadventure.tistory.com/432 node.js with pm.

itadventure.tistory.com