"손으로 실행하면 되는데 cron에 넣으면 안 돈다." cron 디버깅의 90%는 이 한 문장입니다. cron은 여러분의 로그인 셸이 아니라, 거의 비어 있는 환경에서 명령을 실행합니다. 추측 말고 로그부터 봅니다.
1단계 — cron이 실행을 시도하긴 했나 (로그)
먼저 cron 데몬이 그 줄을 실행하려 했는지 확인합니다.
로컬 터미널
# RHEL/CentOS 계열
grep CRON /var/log/cron
# Debian/Ubuntu 계열
grep CRON /var/log/syslog
journalctl -u cron # systemd 환경
로그에 해당 시각의 실행 기록이 없다면 스케줄 표현식이나 crontab 등록 자체가 문제입니다. 기록은 있는데 결과만 없다면 명령 실행 환경의 문제입니다.
2단계 — 등록과 시간 표현식 확인
로컬 터미널
crontab -l # 현재 사용자 crontab
sudo crontab -l -u www-data # 다른 사용자로 등록한 경우
흔한 함정: root로 등록해야 할 작업을 일반 사용자 crontab에 넣음, 시스템 /etc/crontab은 5필드 뒤에 사용자 필드가 하나 더 필요한데 빠뜨림.
원인별 해결
- PATH가 다름: cron의 PATH는 보통
/usr/bin:/bin뿐.node,docker등이 안 잡힘 → 명령을 절대 경로로 쓰거나 crontab 상단에PATH=를 명시 - 환경변수 없음:
.bashrc에서 export한 변수는 cron에 없음 → 스크립트 안에서 직접 정의하거나source처리 %가 줄바꿈으로 해석됨: cron에서 이스케이프 안 한%는 개행 취급(date +%Y등) →\%로 이스케이프- 출력이 사라져 원인 안 보임: cron은 stdout/stderr를 메일로 보냄 → 줄 끝에
>> /tmp/job.log 2>&1를 붙여 직접 로그로 남김 - 권한/실행 비트: 스크립트에
chmod +x누락, 또는 상대 경로로 만든 파일이 엉뚱한 cwd(보통 홈)에 생성
가장 확실한 재현법
cron과 같은 빈 환경으로 직접 돌려보면 차이가 드러납니다.
로컬 터미널
env -i /bin/sh -c '/path/to/job.sh' # 환경변수 비우고 실행
체크리스트
로컬 터미널
grep CRON /var/log/cron # 실행을 시도했나
crontab -l # 등록·표현식 확인
# crontab 줄 끝에 로그 리다이렉트 추가:
# * * * * * /path/job.sh >> /tmp/job.log 2>&1
env -i /bin/sh -c '/path/job.sh' # 빈 환경 재현
cron의 환경·PATH·권한 차이를 직접 끊어보고 운영 스케줄을 다루는 실습은 리눅스 트랙에서 회원가입 없이 무료로 익힐 수 있습니다.