꿈꾸는 시스템 디자이너

Lightsail 사용법 - npm forever 사용법 | How to use npm forever 본문

Development/Cloud computing

Lightsail 사용법 - npm forever 사용법 | How to use npm forever

독행소년 2020. 4. 9. 15:35

 

지난 강좌에서는 nodemon을 이용해서 실시간으로 디버깅과 테스트를 수행하는 방법에 대해서 알아보았다. nodemon으로 Node.js 어플리케이션을 실행하면 해당 디렉토리의 파일의 변화를 자동 감지해서 어플리케이션이 자동 재실행되게 된다.

 

이번 강좌에서는 Node.js 어플리케이션을 백그라운드 데몬으로 실행하는 방법에 대해서 알아본다.

 

1. forever 설치

설치한 우분투 인스턴스로 SSH 접속을 한 후 npm 명령어를 이용해서 golbal하게 forever를 설치한다.

$> sudo npm install forever -g

 

2. forever start

지난 강좌에서 개발했던 helloworld 디렉토리로 이동한 후, forever를 이용해서 Node.js 어플리케이션을 백그라운드 데몬으로 실행해 보자.

$> sudo forever start index.js

forever로 Node.js 어플리케이션을 실행시키는 위해서는 forever start 명령어를 이용한다.

sudo를 이용해서 forever를 실행하는 이유는 helloworld 어플리케이션에서 사용하는 80번 포트가 root 계정에서만 접근이 가능하기 때문이다.

 

실행화면은 다음과 같다.

ubuntu@ip-172-26-10-140:~/helloworld$ sudo forever start index.js
warn:    --minUptime not set. Defaulting to: 1000ms
warn:    --spinSleepTime not set. Your script will exit if it does not stay up for at least 1000ms
info:    Forever processing file: index.js
ubuntu@ip-172-26-10-140:~/helloworld$

 

그럼 웹브라우저를 통해 인스턴스에 접속해보자.

 

잠깐 위의 forever 실행화면을 살펴보자. forever로 helloworld 어플리케이션이 실행된 후 다시 프로포트가 나타난다. 이는 forever가 어플리케이션을 백그라운드 데몬으로 실행했기 때문이다. 이 순간부터는 SSH 접속을 종료해도 어플리케이션이 종료되지 않고 지속적으로 서비스를 제공한다. 서버 다운 서비스를 제공한다는 것이다.

 

3. forever list

forever list를 이용하면 forever를 통해 실행되어 동작 중인 백그라운드 데몬의 정보를 확인할 수 있다.

$> sudo forever list

 

실행화면은 다음과 같다.

ubuntu@ip-172-26-10-140:~/helloworld$ sudo forever list
info:    Forever processes running
data:        uid  command             script   forever pid  id logfile                        uptime
data:    [0] BUFc /usr/local/bin/node index.js 1456    1462    /home/ubuntu/.forever/BUFc.log 0:0:0:29.058
ubuntu@ip-172-26-10-140:~/helloworld$

현재 1개의 forever 프로세스(백그라운드 데몬)이 실행 중이며, 식별번호는 0번, uid는 BUFc, 명령어는 nodemon, 실행중인 script는 index.js라는 것을 확인할 수 있다. 추가로 logfile의 위치와 uptime(경과시간)도 확인이 가능하다.

 

우선 한가지 확인하고 넘어가자. 위 실행을 위해 sudo 명령어를 이용했는데, forever는 sudo 명령어를 사용할 때와 하지 않을 때를 구분한다. 즉 sudo를 이용하지 않고 forever list를 명령하면 다음과 같이 root 권한이 아닌 일반 사용자 권한으로 실행된 프로세스의 정보만 반환한다.(실행한 적이 없으므로 동작중인 프로세스도 없다.)

ubuntu@ip-172-26-10-140:~/helloworld$ forever list
info:    No forever processes running
ubuntu@ip-172-26-10-140:~/helloworld$

 

4. forever stop

forever stop을 이용하면 forever로 실행한 프로세스를 종료할 수 있다. 서버를 정지시키는 기능이다. 다음과 같이 종료할 프로세스의 식별 번호를 부여한다.

$> sudo forever stop 0

 

실행화면은 다음과 같다.

ubuntu@ip-172-26-10-140:~/helloworld$ sudo forever stop 0
info:    Forever stopped process:
    uid  command             script   forever pid  id logfile                        uptime
[0] BUFc /usr/local/bin/node index.js 1456    1462    /home/ubuntu/.forever/BUFc.log 0:0:1:32.92400000000001
ubuntu@ip-172-26-10-140:~/helloworld$ sudo forever list
info:    No forever processes running
ubuntu@ip-172-26-10-140:~/helloworld$

종료 후 다시 list를 조회하니 실행 중인 프로세스가 없음이 확인되었다.

 

자 그럼 실제 hellowrold 어플리케이션이 종료되었는지 웹브라우저를 통해 인스턴스에 접속해보자. 서버가 종료되어 사이트에 연결할 수 없음이라는 메시지가 출력되고 있다.

 

5. forever를 이용한 실시간 디버깅과 테스트

지난 강좌에서 nodemon을 이용해서 소스크도를 실시간 디버깅하면서 웹브라우저를 통해 테스트도 진행했었다. forever를 이용해서 어플리케이션을 백그라운드 데몬으로 동작시키면서 실시간 디버깅과 테스트를 하려면 forever start 단계에서 -w 옵션을 추가해야 한다. -w 옵션은 파일의 변화를 감지해서 어플리케이션을 재실행하여 nodemon과 동일한 효과를 제공한다.

$> sudo forever start -w index.js

 

Cloud9을 실행해서 소스코드를 수정해보자.

var http = require('http');  

http.createServer(function (req, res) {
	res.writeHead(200, {'Content-Type': 'text/plain'});
	res.end('Hello World! Happy World!\nMy World!'); // add Happy World! and My World!
}).listen(80);

 

파일을 저장한 후 인스턴스에 다시 접속해보면, 수정된 내용이 실시간으로 반영되는 것을 확인할 수 있다.

 

6. forever 프로세스에 이름부여

어플리케이션을 forever로 start할 때 마다 임의의 이름(uid)가 부여된다. 프로세스에 이름을 부여하고자 할 땐 --uid 옵션을 이용한다.

$> sudo forever start --uid hello -w index.js

 

실행화면은 다음과 같다. uid 항목에 hello라고 명명한 이름이 출력되고 있다.

ubuntu@ip-172-26-10-140:~/helloworld$ sudo forever start --uid hello -w index.js
warn:    --minUptime not set. Defaulting to: 1000ms
warn:    --spinSleepTime not set. Your script will exit if it does not stay up for at least 1000ms
info:    Forever processing file: index.js
ubuntu@ip-172-26-10-140:~/helloworld$ sudo forever list
info:    Forever processes running
data:        uid   command             script   forever pid  id logfile                         uptime
data:    [0] hello /usr/local/bin/node index.js 1639    1649    /home/ubuntu/.forever/hello.log 0:0:0:8.042
ubuntu@ip-172-26-10-140:~/helloworld$

 

프로세스를 종료할 때 식별번호 외에도 프로세스의 uid도 이용할 수도 있다. hello라고 명명했음으로 다음과 같이 프로세스를 종료할 수 있다.

ubuntu@ip-172-26-10-140:~/helloworld$ sudo forever stop hello
info:    Forever stopped process:
    uid   command             script   forever pid  id logfile                         uptime
[0] hello /usr/local/bin/node index.js 1639    1649    /home/ubuntu/.forever/hello.log 0:0:1:48.215
ubuntu@ip-172-26-10-140:~/helloworld$ sudo forever list
info:    No forever processes running
ubuntu@ip-172-26-10-140:~/helloworld$

 

실제 서버를 개발할 때 여러개의 forever 프로세스들이 동작하게 되는 경우가 발생한다. 식별번호는 생성 순서로 부여되고 uid도 랜덤하게 부여되어 종료하고자 하는 프로세스를 확인하기 불편한 경우가 발생하는데 이렇게 프로세스에 이름을 부여하면 혼란을 방지할 수 있다. 또한 로그파일을 관리할 때에도 유용하다.

 

 

7. forever 로그 관리

forever list나 stop를 실행하면 logfile항목에서 해당 프로세스의 로그파일의 경로를 확인할 수 있다. forever로 실행되는 모든 프로세스들은 사용자영역의 .forever 디렉토리에 저장된다. 숨김폴더로 되어 있으므로 ls -all을 해야 보인다.

 

우선 --uid 옵션으로 hello라고 명칭하고 다시 forever start를 시도하면 다음과 같은 에러가 발생한다.

ubuntu@ip-172-26-10-140:~/helloworld$ sudo forever start --uid hello -w index.js
warn:    --minUptime not set. Defaulting to: 1000ms
warn:    --spinSleepTime not set. Your script will exit if it does not stay up for at least 1000ms
info:    Forever processing file: index.js
error:   Cannot start forever
error:   log file /home/ubuntu/.forever/hello.log exists. Use the -a or --append option to append log.

 

이는 이미 같은 이름의 로그파일이 .forever 디렉토리에 존재하기 때문이며 -a 나 --append 옵션을 추가해서 기존 로그파일에 로그를 이어서 저장하도록 하거나 기존의 hello.log 파일을 삭제한 후 시도해야 한다.

$> sudo forever start -a --uid hello -w index.js

 

소스코드를 다음과 같이 수정한 후 저장하자.

var http = require('http');  

console.log("::: start HelloWorld Application :::");
console.log(Date().toString());

http.createServer(function (req, res) {
	console.log("\n:: new request::")
	console.log(Date().toString());
	res.writeHead(200, {'Content-Type': 'text/plain'});
	res.end('Hello World! Happy World!\nMy World!'); // add Happy World! and My World!
	
}).listen(80);

helloworld 어플리케이션이 실행될 때 로그를 한번 출력하고, 인스턴스 접속이 요청될 때마다 로그를 출력하도록 수정한 것이다.

 

파일을 저장하고 인스턴스에 몇번 접속해 본 후 로그파일을 확인해 보자.

ubuntu@ip-172-26-10-140:~/.forever$ cat hello.log
error: Could not read .foreverignore file.
error: ENOENT: no such file or directory, open '/home/ubuntu/helloworld/.foreverignore'
::: start HelloWorld Application :::
Thu Apr 09 2020 05:57:18 GMT+0000 (UTC)

:: new request::
Thu Apr 09 2020 05:57:32 GMT+0000 (UTC)

:: new request::
Thu Apr 09 2020 05:57:32 GMT+0000 (UTC)
error: Forever detected script was killed by signal: SIGKILL
error: Could not read .foreverignore file.
error: ENOENT: no such file or directory, open '/home/ubuntu/helloworld/.foreverignore'
::: start HelloWorld Application :::
Thu Apr 09 2020 06:03:44 GMT+0000 (UTC)

:: new request::
Thu Apr 09 2020 06:04:37 GMT+0000 (UTC)

:: new request::
Thu Apr 09 2020 06:04:37 GMT+0000 (UTC)

:: new request::
Thu Apr 09 2020 06:22:47 GMT+0000 (UTC)

:: new request::
Thu Apr 09 2020 06:22:48 GMT+0000 (UTC)

:: new request::
Thu Apr 09 2020 06:22:48 GMT+0000 (UTC)

:: new request::
Thu Apr 09 2020 06:22:48 GMT+0000 (UTC)
ubuntu@ip-172-26-10-140:~/.forever$

 

.forever 디렉토리의 모든 로그파일을 삭제하고 할 때에는 cleanlogs 명령을 이용하면 된다.

ubuntu@ip-172-26-10-140:~/.forever$ ls
2oEA.log  6kJY.log  EMP-.log  L2rx.log  T-0N.log  config.json  oNUE.log  r6tR.log  z8Co.log
2pf-.log  78ME.log  FYH6.log  P5b9.log  WgGt.log  hVb7.log     pb-3.log  sock      z8IB.log
5SoP.log  BUFc.log  HW.log    QP6i.log  YAEA.log  hello.log    pids      xRRe.log
5SsO.log  D70J.log  IAPx.log  SoGg.log  bwKh.log  mv0N.log     r1ZQ.log  xf4O.log
ubuntu@ip-172-26-10-140:~/.forever$ forever cleanlogs
ubuntu@ip-172-26-10-140:~/.forever$ ls
config.json  pids  sock
ubuntu@ip-172-26-10-140:~/.forever$

 

자 정리할 시간다.

forever를 이용하면 Node.js 어플리케이션을 백그라운드 데몬으로 안정적으로 실행/종료시킬 수 있다.

-w 옵션을 이용하면, nodemon을 이용했을 때 처럼 실시간으로 디버깅과 테스트를 진행할 수 있다.

-uid 옵션을 이용하면, 프로세스에 이름을 부여할 수 있으며, 이 이름으로 로그파일이 저장된다.

-a 옵션을 이용하면 기존의 로그파일에 이어서 로그가 추가된다.

 

추가로 지난 강좌에서 설치했던 Cloud9을 forever로 실행하는 예제는 다음과 같다.

$> forever start -a --uid cloud9 server.js -w /home/ubuntu/helloworld/ -l 0.0.0.0 -p 9002 -a test:test1234

 

다은 시간에는 실시간으로 로그파일을 확인하는 방법에 대해서 알아본다.

 

 

 

Comments