웹 개발
systemd 서비스에 WorkingDirectory를 적어야 했던 이유
systemd로 Node 앱을 띄울 때 상대 경로 파일을 못 찾아서 고친 설정 노트다.
로그에 나온 에러
Node 앱을 systemd 서비스로 등록했는데 로컬 실행에서는 문제없던 파일 읽기가 서버에서만 실패했다. 에러는 대략 이런 모양이었다.
Error: ENOENT: no such file or directory, open './data/config.json'
처음에는 파일 권한을 의심했다. ls -l로 봐도 파일은 있었고, 서비스 계정도 읽을 수 있었다. 놓친 부분은 실행 위치였다.
왜 터미널 실행과 달랐나
터미널에서는 프로젝트 폴더에 들어간 뒤 실행했다.
cd /srv/my-app
node server.js
하지만 systemd는 내가 생각한 폴더에서 실행해 주지 않는다. 앱 코드에 상대 경로가 있으면 현재 작업 디렉터리에 따라 결과가 달라진다.
수정한 유닛 파일
나는 서비스 파일에 WorkingDirectory를 명시했다.
[Unit]
Description=My Node App
After=network.target
[Service]
User=app
WorkingDirectory=/srv/my-app
ExecStart=/usr/bin/node server.js
Restart=always
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
변경 후에는 데몬 설정을 다시 읽고 상태를 확인했다.
sudo systemctl daemon-reload
sudo systemctl status my-app --no-pager
같이 확인한 항목
이 문제를 보면서 아래도 같이 점검했다.
ExecStart에 적은 Node 경로가 실제로 존재하는지- 서비스 계정이 프로젝트 폴더를 읽을 수 있는지
.env를 쓴다면EnvironmentFile경로가 맞는지- 로그가
journalctl -u 서비스명에 남는지
메모
상대 경로는 작은 프로젝트에서는 편하지만, 서비스로 띄우는 순간 실행 위치가 숨어 있는 의존성이 된다. 다음부터는 파일 경로를 다룰 때 WorkingDirectory를 정하거나, 코드에서 절대 경로 기준을 분명히 잡기로 했다.