Carryduo

Carryduo | ubuntu crontab을 이용한 pm2 로그 관리 스케줄링

차가운에스프레소 2023. 1. 25. 21:13

1. 개요

- Carryduo는 매일 약 25000개 이상의 롤 게임 데이터를 분석한다.

- 게임 데이터 분석에는 별도의 서버를 운영하고 있으며, 데이터 분석 과정은 로그로 꼼꼼히 모니터링한다.

- 데이터 분석은 개발 편의상 javascript로 작성하고, pm2를 이용해서 프로세스를 관리하고 있었는데, 다음과 같은 로그를 확인할 수 있었다.

서버에 더이상 로그를 작성할 용량이 없다는 로그

- 요컨대, 로그가 계속 누적되면서 더 이상 로그를 작성할 용량이 남아있지 않아, 서버에서 프로세스를 중단시킨 것이다.

- 의문이었다. 필자는 winston 라이브러리를 이용해서 일주일 간격으로 로그를 관리해주고 있었기 때문이다.

- 구글링을 해본 결과, pm2는 자체적으로 .pm2 -> logs 경로에 서버에서 기록되는 로그들을 모두 저장하고 있다는 것을 확인할 수 있었다.

- 즉, 필자가 winston으로 관리하는 것과는 별도로 게속 로그가 생성되고 있었던 것이다.

- 이를 해결하기 위해서는 두 가지 방법이 있을 것이다.

1. pm2 설정에서 로그 관련 설정을 변경한다.
2. 서버에서 자체적으로 pm2에서 작성하는 로그 또한 관리하도록 스케줄을 생성한다.

- 필자는 2번을 채택했다. 이유는 필자가 winston으로 관리하는 로그 이외에 프로세스에서 예기치 않게 발생할 수 있는 로그를 확인할 필요성을 조금이나마 느꼈기 때문이다.

- 이에, 2번 작업을 위해 ubuntu crontab을 이용하였다.

 

2. ubuntu crontab을 이용한 스케줄 생성(etc/crontab 직접 수정)

- ubuntu 환경에서 crontab은 cron 구조에 맞춰진 스케줄러라고 생각하면 된다. crontab에서 스케줄러를 생성하는 구조는 다음과 같다.

*   *   *  *  *      "유저" "명령어"
┬ ┬ ┬ ┬ ┬
│ │ │ │ └─ 요일 (0 - 6) (0:일요일, 1:월요일, 2:화요일, …, 6:토요일)
│ │ │ └─ 월 (1 - 12)
│ │ └─일 (1 - 31)
│ └─ 시 (0 - 23)
└─ 분 (0 - 59)

cf) * 는 매일, 매분, 매시 등을 의미한다.
cf) */n은 n의 간격만큼의 시, 분을 의미한다. 예컨대, */1은 1분마다, 1시간마다를 의미할 수 있다.

- 요컨대, "1시간마다 a라는 유저로 app.js를 실행한다"라는 스케줄을 등록한다면 다음과 같이 crontab을 작성할 수 있을 것이다.

0 */1 * * * a node app.js

- 한편, pm2에서 로그를 삭제시키는 명령어는 다음과 같다.

pm2 flush

- 위 내용을 종합하여, 필자는 우분투 계정으로 매주 월요일 자정에  pm2 로그를 삭제시키는 스케줄을 다음과 같이 등록했다.

0 0 * * 1 ubuntu pm2 flush

- 이를 통해, pm2에서 무기한 누적되는 로그에 따라 서버에서 프로세스가 갑작스레 중단되는 문제를 해결했다.

 

- 하지만 위 방법은 경우에 따라서 등록한 crontab 스케줄이 실행되지 않는다고 한다. 그 이유 중 하나는 crontab에 생성한 schedule은 /var/spoll/cron/crontab 경로에 crontab을 실행할 계정 명의로 예정된 스케줄이 명시된 파일이 생성되어야 하는데, 그렇지 않기 떄문인 것으로 추론된다.

3. ubuntu crontab 생성하기(crontab 명령어 이용)

1) crontab 스케줄 생성과 관련한 명령어와 crontab 로그 조회 경로

crontab -e (현재 계정으로 crontab 스케줄 생성 및 편집)
crontab -l (현재 계정으로 등록된 crontab 스케줄 조회)
crontab -r (현재 계정으로 등록된 crontab 스케줄 삭제)
service cron start/restart (crontab 실행/재실행)
service cron status(crontab 상태 조회)

/var/spool/cron/crontabs/계정 (계정 명의로 등록된 스케줄이 저장된 파일 경로, 관리자 권한으로 접근 가능)
/var/log/syslog (system에서 실행하는 cron 스케줄러들에 대한 로그)
/var/spool/mail/계정 (cron 실행에 대한 메일 발송 여부를 선택했을 경우 확인 가능한 로그)

2) crontab 명령어를 이용해 crontab 스케줄러를 생성하는 과정


1. crontab -e (crontab 편집)

2. 편집기 선택(필자는 easiest를 선택했다)

3. 실행할 명령어에 대한 sh 파일 생성

- crontab 명령어를 이용해 스케줄링을 할 경우에는, sh 파일을 이용하는 것이 보편적이라고 한다.

- sh 파일 실행을 위해, 파일에 실행 권한을 부여한다.

chmod +x <sh파일의 경로>

4. 편집창에서 crontab 설정하고 저장하기

- nano 파일에서는 ctrl + O = 저장, ctrl + x = 나오기 이다.

30 * * * *  <sh파일의 경로>

5. crontab 재실행하기

service cron restart (루트 계정이 아닌 경우, 비밀번호 요구됨)

3) crontab 사용 시 유의 사항

(1) sh 파일 실행권한 부여

- 위에서 언급한 바와 같이, sh 파일을 통해 실행할 명령어를 주입하는 경우, 해당 파일에 대한 실행 권한을 부여해야한다.

(2) 메일 관리자

- crontab -e 명령어를 사용해 스케줄러를 등록하는 경우, default로 메일 관리자를 요구한다. 메일 관리자가 서버에 별도로 존재하지 않는다면, 다음과 같은 cron 에러 메시지를 확인할 수 있다.

(CRON) info (No MTA installed, discarding output)

- 이를 해결하는 방법은 크게 두 가지이다. 1) postfix와 같은 메일 관리자를 설치한다. 2) crontab에서 메일 관리자 설정을 변경한다.


[1] postfix 설치

- 다음 명령어로 postfix를 로컬 경로로 설치해주면, 위와 같은 에러 메시지가 확인되지 않고, crontab이 실행되는 것을 확인할 수 있다.

- 아울러, var/spool/mail/계정 경로에서 mail 발송 여부와 cron에 대한 로그를 확인할 수 있다.

apt-get install postfix

[2] crontab 스케줄에서 메일 관리자 설정 변경

- crontab -e  편집기에서 맨 첫번째 줄에 MAILTO = ""를 기입해주면, 메일 관리자 설정을 해제할 수 있다.

- 이 경우, crontab의 로그는  var/log/syslog를 통해 확인하면 되는데, 이 로그의 관리는 기본적으로 /etc/crontab.conf , /etc/crontab.d 에서 관리되고 있음을 확인할 수 있었다.


- 필자는 [2] 방법을 채택했다. 왜냐하면, 실제로 메일 전송 서비스가 필요하지 않았으며, var/spool/mail/계정 경로에 로그가 쌓이는 것이 부담되었기 때문이다. 어차피 로그는 var/log/syslog에 기록이 되기 때문이다.

(3) pm2 명령어의 경로

- 최초에 sh 파일을 작성할 시, 필자는 다음과 같이 작성했다. 그리고 다음 에러를 확인했다.

pm2 flush handler (handler 라는 프로세스의 pm2 로그 파일을 삭제)
// pm2 command not found

- sudo 경로로 실행할 경우에는 command not found 에러가 발생하지 않으나, flush를 실행하는 경로가 의도한 대로 나타나지 않았다. 필자가 실행하는 pm2는 root 권한이 아니라 ubuntu 권한에서 실행되고 있었기 떄문이다.

- 이에, sudo 권한이 아닌 상태에서 pm2 명령어를 실행하고자 하였는데, 이는 명령어를 다음과 같이 작성함으로써 해결했다.

whereis pm2 (pm2가 설치된 경로 확인)
/usr/local/bin/pm2 flush (확인된 경로로 pm2 명령어 실행)

- 에러가 발생한 까닭은 단순히 pm2라고 하면, shell 입장에서 해당 pm2가 어떤 것인지 그 경로를 찾을 수 없기 때문이라고 한다.

 

4. 참고자료

- ubuntu crontab을 이용한 스케줄러 생성