본문 바로가기

Etc

윈도우, 리눅스에서 서버 재부팅시 프로그램 자동실행 설정하기 (feat. next.js)

728x90

이번에 윈도우, 리눅스 등 모든 서버에서 재부팅 시 프로그램이 자동으로 실행되도록 설정했다.

기존에는 pm2로 관리를 했었는데, 서버가 꺼질 때마다 수동으로 프로그램을 시작해줘야 했다. 

 

서버가 꺼질때마다 다시 시작하는 것도 귀찮았는데, 꺼졌다는 걸 인지하지 못했을 때 오는 민원 전화가 더 무서웠다🥲

그래서 이러한 상황을 방지하기 위해 자동실행 설정을 시작했다. 

그 과정을 고생한거 정리할 겸 기록 겸으로 블로그에 작성한다.

 

우선은 윈도우부터!

윈도우는 nssm을 이용해 배치파일을 서비스에 등록하는 방법을 사용했다. 

 

바쁜 분들은 성공과정으로 고고 > 정리 부분 보면 됨  

 

 

1. Window

1) 실패 과정 

이전 프로젝트 했을 당시, window 서버에서 nssm을 통해 자동 실행을 등록했었다.

그래서 이번에도 nssm을 사용했다. 

 

처음엔 nssm을 설치하고 next.js 파일 자체를 실행하려 했다.

이전 프로젝트에서도 비슷한 경험이 있어서 똑같이 하면 될 줄 알았다. 

 

첫 시도는 성공!

그런데 운영이 아닌 개발 버전으로 실행됐다.

찾아보니까 환경변수 설정이 안 되어 있어서 그랬다. 

 

 

nssm set <servicename> AppEnvironmentExtra JAVA_HOME=C:\java
> 
nssm set app AppEnvironmentExtra NODE_ENV=production

 

nssm 홈페이지 가니까 위 방법으로 환경변수가 설정 가능하다길래 production 모드로 설정해 줬다.

적용 후 실행하니 운영으로 열리긴 했다. 

그런데 에러를 동반한.. 

 

찾아보니 npm run build를 안 해서 난 에러였다. 

그래서 다시 npm run build를 하고 재실행했더니 제대로 실행됐다!!

 

이렇게 끝인 줄 알았지만, 컴퓨터 껐다가 켜보니까 인터넷 서버 에러가 발생했다..

그렇지 이렇게 간단히 끝날 리가 없지 싶었다. 

 

 

- 인터넷 서버 에러

 

서버 재시작할 때마다 인터넷 서버 에러가 발생했다.

에러 내용을 자세히 보니까 내부에서 에러가 난 것 같았다

 

서비스 끄고 npm start 해보니 다시 next build를 하라는 에러가 발생했다ㅠ

아니 분명 이전에 했는데 또.. 

어쨌든 하라 해서 하고 npm start 하니 다시 잘 실행됐다.

다시 서비스 끄고 시작하니 또 성공!

 

그런데 재부팅하니 또 똑같은 에러가 발생했다.

재부팅할 때마다 build하고 실행되도록 해봐야겠다는 생각이 들었다. 

 

 

 

- 재부팅할 때마다 빌드되도록 수정

 

next build는 node_modules > ./bin > next 에서 실행된다. 

 

nssm set app AppParameters C:\Users\...\node_modules\.bin\next build && C:\Users\...\server\app.js
Set parameter "AppParameters" for service "app".

 

그래서 위 명령어를 통해 build 한 후 프로그램이 실행되도록 수정했다. 

처음에 실행했을 땐 제대로 켜졌는데 다시 시작하니까 에러가 발생했다..

 

에러를 확인하니까 build 에러였다

이때부터 매우 당황하기 시작했지만 침착하게 서버 재부팅을 했다. 

그러니까 다시 잘됨.. 

 

하지만 에러가 났다 안 났다 하기 때문에 이 방법으로 실행하면 안 된다고 생각했다.

그래서 찾아본 방법이 배치파일을 활용한 것이었다

 

 

 

- 배치파일 활용

 

서버 재부팅 시 자동 실행 작업을 하기 전까지는 배치파일이 뭔지도 몰랐다.

폭풍 구글링과 질문을 통해 배치파일이 있다는 걸 알게 되었다. 

배치파일이 뭔지는 하단 "2) 정리" 부분에 적어놓겠다. 

 

cd C:\Users\...
npm start

 

배치파일을 활용해서 실행하는 건 진짜 간단했다.

우선 배치파일에 프로그램 실행 명령어를 적어놓는다.

그 후 nssm을 통해 서버가 꺼지면 배치파일이 자동으로 실행되도록 하면 된다.

 

진짜 뻥 안 치고 10번 넘게 서버 재부팅해봤는데 에러가 하나도 안 났다.

드디어 성공..

눈물의 성공..

 

이 방법으로 다른 window 서버에 있는 프로그램들도 자동으로 실행되도록 수정했다. 

 

 

 

2) 정리 - 성공 과정

-  배치파일 생성

cd C:\Users\project\test
npm start

 

Notepad와 같은 텍스트 에디터를 열어서 배치 명령어를 작성해 준다.

말 그대로 프로젝트를 실행할 때 사용하는 명령어를 입력해 주면 된다.

 

우선 해당 프로젝트로 이동해야 하기 때문에 프로젝트 경로 이동 명령어를 써준다.

예를 들어 해당 프로젝트가 C:\Users\project\test에 있다면 cd C:\Users\project\test를 적어준다.

그 후, 프로젝트에서 시작할 명령어를 써준다.

npm start로 프로그램을 실행하기 때문에 그대로 적어줬다.

 

*배치파일이란

 

윈도우 배치파일은 명령어를 포함하고 있는 텍스트 파일을 말한다.

배치파일을 실행시키면, 안에 있던 명령어들이 windows 커맨드 프롬프트에서 순차적으로 실행된다. 

 

.bat 혹은 .cmd 확장자를 가지고 있으며, 보통 사용자가 반복적으로 실행해야 하는 작업을 자동화할 때 주로 사용한다.

단순 파일 복사부터 복잡한 자동화 스크립트까지 다양한 작업을 수행할 수 있다. 

 

텍스트 에디터를 사용하며, 각 줄에는 하나의 명령어가 들어간다. 

해당 명령어 = window 커맨드 명령어라고 생각하면 된다. 

 

 

- 서비스 등록(NSSM) 

 

우선, NSSM 홈페이지에서 파일을 설치해 준다.

위 사진을 클릭하면 바로 다운로드 사이트로 이동한다.

 

 

*NSSM이란

 

윈도우에서 서비스를 관리할 때 사용하는 도구이다.

nssm을 통해 사용하는 어떤 실행 파일도 windows 서비스로 설치하고 관리할 수 있다.

 

 

nssm.exe install serviceName

 

nssm.exe가 설치된 곳으로 이동한 후, install 명령어를 이용해 서비스를 생성해 준다.

serviceName에는 우리가 설정할 서비스 이름을 넣어주면 된다. 

 

 

 

그럼 위와 같이 NSSM editor가 뜰 것이다.

 

Path에 우리가 실행할 배치파일 위치를 넣어주고, Startup directory에 배치파일이 있는 폴더 위치를 넣어준다.

그 후 Edit service를 클릭해 준다.

 

 

nssm start serviceName

 

제대로 저장되었으면, start 명령어를 통해 우리가 만든 서비스를 시작시켜 주면 된다.

 

 

nssm edit serviceName

 

만일 수정사항이 있다면 edit 명령어를 통해 nssm editor를 다시 꺼낼 수 있다.

 

 

nssm set [serviceName] [parameter] [value]

 

editor가 아니라 명령어로 수정하고 싶다면 위처럼 set을 사용하면 된다. 

 

이제 시작 > 서비스에 들어가서 확인해 보면, 우리가 등록한 서비스를 확인할 수 있다. 

 

 

 

2. 리눅스 

마찬가지로 실패과정, 성공과정 따로 적는다.

자세한 설명과 정리는 성공과정에 있으니 바쁜 분들은 바로 성공과정으로 가면 된다!

 

 

1) 실패 과정

리눅스에서는 systemctl를 통해 작업을 진행했다.

 

sudo nano /etc/systemd/system/myapp.service

 

 

우선 서비스 설정 파일을 생성했다. 

그리고 그 안에 파일 내용을 적어놓고 "sudo systemctl start myapp" 명령어를 통해 실행했다.

enable 명령어를 통해 부팅 시 자동으로 실행되도록 설정도 마쳤다.

 

Failed to enable unit: Invalid argument

 

 

그러나 역시나 기대를 저버리지 않고 에러가 발생했다.

 

"sudo systemctl status myapp"을 통해서 확인해 봤더니 에러 나는 부분이 없었다. 

 재부팅해보니 자동으로 실행되지도 않았다. 

 

systemctl is-enabled display

 

위 명령어를 통해 자동 설정이 되어 있는지 확인해 보니 "disabled"가 떴다

설정이 안 되어 있었다는 거다ㅎ

 

다시 설정 파일을 확인해 봤다.

역시나!!! 스펠링이 틀렸다ㅋㅋㅋㅋㅋㅋㅋ

 

WantedBy=multi-user.target 가 WantedBy=multi-user.targe 으로 되어 있었던 거다..

진짜 하루 꼬박 에러 찾다가 도저히 모르겠어서 설정파일 복붙하고 gtp한테 뭐가 틀렸냐니까 알려줬다.

나는 t 하나 빼먹은 죄로 하루를 날린 거다.

 

쨌든 무사히 찾아서 수정하고 다시 실행했더니 짜잔!

Created symlink /etc/systemd/system/multi-user.target.wants/myapp.service → /etc/systemd/system/myapp.service.

 

드디어 성공 메시지가 떴다

재부팅해보니 자동으로 실행됐다!

 

혹시 몰라서 "systemctl is-enabled myapp" 명령어로 확인해 보니까 "enabled"가 떴다

드디어 성공 

 

 

 

2) 정리 - 성공 과정 

systemctl은 리눅스에서 시스템 및 서비스 관리를 할 때 사용하는 명령어이다.

이를 통해 서비스 시작, 중지 등을 설정할 수 있다. 

 

 

- 서비스 파일 생성

sudo nano /etc/systemd/system/myapp.service

 

sudo 관리자 명령어를 통해 service 파일을 생성한다. 

이때 nano는 텍스트 편집기 명령어로 다른 편집기를 사용해도 상관없다. 

 

서비스 설정 파일의 경로는 위와 똑같이 하되, 이름은 원하는 대로 지정할 수 있다.

다만 뒤에 .service를 붙여줘야 한다. 

 

 

[Unit]
Description=My Application Service  //서비스 설명

[Service]
ExecStart=/usr/bin/node server/app.js  //시작 명령
WorkingDirectory=/path/to/your/app  //프로그램이 위치한 디렉토리
Restart=always   //서비스 실패시 자동 다시 시작하도록 설정
User=root   //서비스 실행 사용자 지정
Environment=NODE_ENV=development   //env 설정 

[Install]
WantedBy=multi-user.target

 

이제 해당 파일을 편집하면 된다. 필자는 vim을 통해서 수정했다. 

 

[Unit]은 서비스의 설명과 동작을 [Service]는 서비스 실행과 관련된 세부 사항을 정의하는 부분이다.

[Install]은 서비스가 설치될 때 설정을 정의하는 부분이다. 

 

그중 ExecStart는 서비스 시작 시 실행할 명령어를 입력하는 공간이다.

여기서는 Node.js를 실행할 것이기 때문에 usr/bin/node에 있는 server/app.js를 실행히켜줬다. 

 

WantedBy는 서비스가 어느 대상에 연결될지 지정하면 된다.

multi-user.target을 입력하면 다중 사용자 모드로 부팅될 때 서비스가 시작된다. 

 

 

- 서비스 설정 적용 및 시작 

sudo systemctl daemon-reload  // systemd에 새로운 서비스 파일을 로드
sudo systemctl start myapp  // 서비스를 시작
sudo systemctl enable myapp  // 부팅 시 자동 실행되도록 설정

 

서비스 설정 파일을 수정했으면, systemctl daemon-reload를 통해 해당 파일을 다시 로드하도록 해준다.

그 후 start로 서비스를 시작하고, enable 명령어로 부팅 시 자동으로 서비스가 시작되도록 설정해 준다. 

 

Created symlink /etc/systemd/system/multi-user.target.wants/myapp.service → /etc/systemd/system/myapp.service.

 

해당 메시지가 뜨면 서비스가 성공적으로 실행되었다는 의미이다.

 

 

728x90