개발현황

크레플의 R&D를 소개합니다.

R&D

개발현황

EOFError로 인해 무한 로그가 발생한 문제 해결

  • 관리자
  • 2025.05.12

개요

크레플 내부 시스템에서 발생한 로그 폭주 현상에 대해 원인을 분석하고, 적절한 대응 방안을 적용한 사례를 공유합니다. 본 이슈는 단일 예외가 적절히 처리되지 않아 syslog 로그 파일이 수백 GB까지 증가한 문제로, 시스템 안정성과 운영 효율성 측면에서 중요한 교훈을 제공합니다.

문제 현황

  • 시스템에서 “Filesystem root 용량 부족” 경고 발생
  • /var 디렉토리 사용량이 848GB 이상으로 급증
  • 주요 로그 파일:
    • /var/log/syslog.1: 723GB
    • /var/log/syslog: 118GB
  • syslog에 동일한 에러 메시지가 초당 수십 건 이상 반복 기록됨

원인 분석

문제의 핵심 원인은 Python 실행 스크립트인 app_runner.pyinput() 함수 호출에 있었습니다. 이 코드는 사용자 입력을 요구하는데, 백그라운드 또는 터미널 없는 환경에서 실행될 경우 EOFError가 발생합니다.

해당 예외는 적절한 예외처리 없이 반복되어 매 실행 시마다 로그에 오류 메시지를 기록하게 되었고, 이는 짧은 시간 내 수백 GB의 로그 파일을 생성하는 결과로 이어졌습니다.

조치 내용

1. 임시 조치: 로그 파일 정리

시스템 용량 확보를 위해 다음 명령어로 로그를 삭제 및 초기화했습니다.

$ sudo rm /var/log/syslog.1 /var/log/syslog.2.gz
$ sudo truncate -s 0 /var/log/syslog

⚠️ 주의: truncate 명령은 현재 기록 중인 로그 파일을 비우는 방식으로, 로그 기록의 연속성을 끊기 때문에 권장되지 않는 방식입니다. 반드시 원인 차단이 선행되어야 합니다.

2. 근본 조치: 예외 상황 차단

def run_step(...):
    if not sys.stdin.isatty():
        return

sys.stdin.isatty()는 현재 표준 입력(stdin)이 터미널인지 아닌지를 확인하는 함수입니다. 쉽게 말하면, 사용자와 직접 소통할 수 있는 상태인지를 알려줍니다.

  • 결과가 True → 터미널(콘솔)에서 직접 실행 중
  • 결과가 False → 백그라운드 실행, 파일 리디렉션, 크론탭, 시스템 서비스 등

터미널이 없는 환경에서는 False를 반환하므로, 해당 조건에서 input() 호출을 방지함으로써 EOFError를 차단할 수 있습니다.

3. 로그 정책 검토

  • 시스템 로그는 기본적으로 logrotate를 통해 관리됨
  • 운영 환경에 맞게 로그 보관 주기를 재조정함

기술적 고려사항 및 권장사항

로그 정책

  • 무한 로그 발생 방지를 위해 로그 발생량을 통제하는 구조가 우선되어야 함
  • 로그는 문제 진단 및 추적을 위한 자산이므로 무분별한 삭제보다 선제적 차단과 정책 설정이 중요함

코드 내 입력 처리

  • input()과 같이 사용자 입력을 요구하는 코드는 반드시 실행 환경을 고려하여 사용할 것
  • 터미널 여부 확인 또는 try-except 예외처리로 안정성을 확보해야 함

시스템 운영

  • /var/log 등 주요 디렉토리의 디스크 사용량을 모니터링 및 알림 시스템을 통해 주기적으로 점검
  • 로그 보관 주기 및 회전 설정을 통해 장기적인 저장소 관리 체계 마련

결론

이번 이슈는 단순한 에러 하나가 시스템 전체의 리소스에 얼마나 큰 영향을 줄 수 있는지를 보여주는 사례였습니다.

이러한 문제는 운영환경에서 흔히 발생할 수 있으며, 개발 시 실행 환경을 고려한 설계, 예외 상황에 대한 철저한 대응, 그리고 시스템 로그 정책에 대한 이해가 필수적입니다.

앞으로도 안정적인 시스템 운영을 위해 지속적인 점검과 개선을 이어갈 예정입니다.