← 글 목록

라즈베리파이 알 수 없는 재부팅, systemd 좀비 서비스가 범인이었다

/ 6분 분량

라즈베리파이가 며칠 간격으로 이유 없이 재부팅되거나 전원이 내려가는 것처럼 멈추는 문제를 겪었습니다. journalctl 로그를 파고들어 원인을 찾아낸 과정을 정리합니다.

학습 주제

  • 주제: systemd 서비스 유닛 오류로 인한 라즈베리파이 반복 재부팅 문제 진단 및 해결
  • 날짜: 2026년 7월 18일

탐구 과정

집에서 돌리고 있는 라즈베리파이가 며칠 간격으로 알 수 없이 재부팅되거나, 전원이 내려간 것처럼 멈추는 증상이 있었습니다. 특정 작업을 하다 죽는 것도 아니고 그냥 시간이 지나면 재부팅되어 있어서 원인을 짐작하기 어려웠습니다.

일단 의심 가는 프로세스가 있는 게 아니라 "뭔가 계속 이상한 짓을 하는 서비스가 있을 것"이라는 감으로 시작했습니다. 그래서 journalctl로 전체 서비스 이력을 훑어서, 재시작 횟수가 비정상적으로 많은 유닛이 있는지부터 확인하기로 했습니다.

핵심 학습 내용

journalctl로 이상 유닛 찾아내기

전체 로그를 뒤져보니 learningetl.service("LearningETL Daemon - AI Chat Auto Collector")라는 유닛에서 Scheduled restart 로그가 하루에만 약 8,433번씩 찍혀 있었습니다. 단순 계산해보면 대략 10초에 한 번씩 재시작을 영구적으로 반복하고 있었던 셈이고, 보존된 저널 전체 기준으로는 실패 기록이 46만 번을 넘어 있었습니다.

실패 메시지를 확인해보니:

learningetl.service: Failed to load environment files: No such file or directory
learningetl.service: Failed to spawn 'start-pre' task: No such file or directory
learningetl.service: Failed with result 'resources'.

원인은 단순했습니다. 프로젝트 폴더가 예전에 /home/jcw/LearningETL이었다가 /home/jcw/LearningCollector_v1.0으로 이름이 바뀌었는데, systemd 서비스 파일의 EnvironmentFile이나 실행 스크립트 경로는 옛날 경로 그대로 남아 있었던 겁니다. 폴더가 사라진 뒤로 서비스가 트리거될 때마다 즉시 실패했고, Restart= 정책이 걸려 있어서 systemd가 절대 포기하지 않고 몇 달째 10초 간격으로 재시도를 반복하고 있었습니다.

같은 문제를 가진 두 번째 유닛

같은 패턴의 이름 불일치 문제가 하나 더 있었습니다. learningcollector-daily.service도 /home/jcw/LearningCollector/scripts/runtime/daily-collect.sh(역시 _v1.0이 빠진 옛 경로)를 가리키고 있어서, 매일 자정 타이머가 돌 때마다 203/EXEC No such file or directory로 실패하고 있었습니다.

재부팅 패턴과의 연결고리

journalctl --list-boots로 부팅 이력을 확인해보니, 이 10초 간격 무한 재시작 루프가 방치된 기간 동안 며칠 간격으로, 심지어 하루에 여러 번(몇 시간 사이 6번씩) 재부팅되는 패턴이 겹쳐서 나타나고 있었습니다. 더 골치 아팠던 건, 재부팅해도 부팅 직후 같은 루프가 곧바로 다시 시작되니 문제가 계속 반복될 수밖에 없는 구조였다는 점입니다.

이해한 내용

가장 크게 배운 건 Restart= 정책이 걸린 데몬형 서비스는 실패해도 겉으로 티가 안 난다는 점입니다. 에러 메시지가 화면에 뜨는 것도 아니고, 그냥 조용히 백그라운드에서 10초마다 실패-재시도를 반복하면서 리소스를 갉아먹고 있었습니다. 로그를 직접 뒤지지 않았다면 계속 몰랐을 문제였습니다.

또 하나는 경로 이름 변경의 파급 범위입니다. 프로젝트 폴더 이름을 바꾸는 건 단순히 폴더 하나만 건드리는 게 아니라, 그 경로를 참조하는 모든 설정(systemd 유닛, 크론잡, 환경변수 파일 등)을 같이 고려해야 하는 작업이라는 걸 체감했습니다.

실전 적용

해결 방법은 간단했습니다. 경로가 바뀌어서 이미 죽어버린 옛날 유닛들을 고쳐 쓸 이유가 없다고 판단하고, learningetl.service와 learningcollector-daily.service/learningcollector-daily.timer를 모두 중지한 뒤 유닛 파일 자체를 삭제했습니다.

제거 후 systemctl status로 확인해보니 두 유닛 모두 "could not be found"로 나왔고, 이후로는 반복 재부팅 패턴도 더 이상 나타나지 않았습니다.

앞으로 프로젝트 폴더를 옮기거나 이름을 바꿀 때는 다음을 체크리스트로 삼으려 합니다:

  • systemctl list-units --type=service --all로 관련 유닛이 있는지 확인
  • 유닛 파일 안의 ExecStart, EnvironmentFile 경로 점검
  • 이름을 바꾼 직후 journalctl -u <서비스명> -f로 정상 기동되는지 즉시 확인

추가 학습 계획

  • systemd의 Restart= 정책 종류(on-failure, always, on-abnormal 등)와 각각의 동작 차이를 더 깊게 공부하고 싶습니다.
  • 재시작 무한 루프를 자동으로 감지해서 알림을 보내는 모니터링 스크립트를 만들어보고 싶습니다. (예: 특정 유닛의 restart 카운트가 임계치를 넘으면 슬랙/이메일 알림)
  • journalctl --list-boots와 dmesg를 조합해서 하드웨어적 원인(전원 문제, SD카드 손상 등)과 소프트웨어적 원인을 구분하는 진단 루틴을 정리해두고 싶습니다.