virtual-insanity
← 뒤로

800 운영/810 런북/크론-에러-대응.md

seedling

크론 에러 대응

증상

  • 크론 작업이 예정 시간에 실행되지 않음
  • cron_error_alerted 플래그가 설정되어 텔레그램 알림 수신
  • 특정 작업이 연속 실패하여 자동 비활성화됨
  • jobs.json 파싱 에러 (잘못된 JSON)

원인

  1. jobs.json 구문 오류 — 수동 편집 시 JSON 깨짐
  2. 스크립트 경로 변경 — 파이프라인 스크립트 이동/삭제 후 미갱신
  3. 의존 서비스 장애 — DB, 네트워크, LLM 등 외부 의존 불가
  4. 연속 실패 임계치 초과 — 기본 정책에 의해 작업 자동 비활성화

해결 단계

1. 크론 설정 확인 및 검증

# jobs.json 유효성 검사
python3 -m json.tool ~/.openclaw/cron/jobs.json > /dev/null && echo "JSON OK" || echo "JSON INVALID"

# 전체 작업 수 및 활성 작업 확인
python3 -c "
import json
with open('$HOME/.openclaw/cron/jobs.json') as f:
    jobs = json.load(f)
total = len(jobs)
active = sum(1 for j in jobs if j.get('enabled', True))
print(f'Total: {total}, Active: {active}, Disabled: {total - active}')
"

2. 실패한 작업 로그 확인

# 크론 실패 분석
python3 ~/.openclaw/workspace/scripts/cron_failure_analyzer.py

# 최근 크론 로그
ls -lt ~/.openclaw/workspace/scripts/logs/cron_*.log 2>/dev/null | head -10

3. jobs.json 수정 (atomic read-modify-write)

주의: 직접 에디터로 jobs.json을 열어 수정하지 마세요. 동시 접근 시 데이터 손실 위험.

# 1) 백업
cp ~/.openclaw/cron/jobs.json ~/.openclaw/cron/jobs.json.bak.$(date +%s)

# 2) atomic 수정 (예: 특정 작업 재활성화)
python3 -c "
import json, tempfile, os

JOBS_PATH = os.path.expanduser('~/.openclaw/cron/jobs.json')

with open(JOBS_PATH) as f:
    jobs = json.load(f)

# 예: 'blog_monitor' 작업 재활성화
for j in jobs:
    if j.get('id') == 'blog_monitor':
        j['enabled'] = True
        j.pop('cron_error_alerted', None)
        j['consecutive_failures'] = 0
        print(f'Re-enabled: {j[\"id\"]}')

# atomic write
tmp_fd, tmp_path = tempfile.mkstemp(dir=os.path.dirname(JOBS_PATH))
with os.fdopen(tmp_fd, 'w') as tmp:
    json.dump(jobs, tmp, indent=2, ensure_ascii=False)
os.replace(tmp_path, JOBS_PATH)
print('jobs.json updated atomically')
"

4. cron_error_alerted 플래그 초기화

python3 -c "
import json, tempfile, os

JOBS_PATH = os.path.expanduser('~/.openclaw/cron/jobs.json')

with open(JOBS_PATH) as f:
    jobs = json.load(f)

cleared = 0
for j in jobs:
    if j.get('cron_error_alerted'):
        j['cron_error_alerted'] = False
        j['consecutive_failures'] = 0
        cleared += 1

tmp_fd, tmp_path = tempfile.mkstemp(dir=os.path.dirname(JOBS_PATH))
with os.fdopen(tmp_fd, 'w') as tmp:
    json.dump(jobs, tmp, indent=2, ensure_ascii=False)
os.replace(tmp_path, JOBS_PATH)
print(f'Cleared error alerts for {cleared} jobs')
"

5. 연속 실패로 비활성화된 작업 복구

# 비활성화된 작업 목록 확인
python3 -c "
import json
with open('$HOME/.openclaw/cron/jobs.json') as f:
    jobs = json.load(f)
for j in jobs:
    if not j.get('enabled', True):
        print(f'  DISABLED: {j.get(\"id\")} (failures: {j.get(\"consecutive_failures\", 0)})')
"

비활성화된 작업을 복구하려면 3단계의 수정 스크립트에서 해당 작업 ID를 지정하세요.

확인 방법

# JSON 유효성 재검증
python3 -m json.tool ~/.openclaw/cron/jobs.json > /dev/null && echo "OK"

# 활성 작업 수 확인
python3 -c "
import json
with open('$HOME/.openclaw/cron/jobs.json') as f:
    jobs = json.load(f)
active = [j['id'] for j in jobs if j.get('enabled', True)]
print(f'Active jobs: {len(active)}')
"

# 크론 스모크 테스트
bash ~/.openclaw/workspace/scripts/cron_smoke_test.sh

# 헬스체크
python3 ~/.openclaw/workspace/scripts/health_check.py