systemctl 및 journalctl을 사용한 Linux 서비스 문제 해결
systemctl과 journalctl을 사용하여 실패하거나 비정상적인 Linux 서비스를 디버깅하는 실용적인 워크플로
systemctl 및 journalctl을 사용한 Linux 서비스 문제 해결
Linux 서비스가 실패하면 가장 빠른 경로는 일반적으로 웹 검색이 아닙니다. 세 가지 로컬 확인이 필요합니다: systemd가 어떻게 생각하는지, 서비스가 기록한 내용, 실패 전에 변경된 사항입니다. systemctl과 journalctl은 추측 없이 이러한 답변을 제공합니다.
이 가이드는 일반적인 서비스 실패 사례를 예시로 사용합니다: 시작되지 않는 서비스, 실행 중이지만 유용한 작업을 수행하지 않는 프로세스, 정상으로 보이다가 종료되는 서비스입니다. 명령어는 대부분의 systemd 관리 서비스에 적용되지만, 정확한 유닛 이름과 로그 위치는 배포판 및 패키지에 따라 다릅니다.
systemctl 및 journalctl 이해하기
문제 해결에 들어가기 전에 이 두 가지 주요 도구의 역할을 이해하는 것이 중요합니다:
systemctl: 이 명령어는systemd시스템 및 서비스 관리자를 제어하고 쿼리하는 중앙 유틸리티입니다. 서비스를 시작, 중지, 재시작, 상태 확인, 활성화/비활성화할 수 있습니다.journalctl: 이 명령어는 중앙 집중식 로깅 시스템인 systemd 저널을 쿼리하는 데 사용됩니다. 커널, 시스템 서비스 및 애플리케이션의 로그를 수집하여 시스템 이벤트에 대한 통합된 보기를 제공합니다.journalctl은 서비스가 실패하거나 예기치 않게 동작한 이유를 이해하는 데 매우 중요합니다.
일반적인 문제 해결 시나리오 및 해결 방법
일반적인 문제와 해결 방법을 살펴보겠습니다:
1. 서비스 시작 실패
아마도 가장 일반적인 문제입니다. 서비스를 시작하려고 하면 즉시 실패합니다.
1단계: 서비스 상태 확인
systemctl status를 사용하여 서비스 상태 및 최근 로그 항목에 대한 즉각적인 개요를 확인합니다.
sudo systemctl status apache2.service
예상 출력 (예시 - 실제와 다를 수 있음):
● apache2.service - The Apache HTTP Server
Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
Active: **failed** (result: exit-code) since Tue 2023-10-27 10:00:00 UTC; 1min ago
Docs: https://httpd.apache.org/docs/2.4/
Process: 12345 ExecStart=/usr/sbin/apachectl start (code=exited, status=1/FAILURE)
Main PID: 12345 (code=exited, status=1/FAILURE)
Oct 27 10:00:00 your-server systemd[1]: Starting The Apache HTTP Server...
Oct 27 10:00:00 your-server apachectl[12345]: AH00526: Syntax error on line 123 of /etc/apache2/apache2.conf:
Oct 27 10:00:00 your-server apachectl[12345]: Invalid Mutex directory in argument file: '/var/run/apache2/'
Oct 27 10:00:00 your-server systemd[1]: apache2.service: Main process exited, code=exited, status=1/FAILURE
Oct 27 10:00:00 your-server systemd[1]: **Failed** to start The Apache HTTP Server.
Oct 27 10:00:00 your-server systemd[1]: apache2.service: Unit entered failed state.
분석: systemctl status 출력은 Active: failed를 명확히 보여주고 오류 메시지의 일부를 제공합니다: Invalid Mutex directory in argument file: '/var/run/apache2/'. 이는 구성 문제를 시사합니다.
2단계: journalctl로 로그 조사
더 자세한 정보를 위해 journalctl을 사용하여 실패한 서비스에 대한 로그를 확인합니다. -u 플래그는 유닛(서비스)을 지정합니다.
sudo journalctl -u apache2.service -xe
-u apache2.service:apache2.service유닛에 대한 로그를 필터링합니다.-x: 일부 로그 메시지에 대한 설명을 추가합니다.-e: 저널의 끝으로 이동하여 가장 최근 항목을 표시합니다.
잠재적 발견: journalctl 출력은 구성 오류, 권한 문제 또는 종속성 문제에 대한 더 많은 컨텍스트를 드러낼 수 있습니다.
3단계: 구성 파일 확인
오류 메시지를 기반으로 관련 구성 파일을 검사합니다. 위의 예에서는 /etc/apache2/apache2.conf와 /var/run/apache2/ 디렉토리를 가리킵니다.
sudo nano /etc/apache2/apache2.conf
해결 방법: 이러한 문제는 종종 런타임 디렉토리 누락, 패키징 변경 또는 더 이상 존재하지 않는 경로를 참조하는 구성 파일에서 발생합니다. 인터넷의 예제를 맹목적으로 디렉토리를 생성하지 마십시오. 먼저 애플리케이션이 배포판에서 기대하는 것을 확인한 다음 누락된 경로나 구성을 수정하십시오. 가능한 수리는 다음과 같습니다:
sudo mkdir -p /var/run/apache2/
sudo chown www-data:www-data /var/run/apache2/
sudo systemctl start apache2.service
오류가 구문 문제를 언급하는 경우, 다시 시작하기 전에 애플리케이션 자체 구성 테스트를 실행하십시오:
sudo apachectl configtest
sudo nginx -t
sudo sshd -t
애플리케이션별 유효성 검사기는 systemd가 이해할 수 없는 실수를 잡아냅니다. Systemd는 프로세스가 종료되었는지 여부를 알고 있습니다. Nginx server 블록이 잘못된 인증서 파일을 가리키는지 또는 Apache 지시문이 다른 컨텍스트에 속하는지 알지 못합니다.
2. 서비스가 실행 중이지만 응답하지 않음
때로는 systemctl status가 서비스를 active (running)으로 표시하지만 의도된 기능을 수행하지 않습니다(예: 웹 서버가 페이지를 제공하지 않음).
1단계: 서비스 상태 및 PID 확인
실제로 실행 중이고 프로세스 ID(PID)가 있는지 확인합니다.
sudo systemctl status nginx.service
active (running)으로 표시되면 PID를 기록해 둡니다.
2단계: 서비스 로그에서 오류 확인
실행 중이더라도 서비스가 제대로 작동하지 못하게 하는 내부 오류가 발생할 수 있습니다.
sudo journalctl -u nginx.service -f
-f: 로그 출력을 실시간으로 따라갑니다.journalctl이 실행되는 동안 문제를 트리거할 수 있는 경우(예: 웹 페이지에 액세스 시도) 유용합니다.
3단계: 애플리케이션별 로그 확인
많은 서비스가 systemd 저널 외에도 자체 로그를 기록합니다. Nginx 또는 Apache와 같은 웹 서버의 경우 일반적인 로그 위치(예: /var/log/nginx/error.log, /var/log/apache2/error.log)를 확인합니다.
sudo tail -n 50 /var/log/nginx/error.log
4단계: 리소스 사용량 확인
과부하된 시스템은 서비스가 응답하지 않게 만들 수 있습니다.
top
htop
free -h
서비스 프로세스의 높은 CPU, 메모리 또는 디스크 I/O를 찾습니다.
또한 서비스가 예상하는 곳에서 수신 대기 중인지 확인합니다:
sudo ss -ltnp
sudo ss -lunp
웹 서비스의 경우 systemctl에서 nginx가 활성화된 것을 보는 것은 이야기의 절반에 불과합니다. 0.0.0.0:80, 127.0.0.1:8080, IPv6 소켓 또는 소켓에 전혀 바인딩되어 있는지 여부를 여전히 알아야 합니다. 방화벽 규칙, 리버스 프록시 불일치 또는 잘못된 바인드 주소는 외부에서 볼 때 정상 프로세스가 손상된 것처럼 보이게 할 수 있습니다.
해결 방법: 로그가 문제를 나타내거나 리소스가 부족한 경우 다음이 필요할 수 있습니다:
- 구성 최적화.
- 서비스 재시작 (
sudo systemctl restart <service_name>.service). - 기본 시스템 리소스 문제 조사.
- 필요한 경우 시스템 리소스 증가.
3. 서비스가 예기치 않게 중지됨
이전에 실행 중이던 서비스가 갑자기 중지되는 경우, 종종 처리되지 않은 예외 또는 감시 시간 초과로 인해 발생합니다.
1단계: journalctl로 최근 기록 확인
journalctl을 사용하여 서비스가 중지되기 직전에 발생한 상황을 확인합니다. --since 및 --until 플래그는 대략적인 시간을 알고 있는 경우 유용합니다.
sudo journalctl -u <service_name>.service --since "1 hour ago"
또는 마지막 부팅 이후 서비스와 관련된 모든 로그를 보려면:
sudo journalctl -u <service_name>.service -b
2단계: 코어 덤프 또는 충돌 보고서 찾기
서비스가 충돌한 경우 시스템이 코어 덤프 또는 충돌 보고서를 생성했을 수 있습니다.
ls -l /var/crash/
3단계: systemd 서비스 유닛 파일 검토
서비스의 유닛 파일(일반적으로 /etc/systemd/system/ 또는 /lib/systemd/system/에 있음)에서 Restart= 지시문 및 WatchdogSec= 설정을 검사합니다. 잘못된 Restart= 구성 또는 너무 짧은 WatchdogSec=는 예기치 않은 재시작 또는 실패를 유발할 수 있습니다.
systemctl cat <service_name>.service
해결 방법: 로그에서 식별된 근본 원인을 해결합니다. 여기에는 코드 버그 수정, systemd 유닛 파일 매개변수 조정 또는 리소스 제한 증가가 포함될 수 있습니다.
반복적인 재시작이 표시되면 systemd가 유닛을 속도 제한했는지 확인합니다:
systemctl status <service_name>.service
journalctl -u <service_name>.service --since "30 minutes ago"
Start request repeated too quickly에 대한 메시지는 일반적으로 서비스가 짧은 시간 내에 여러 번 충돌했음을 의미합니다. 기본 문제를 해결한 후 실패 상태를 지웁니다:
sudo systemctl reset-failed <service_name>.service
sudo systemctl start <service_name>.service
4. systemctl enable 또는 systemctl disable 문제
런타임 실패는 아니지만 서비스를 활성화하거나 비활성화하는 데 문제가 발생할 수 있습니다.
문제: 서비스가 활성화되어 있지만 부팅 시 시작되지 않거나 그 반대입니다.
상태 확인:
sudo systemctl is-enabled <service_name>.service
이 명령어는 enabled 또는 disabled를 출력합니다.
문제 해결:
- 서비스 유닛 파일 자체가 유효하고 올바르게 배치되었는지 확인합니다(예:
/etc/systemd/system/). - 유닛 파일을 변경한 후에는 항상
sudo systemctl daemon-reload를 실행합니다. - 서비스 로그(
journalctl -u <service_name>.service)에서 활성화되어 있어도 활성화되지 못하게 하는 시작 오류가 있는지 확인합니다.
효과적인 문제 해결을 위한 팁
systemctl status로 시작: 항상 여기서 시작하십시오. 빠른 스냅샷을 제공하고 종종 올바른 방향을 알려줍니다.journalctl -u <service>사용: 이것이 왜 무언가가 발생하는지 이해하는 기본 도구입니다.journalctl과 함께-f플래그: 문제를 재현하려고 할 때 실시간 모니터링에 매우 유용합니다.systemctl restart <service>: 구성을 변경한 후에는 항상 서비스를 다시 시작하여 적용하십시오.systemctl daemon-reload:.service유닛 파일을 수정한 후에 중요합니다.- 종속성 확인: 때로는 서비스가 의존하는 서비스가 시작되지 않았거나 자체적으로 실패하여 서비스가 실패합니다.
systemctl status는 종종 이를 표시합니다. - 권한: 많은 서비스 실패는 잘못된 파일 또는 디렉토리 권한으로 인해 발생합니다. 서비스가 실행되는 사용자에게 필요한 액세스 권한이 있는지 확인하십시오.
- 네트워크 문제: 서비스가 네트워크에 의존하는 경우 네트워크 연결, 방화벽 규칙 및 포트 가용성을 확인하십시오.
유지되는 문제 해결 순서
압박이 있을 때마다 매번 동일한 순서를 사용하십시오:
systemctl status <service>.service
journalctl -u <service>.service -b --no-pager
systemctl cat <service>.service
systemctl list-dependencies <service>.service
현재 상태로 시작한 다음 현재 부팅의 로그를 읽고 systemd가 보는 대로 유닛을 검사한 다음 종속성을 확인합니다. 서비스가 네트워크를 향하는 경우 ss -ltnp 및 로컬 curl 또는 클라이언트 테스트를 추가합니다. 구성 파일을 읽는 경우 서비스 자체 구성 유효성 검사기를 실행합니다.
요점은 무작위 재시작을 피하는 것입니다. 재시작은 구성 변경 또는 프로세스 중단 후에 유효한 수정일 수 있지만 증거도 파괴합니다. 변경하는 내용과 이유를 알 수 있도록 먼저 저널을 충분히 읽으십시오.
길을 잃지 않고 저널 출력 읽기
journalctl은 특히 바쁜 서버에서 시끄러울 수 있습니다. 좁게 시작한 다음 필요할 때만 넓히십시오.
현재 부팅의 단일 서비스:
journalctl -u <service>.service -b --no-pager
지난 몇 분:
journalctl -u <service>.service --since "15 minutes ago" --no-pager
이전 부팅:
journalctl -u <service>.service -b -1 --no-pager
이 이전 부팅 보기는 서비스가 시작 중에 실패한 후 복구되었거나 전체 시스템이 검사하기 전에 재부팅된 경우에 유용합니다. 부팅 목록은 다음으로 볼 수 있습니다:
journalctl --list-boots
서비스가 구조화된 필드 또는 긴 줄을 기록하는 경우 짧은 ISO 타임스탬프를 사용하십시오:
journalctl -u <service>.service -o short-iso --no-pager
로그를 공유해야 하는 경우 비밀, 토큰, 내부 호스트 이름 및 고객 데이터를 제거하십시오. 서비스 로그에는 종종 환경에서 파생된 설정, URL, 헤더 또는 연결 문자열이 포함됩니다. 깨끗한 문제 해결 습관에는 출력을 어디에나 붙여넣기 전에 편집하는 것이 포함됩니다.
systemctl이 "Active"라고 말하지만 사용자가 여전히 실패를 볼 때
active (running) 상태는 systemd에 유닛의 기대치와 일치하는 프로세스가 있음을 의미할 뿐입니다. 애플리케이션이 정상임을 증명하지 않습니다. 웹 애플리케이션이 실행 중이면서 HTTP 500을 반환할 수 있습니다. 작업자가 활성 상태이면서 잘못된 대기열 메시지에 멈출 수 있습니다. 데이터베이스 프록시가 실행 중이면서 모든 백엔드 연결이 실패할 수 있습니다.
네트워크 서비스의 경우 사용자가 의존하는 동일한 계층에서 테스트하십시오:
curl -v http://127.0.0.1:8080/health
curl -v http://localhost/health
curl -v https://service.example.com/health
이 세 가지 확인은 다른 질문에 답합니다. 첫 번째는 로컬 앱 포트를 확인합니다. 두 번째는 로컬 리버스 프록시를 포함할 수 있습니다. 세 번째는 DNS, TLS, 라우팅, 방화벽 규칙 및 공용 경로를 확인합니다.
작업자 서비스의 경우 소비하거나 생성하는 항목을 살펴보십시오. 대기열 작업자는 대기열 깊이 확인이 필요할 수 있습니다. 백업 서비스는 최근 출력 파일이 필요할 수 있습니다. 메트릭 수집기는 메트릭 백엔드에 대한 쿼리가 필요할 수 있습니다. systemctl은 감독이 작동하는지 알려줍니다; 애플리케이션 확인은 서비스가 유용한지 알려줍니다.
한 번에 하나의 변수 수정
배포 후 유닛이 실패하면 여러 항목을 변경하고 다시 시작하고 싶은 유혹이 있습니다. 이는 실제 원인을 숨길 수 있습니다. 한 번에 하나의 변경을 선호하십시오:
systemctl cat my-app.service
journalctl -u my-app.service --since "30 minutes ago" --no-pager
sudo systemctl edit my-app.service
sudo systemctl daemon-reload
sudo systemctl restart my-app.service
그런 다음 다음 항목을 변경하기 전에 결과를 확인하십시오. 실패가 누락된 파일인 경우 파일 경로를 수정하십시오. 권한 오류인 경우 소유권 또는 모드를 수정하십시오. 종속성인 경우 유닛 관계 또는 애플리케이션 재시도 동작을 수정하십시오. 느리고 지루한 문제 해결은 추적되지 않은 5개의 편집으로 재시작 루프를 도는 것보다 종종 더 빠릅니다.