수동으로는 성공하고 cron에서만 실패하는 스크립트는 실행 위치가 다를 수 있습니다. 먼저 첫 traceback, 실행 파일의 절대 경로, 현재 작업 디렉터리를 기록합니다. 환경 변수 전체를 로그에 찍으면 토큰이나 DB 비밀번호가 노출될 수 있으므로 필요한 값만 확인합니다.
인터프리터를 고정한 세 번의 실행
Python 3.12.3으로 임시 application 디렉터리에 read.py와 input.txt를 만들었습니다. read.py가 상대 경로 input.txt를 읽을 때 application에서 실행하면 0, 상위 디렉터리에서 실행하면 FileNotFoundError와 1이었습니다. 파일 기준 절대 경로로 바꾸면 상위 디렉터리에서도 0이었습니다. 패키지 설치나 권한 변경은 없었습니다.
from pathlib import Path
import sys
print("interpreter:", sys.executable)
print("cwd:", Path.cwd())
data_file = Path(__file__).resolve().parent / "input.txt"
print(data_file.read_text())
이 예제는 스크립트 옆의 정적 입력 파일에 맞는 방식입니다. 배포 환경의 설정·쓰기 데이터는 명시적인 외부 경로를 인자로 받는 편이 적절할 수 있습니다. 상대 경로의 기준은 Path.cwd 설명과 대조할 수 있습니다. 로그에 출력할 파일 내용은 비밀값이 없는 테스트 자료로 제한하세요.
작업 디렉터리가 맞아도 남는 차이
ModuleNotFoundError라면 cron이 선택한 Python이 수동 실행의 가상환경과 같은지 비교합니다. Permission denied라면 스케줄러의 실행 계정으로 해당 경로 접근을 확인합니다. 네트워크 요청 실패라면 프록시·CA 설정을 별도로 봅니다. cron의 PATH를 넓히는 한 가지 변경으로 이 세 문제를 동시에 설명하지 마세요.
실제 예약에 반영할 때는 인터프리터·스크립트·설정 파일의 절대 경로와 로그 위치를 명시하고, 같은 계정에서 한 번 실행한 뒤 다음 예약 실행의 결과를 확인합니다. 이번 검사는 CWD 차이만 재현했으며 백업의 완전성이나 cron 자체의 성공을 검증하지 않았습니다.