GrepBoard/매뉴얼
51 편 ·

서비스가 failed 일 때 원인 찾기

·Ubuntu 24.04 · systemd 255 (일시 유닛으로 재현)·6 단계

systemctl status 의 Active·status 줄을 읽고, journalctl 로 실패 직전 로그를 보고, 203/EXEC 와 start request repeated too quickly 를 고칩니다.

서비스가 failed 가 되면 status → journalctl → systemctl cat 순서로 봅니다. 출력은 일시 유닛(systemd-run)을 일부러 실패시켜 얻은 실제 결과이고, 유닛 이름은 myapp, 경로는 /srv/app 로 바꿨습니다.

[1] systemctl status 로 어떻게 죽었는지 봅니다. Active: 는 상태와 이유(Result: exit-code), Process: 는 실행한 명령과 종료 코드(code=exited, status=3), Main PID: 는 마지막에 돈 프로세스입니다.

console
# systemctl status myapp --no-pager× myapp.service - /bin/sh -c "echo \"myapp: cannot open /srv/app/config.yml\" >&2; exit 3"     Active: failed (Result: exit-code) since Mon 2026-10-19 12:16:54 KST; 1s ago    Process: 47127 ExecStart=/bin/sh -c echo "myapp: cannot open /srv/app/config.yml" >&2; exit 3 (code=exited, status=3)   Main PID: 47127 (code=exited, status=3)

[2] 프로그램이 남긴 오류는 journalctl 에 있습니다. -u 유닛, -b 이번 부팅, -n 50 마지막 50줄, --no-pager 페이저 없이 출력합니다.

console
# journalctl -u myapp -b --no-pager -n 50Oct 19 12:16:54 server1 sh[47127]: myapp: cannot open /srv/app/config.ymlOct 19 12:16:54 server1 systemd[1]: myapp.service: Main process exited, code=exited, status=3/NOTIMPLEMENTEDOct 19 12:16:54 server1 systemd[1]: myapp.service: Failed with result 'exit-code'.

sh[47127]: 줄이 프로그램이 직접 쓴 메시지, 곧 원인입니다.

[3] 실제로 적용된 유닛은 systemctl cat 으로 봅니다. 유닛 파일과 드롭인(myapp.service.d/)을 파일 경로와 함께 보여 줍니다.

console
# systemctl cat myapp --no-pager# /run/systemd/transient/myapp.service[Service]ExecStart=ExecStart="/bin/sh" "-c" "echo \"myapp: cannot open /srv/app/config.yml\" >&2; exit 3"

[4] 흔한 원인은 status=203/EXEC 입니다. 매뉴얼(systemd.exec 의 Process Exit Codes)은 execve(2) 호출이 실패한 것이고 「대개 실행 파일이 없거나 접근할 수 없어서」라고 설명합니다. 아래는 파일은 있는데 첫 줄 인터프리터(#!/usr/bin/python4)가 없는 경우입니다.

console
# systemctl status myapp --no-pager    Process: 47581 ExecStart=/srv/app/bin/myapp (code=exited, status=203/EXEC)   Main PID: 47581 (code=exited, status=203/EXEC) # journalctl -u myapp -b --no-pager -n 50Oct 19 12:16:59 server1 (myapp)[47581]: myapp.service: Failed to execute /srv/app/bin/myapp: No such file or directory

[5] 재시작을 켠 서비스가 계속 죽으면 start request repeated too quickly 로 멈춥니다. 아래는 Restart=always 에 10초 안에 3번만 시작하도록 제한한 유닛의 결과입니다.

console
# journalctl -u myapp -b --no-pager -n 4Oct 19 12:17:05 server1 systemd[1]: myapp.service: Scheduled restart job, restart counter is at 3.Oct 19 12:17:05 server1 systemd[1]: myapp.service: Start request repeated too quickly.Oct 19 12:17:05 server1 systemd[1]: Failed to start myapp.service - /bin/sh -c "echo \"myapp: bind: address already in use\" >&2; exit 1".

이 줄은 결과일 뿐입니다. 원인은 로그 위쪽 프로그램이 쓴 줄(myapp: bind: address already in use)에 있습니다. 기본 한도는 StartLimitIntervalSec=10s · StartLimitBurst=5 이고, 넘으면 reset-failed 전에는 다시 시작되지 않습니다.

[6] 원인을 고칩니다. 유닛 파일을 바꿨다면 daemon-reload 로 다시 읽게 하고, reset-failed(failed 상태를 되돌립니다)로 실패 기록과 시작 횟수 제한을 지운 뒤 시작합니다.

/etc/systemd/system/myapp.service
[Unit]Description=myapp [Service]ExecStart=/srv/app/bin/myapp --config /srv/app/config.ymlRestart=on-failure [Install]WantedBy=multi-user.target
console
# systemctl daemon-reload# systemctl reset-failed myapp# systemctl restart myapp

syslog · journal 로그를 브라우저에서 바로 분석 ↗ — 아무것도 올라가지 않습니다.

#systemd#systemctl#journalctl