Linux 시스템을 관리하다 보면 누구나 한 번쯤은 마주치게 되는 상황이 있습니다. systemctl status 명령어를 실행했는데 “Active: failed (Result: exit-code), code=exited”라는 빨간 글씨가 나타나는 순간이죠. 처음 이런 상황에 직면하면 당황스럽기 마련인데, 사실 이는 시스템 관리에서 매우 흔하게 발생하는 문제입니다.

이번 포스에서는 이런 상황에서 당황하지 않고 체계적으로 문제를 진단하고 해결하는 방법 알아보겠습니다. 🙂

code=exited

 

1. 먼저 이해하기: exit-code (code=exited)오류가 의미하는 것

Active: failed (Result: exit-code)는 해당 서비스가 정상적으로 종료되지 않았다는 의미입니다. 쉽게 말해서 프로그램이 실행되다가 문제를 만나 비정상적으로 종료된 상황이죠.

● nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Fri 2024-05-24 14:30:45 KST; 2min 24s ago
  Process: 2491 ExecStart=/usr/sbin/nginx (code=exited, status=1/FAILURE)
 Main PID: 2491 (code=exited, status=1/FAILURE)

위 예시에서 보면 nginx 서비스가 시작 과정에서 실패했고, 프로세스 ID 2491로 실행되었다가 상태 코드 1로 종료되었음을 알 수 있습니다. 이때 중요한 것은 단순히 “실패했다”는 사실보다는 “왜 실패했는지”를 찾아내는 것입니다.

 

2. 즉시 확인해야 할 기본 정보들

서비스 실패를 발견했다면 가장 먼저 다음 명령어들로 기본 정보를 수집해야 합니다.

상세 상태 확인하기

sudo systemctl status service-name --full --lines=50

--full 옵션은 긴 줄도 잘리지 않게 전체를 보여주고, --lines=50은 최근 50줄의 로그를 함께 표시합니다. 이렇게 하면 단순한 상태 정보 외에도 실제 오류 메시지까지 한 번에 볼 수 있어 시간을 절약할 수 있습니다.

전체 실패 서비스 목록 확인

sudo systemctl list-units --failed

때로는 하나의 서비스 실패가 다른 서비스들에게 연쇄 영향을 미치는 경우가 있습니다. 전체적인 상황을 파악하는 것이 중요하죠.

 

3. journalctl로 진짜 원인 찾기

systemctl status만으로는 한계가 있을 때가 많습니다. 진짜 문제의 원인을 찾으려면 journalctl을 활용해야 합니다.

서비스별 상세 로그 확인

sudo journalctl -u service-name.service --since today

오늘 발생한 해당 서비스의 모든 로그를 시간순으로 보여줍니다. 서비스가 언제부터 문제를 보이기 시작했는지 추적할 수 있어요.

실시간 로그 모니터링

sudo journalctl -u service-name.service -f

서비스를 재시작하면서 실시간으로 어떤 오류가 발생하는지 관찰할 때 유용합니다. 문제가 발생하는 정확한 순간을 포착할 수 있죠.

부팅 관련 문제 진단

sudo journalctl -u service-name.service -b

현재 부팅 세션에서 발생한 로그만 보여줍니다. 시스템 재시작 후 서비스가 제대로 시작되지 않는 문제를 진단할 때 특히 유용합니다.

 

4. 자주발생하는 에러 유형별 해결법

지금까지의 경험을 바탕으로 자주 발생하는 에러 유형별로 해결 방법을 정리해보겠습니다.

설정 파일 문제

가장 흔한 원인 중 하나는 설정 파일의 문법 오류입니다.

# nginx의 경우
sudo nginx -t

# apache의 경우  
sudo apache2ctl configtest

# 설정 파일 위치 확인
sudo systemctl show service-name | grep ExecStart

설정 파일 검증 명령어를 먼저 실행해보세요. 대부분의 서비스들은 설정 파일의 문법을 미리 검사할 수 있는 기능을 제공합니다.

권한 및 사용자 문제

exit code 217이 나타나면 사용자 관련 문제일 가능성이 높습니다.

# 서비스 설정에서 지정된 사용자 확인
sudo systemctl show service-name | grep User

# 해당 사용자가 존재하는지 확인
id username

# 사용자 생성 (필요한 경우)
sudo useradd -r -s /bin/false service-user

의존성 문제

서비스가 필요로 하는 다른 서비스나 네트워크가 준비되지 않았을 때 발생합니다.

# 서비스 의존성 확인
sudo systemctl list-dependencies service-name

# 의존 서비스들의 상태 확인
sudo systemctl status network-online.target
sudo systemctl status multi-user.target

네트워크가 필요한 서비스라면 After=network-online.target 설정을 확인해보세요.

포트 충돌 문제

같은 포트를 사용하려는 다른 프로세스가 있을 때 발생합니다.

# 포트 사용 현황 확인
sudo netstat -tlpn | grep :80
sudo ss -tlpn | grep :80

# 해당 포트를 사용하는 프로세스 종료
sudo lsof -ti:80 | xargs sudo kill -9

 

5. 그래도 해결이 안될 때 처리 방법

일반적인 방법으로 해결되지 않는 복잡한 문제들을 위한 고급 기법들입니다.

상세 로그 레벨 활성화

# 서비스 환경에 디버그 옵션 추가
sudo systemctl edit service-name

# 아래 내용 추가
[Service]
Environment="DEBUG=1"
ExecStart=
ExecStart=/usr/bin/service-binary --verbose --debug

서비스 파일 직접 분석

# 서비스 파일 위치 확인
sudo systemctl status service-name | grep Loaded

# 서비스 파일 내용 확인
sudo cat /etc/systemd/system/service-name.service

# 서비스 재로드 (수정 후)
sudo systemctl daemon-reload

수동 실행으로 문제 격리

# 서비스와 동일한 환경에서 수동 실행
sudo -u service-user /usr/bin/service-binary --config /etc/service/config.conf

# 환경 변수까지 동일하게 맞춰서 실행
sudo systemd-run --uid=service-user --gid=service-group --setenv=HOME=/var/lib/service /usr/bin/service-binary

 

6. 동일한 에러 재발 방지를 위한 모니터링 설정

문제가 해결되었다면 이제 재발을 방지하고 조기에 감지할 수 있는 시스템을 구축해야 합니다.

자동 재시작 설정

# 서비스 파일에 추가
[Service]
Restart=always
RestartSec=10
StartLimitInterval=60
StartLimitBurst=3

이렇게 설정하면 서비스가 실패했을 때 자동으로 재시작을 시도하되, 너무 자주 실패하면 일정 시간 대기하게 됩니다.

로그 관리 최적화

# 로그 크기 제한 설정
sudo journalctl --vacuum-time=30d
sudo journalctl --vacuum-size=1G

# 지속적인 로그 저장 활성화
sudo mkdir -p /var/log/journal
sudo systemctl restart systemd-journald

모니터링 스크립트 작성

#!/bin/bash
# service-monitor.sh

SERVICES=("nginx" "mysql" "redis")

for service in "${SERVICES[@]}"; do
    if ! systemctl is-active --quiet "$service"; then
        echo "$(date): $service is not running!" | tee -a /var/log/service-monitor.log
        # 알림 전송 (이메일, 슬랙 등)
        systemctl restart "$service"
    fi
done

이 스크립트를 cron에 등록하면 주기적으로 중요한 서비스들의 상태를 확인하고 자동으로 복구할 수 있습니다.

 

7. 마지막으로, 에러 해결 단계를 간단히 정리하면…

문제 발생 시 순서대로 확인해볼 수 있는 체크리스트입니다:

  1. 기본 상태 확인: systemctl status service-name --full --lines=50
  2. 상세 로그 분석: journalctl -u service-name --since today
  3. 설정 파일 검증: 서비스별 설정 검증 명령어 실행
  4. 리소스 확인: 디스크 공간, 메모리, 포트 충돌 점검
  5. 의존성 점검: 필요한 다른 서비스들의 상태 확인
  6. 권한 검증: 사용자, 그룹, 파일 권한 확인
  7. 수동 실행: 동일한 환경에서 직접 실행해보기
  8. 네트워크 확인: 필요한 네트워크 서비스들의 준비 상태 점검

 

이상으로 systemctl status입력시 Active: failed (code=exited) 뜰 때 단계적 해결방법에 대하여 알아 봤습니다. systemctl의 exit-code 오류는 처음에는 막막해 보이지만, 체계적으로 접근하면 대부분 해결할 수 있는 문제입니다. 가장 중요한 것은 당황하지 않고 차근차근 로그를 분석하며 원인을 찾아가는 것입니다. 이 글이 여러분의 시스템 운영에 도움이 되었으면 합니다. 🙂

 

댓글 남기기