파이썬 로그가 서비스 실행에서 안 보일 때: journalctl과 파일 로그 확인 순서

터미널에서 실행할 때 보이던 Python 로그가 systemd 서비스로 바뀐 뒤 사라졌다면, 먼저 파일을 새로 만들기보다 서비스의 표준 출력과 표준 오류가 journal로 연결되는지 확인하는 것이 순서입니다. 그다음 애플리케이션이 별도 파일을 정말 필요로 하는지 판단해 FileHandler 또는 SysLogHandler를 선택하면 됩니다.

먼저 로그가 사라진 것이 아니라 경로가 바뀐 것인지 확인합니다

Python의 StreamHandler는 스트림으로 로그를 보내며, 기본 스트림은 sys.stderr입니다. 터미널에서 실행할 때는 이 스트림이 화면에 보이지만, systemd가 프로세스를 관리하면 서비스의 표준 출력·오류는 journal과 연결될 수 있습니다. 따라서 화면에 아무것도 없다는 사실만으로 Python logging 설정이 실패했다고 단정하기 어렵습니다.

서비스 이름을 알고 있다면 다음처럼 유닛별 journal을 먼저 확인합니다.

journalctl -u my-python.service
journalctl -f -u my-python.service

첫 명령은 해당 유닛의 로그를 조회하고, 두 번째 명령은 새 로그가 들어오는지 따라가는 데 사용합니다. 로그가 보인다면 애플리케이션의 StreamHandler를 파일 핸들러로 바꾸는 작업은 당장 필요하지 않습니다.

다만 실제 유닛의 StandardOutput과 StandardError 설정, journald의 저장 설정과 접근 권한에 따라 결과는 달라질 수 있습니다. journal에 현재 로그가 보이더라도 재부팅 뒤 보존되는지는 journald 저장 설정을 별도로 확인해야 합니다. journald는 설정에 따라 로그를 휘발성 또는 영속적으로 저장할 수 있습니다.

journal에 로그가 없을 때는 Python보다 서비스 연결을 좁혀 봅니다

journalctl -u 결과가 비어 있다면 다음 순서로 범위를 줄이는 편이 안전합니다.

  1. 조회한 유닛 이름이 실제 서비스 이름과 같은지 확인합니다.
  2. 서비스가 실행되었는지와 종료 상태를 확인합니다.
  3. 유닛의 표준 출력·오류가 journal로 연결되도록 설정되어 있는지 확인합니다.
  4. Python logging에서 StreamHandler가 실제로 표준 오류 또는 다른 스트림으로 기록하도록 구성되어 있는지 확인합니다.
  5. 서비스 계정이 journal을 조회할 권한이 있는지 확인합니다.

이 과정은 문제를 애플리케이션 코드와 운영 환경으로 나누는 데 도움이 됩니다. 실행 자체가 되지 않는다면 파일 로그를 추가해도 기록되지 않습니다. 반대로 서비스는 실행 중이고 journal에 스트림 로그가 들어온다면, 로그 위치를 몰랐던 것이 원인일 가능성이 큽니다.

별도 파일이 필요할 때만 FileHandler를 선택합니다

FileHandler는 지정한 디스크 파일을 열어 로그를 기록합니다. 운영자가 파일을 별도 수집 경로로 넘겨야 하거나 애플리케이션별 파일을 직접 보관해야 하는 요구가 있다면 선택할 수 있습니다.

import logging

logger = logging.getLogger("worker")
logger.setLevel(logging.INFO)

handler = logging.FileHandler("/var/log/my-python-worker.log")
handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(message)s"))
logger.addHandler(handler)

logger.info("worker started")

여기서 중요한 것은 예제의 경로를 그대로 복사하는 일이 아니라, 서비스 계정이 해당 경로에 쓸 수 있는지와 운영 환경에서 그 파일을 어떻게 보존·수집할지를 함께 결정하는 것입니다. 상대경로는 서비스의 현재 작업 폴더가 터미널에서 실행할 때와 다를 수 있어, 로그가 엉뚱한 위치에 생겼다고 오해하기 쉽습니다.

파일 로그를 추가하면서 같은 메시지를 표준 출력에도 남기면 journal과 파일에 중복 기록될 수 있습니다. 두 경로가 모두 필요한지 먼저 정하고, 필요한 경우에만 각각의 핸들러를 명시적으로 구성하는 편이 관리하기 쉽습니다.

SysLogHandler는 syslog 수집 경로가 있을 때 사용합니다

SysLogHandler는 로컬 또는 원격 Unix syslog 데몬으로 로그를 보냅니다. 이미 syslog 데몬이나 중앙 수집기가 운영되고 있고 그 경로로 전달해야 할 때 적합합니다. Python 프로그램이 임의로 원격 수신 위치를 보장해 주는 핸들러는 아닙니다.

import logging
from logging.handlers import SysLogHandler

logger = logging.getLogger("worker")
logger.setLevel(logging.INFO)

handler = SysLogHandler(address="/dev/log")
logger.addHandler(handler)

logger.info("sent to syslog")

실제 소켓이나 네트워크 주소, 수신 위치는 운영체제와 syslog 데몬 설정에 따라 달라집니다. 따라서 syslog 데몬이 준비되지 않았거나 수신 경로를 확인할 수 없다면, 단순히 SysLogHandler를 추가하는 것보다 systemd journal 경로를 먼저 확인하는 편이 낫습니다.

선택 기준을 짧게 정리하면 이렇습니다

운영 중인 서비스의 기본 진단은 StreamHandler와 systemd journal 조합에서 시작합니다. 서비스별 조회와 실시간 확인이 충분하면 별도 파일을 만들지 않아도 됩니다. 파일 자체를 다른 도구가 읽어야 하거나 애플리케이션별 보관 규칙이 필요할 때 FileHandler를 검토합니다. 이미 syslog 수집 체계가 있고 그 경로로 보내야 할 때 SysLogHandler를 선택합니다.

저라면 로그가 안 보일 때 다음 질문을 먼저 적어 봅니다.

  • 프로그램은 서비스로 실제 실행되었는가?
  • 표준 출력·오류는 어느 경로로 연결되어 있는가?
  • journalctl -u에서 서비스 이름으로 조회했는가?
  • 별도 파일이 필요한 운영 요구가 실제로 있는가?
  • 파일 또는 syslog 수신 경로에 서비스 계정이 접근할 수 있는가?

이 질문에 답한 뒤에야 핸들러를 바꾸는 것이 좋습니다. Python 로그 설정의 문제처럼 보이는 현상도 실행 방식이 바뀌면서 확인 위치가 달라진 결과일 수 있기 때문입니다.

파일 로그 설정 자체와 현재 작업 폴더 때문에 파일을 찾지 못하는 경우는 각각 파이썬 로그 파일이 안 생기는 이유와 logging 설정 점검법과 파이썬 파일이 있는데 FileNotFoundError가 날 때: 상대경로와 현재 작업 폴더 확인법에서 이어서 점검할 수 있습니다.

Leave a Comment