가이드 / crontab 트러블슈팅
crontab이 안 돌아갈 때
확인할 것 10가지 (실전 체크리스트)
“터미널에서 직접 돌리면 되는데 cron으로는 안 돼요” — 서버 운영에서 제일 흔한 미스터리입니다. 원인은 거의 항상 아래 10가지 중 하나예요. 위에서부터 순서대로 확인해 보세요.
1. cron 데몬이 살아있나
systemctl status cron # Ubuntu/Debian
systemctl status crond # RHEL/CentOSactive (running)가 아니면 sudo systemctl start cron. 의외로 재부팅 후 데몬이 안 뜬 케이스가 있습니다.
2. 애초에 실행 시도는 됐나 — 로그부터
grep CRON /var/log/syslog | tail -20 # Ubuntu
journalctl -u cron --since today # systemd 계열로그에 실행 기록이 있는데 결과가 없다 → 스크립트 문제(3~7번). 기록 자체가 없다 → 스케줄/데몬 문제(1, 8~10번). 이 구분이 절반을 줄여줍니다.
3. PATH가 다르다 (가장 흔한 원인)
cron은 로그인 셸이 아니라서 PATH가 /usr/bin:/bin 수준으로 빈약합니다. 터미널에서 되던 node, docker, aws 같은 명령이 cron에서는 command not found가 돼요.
# 어느 위치인지 확인
which node # /usr/local/bin/node
# crontab에서는 절대경로로
0 4 * * * /usr/local/bin/node /home/ubuntu/job.js
# 또는 crontab 맨 위에 PATH 선언
PATH=/usr/local/bin:/usr/bin:/bin4. 상대경로로 파일을 읽고 있다
cron의 작업 디렉터리는 홈(~)입니다. 스크립트 안에서 ./config.json처럼 상대경로를 쓰면 못 찾아요. 스크립트 첫 줄에 cd /path/to/app을 넣거나 전부 절대경로로 바꾸세요.
5. 실행 권한이 없다
chmod +x /home/ubuntu/backup.sh
ls -l /home/ubuntu/backup.sh # -rwxr-xr-x 인지 확인6. % 문자를 그대로 썼다
crontab에서 %는 “줄바꿈”이라는 특수문자입니다. date +%F를 그대로 쓰면 거기서 명령이 잘려요. \%로 이스케이프하거나, 스크립트 파일 안으로 옮기세요.
# ❌ 안 됨
0 4 * * * pg_dump db > backup-$(date +%F).sql
# ✅ 이스케이프
0 4 * * * pg_dump db > backup-$(date +\%F).sql7. 마지막 줄에 개행이 없다
crontab 파일의 마지막 줄은 반드시 줄바꿈으로 끝나야 합니다. 에디터에 따라 마지막 개행 없이 저장되면 그 줄이 조용히 무시돼요. crontab -e로 열어 맨 끝에 빈 줄 하나 확인.
8. 서버 시간대가 생각과 다르다 (한국인 필독)
클라우드 서버 기본 시간대는 대부분 UTC입니다. 0 4 * * *라고 쓰면 한국 시각 오후 1시에 돕니다. 실제로 저희도 백업 크론이 9시간 어긋난 채 돌던 걸 모니터링 알림으로 발견했어요.
date # 서버가 무슨 시간대인지 먼저 확인
# 해결 1: 시각을 UTC로 환산해 등록 (한국 04:00 = UTC 19:00)
0 19 * * * /home/ubuntu/backup.sh
# 해결 2: 서버 시간대 자체를 변경
sudo timedatectl set-timezone Asia/Seoul⚠️ CRON_TZ=Asia/Seoul은 RHEL 계열(cronie)에서만 동작합니다. 우분투/데비안 기본 cron은 CRON_TZ를 지원하지 않아요 — 넣어도 조용히 무시됩니다 (저희가 직접 당한 함정입니다).
9. 사용자 crontab과 /etc/crontab을 혼동했다
/etc/crontab과 /etc/cron.d/는 시각과 명령 사이에 사용자 필드가 하나 더 있습니다 (0 4 * * * root /script.sh). 사용자 crontab(crontab -e) 문법을 그대로 붙여넣으면 안 돌아요. 반대 방향도 마찬가지입니다.
10. 출력을 버려서 에러를 못 보고 있다
> /dev/null 2>&1을 붙여놨다면 에러 메시지도 같이 버려지고 있는 겁니다. 디버깅할 땐 로그 파일로 남기세요:
0 4 * * * /home/ubuntu/backup.sh >> /home/ubuntu/logs/backup.log 2>&1그리고 — 다음번엔 “안 돌았다”를 자동으로 알기
위 10가지는 전부 이미 문제가 생긴 뒤에 찾는 방법입니다. 문제는 cron이 조용히 실패한다는 것 — 며칠 뒤에야 알게 되죠. 크론 끝에 curl 한 줄만 붙이면, 예정 시각에 성공 신호가 안 올 때 디스코드·슬랙·텔레그램으로 바로 알림을 받을 수 있습니다:
0 19 * * * /home/ubuntu/backup.sh && curl -fsS --retry 3 --retry-connrefused https://batch.hkch.co.kr/p/YOUR_TOKEN자세한 방법은 cron 실행 감시 가이드를 참고하세요.