cron 트러블슈팅
cron을 처음 쓰는 사람이 가장 많이 겪는 경험이 있습니다. 터미널에서 직접 실행하면 잘 되는데, crontab에 등록하면 실행이 안 됩니다. 로그를 보면 실행은 됐는데 아무 결과가 없습니다.
cron은 터미널과 다른 환경에서 동작합니다. 이 차이를 이해하면 대부분의 문제를 스스로 해결할 수 있습니다.
흔한 실패 원인 5가지
원인 1. PATH 문제.
터미널에서는 ~/.bashrc나 ~/.profile이 로드되어 PATH가 풍부합니다. cron의 기본 PATH는 /usr/bin:/bin뿐입니다. python3, node, pip 같은 명령어가 이 경로에 없으면 실행이 실패합니다.
# 실패하는 경우0 3 * * * python3 /home/ubuntu/scripts/job.py# 해결: 절대 경로 사용0 3 * * * /usr/bin/python3 /home/ubuntu/scripts/job.py# 또는 crontab 상단에 PATH 설정PATH=/usr/local/bin:/usr/bin:/bin:/home/ubuntu/.local/bin0 3 * * * python3 /home/ubuntu/scripts/job.py
어떤 경로를 써야 할지 모르면 터미널에서 which python3로 확인합니다.
원인 2. 실행 권한 없음.
스크립트에 실행 권한이 없으면 cron이 실행할 수 없습니다.
# 실행 권한 확인ls -l /home/ubuntu/scripts/backup.sh# 권한 없으면 추가chmod +x /home/ubuntu/scripts/backup.sh
원인 3. 환경변수 미설정.
스크립트가 HOME, USER, 또는 커스텀 환경변수에 의존한다면 cron 환경에서 값이 없을 수 있습니다.
# crontab 상단에 필요한 환경변수 선언HOME=/home/ubuntuUSER=ubuntuMYAPP_ENV=productionDB_PASSWORD=secret0 3 * * * /home/ubuntu/scripts/deploy.sh
또는 스크립트 내부에서 직접 설정합니다.
#!/usr/bin/env bash# 파일: deploy.sh# cron 환경을 위해 명시적으로 설정export PATH="/usr/local/bin:/usr/bin:/bin"export HOME="/home/ubuntu"source /home/ubuntu/.profile 2>/dev/null || true# 이하 작업...
원인 4. 출력 리다이렉션 누락.
cron은 명령의 출력을 MAILTO로 이메일 발송합니다. 이메일이 설정되지 않은 환경에서는 출력이 그냥 사라집니다. 에러가 나도 알 방법이 없습니다.
# 좋지 않음 (출력 어디 갔는지 모름)0 3 * * * /home/ubuntu/scripts/backup.sh# 출력과 에러 모두 로그 파일에 기록0 3 * * * /home/ubuntu/scripts/backup.sh >> /var/log/backup.log 2>&1
원인 5. 사용자 crontab vs 시스템 crontab 혼동.
crontab -e로 편집하는 것은 현재 사용자의 crontab입니다. 루트 권한이 필요한 작업인데 일반 사용자 crontab에 등록하면 실패합니다.
# 일반 사용자 crontab (현재 사용자 권한으로 실행)crontab -e# 루트 crontab (루트 권한으로 실행)sudo crontab -e# 시스템 crontab (/etc/crontab) - 사용자 지정 가능# 분 시 일 월 요일 사용자 명령어0 3 * * * root /usr/local/bin/backup.sh
cron 디버깅 방법
방법 1. 스크립트 수동 실행으로 기본 동작 확인.
cron 환경을 흉내 내서 스크립트를 실행해봅니다.
# cron이 쓰는 최소 환경으로 실행env -i PATH=/usr/bin:/bin HOME=/home/ubuntu /home/ubuntu/scripts/backup.sh
이렇게 실행했을 때 에러가 나면 스크립트 자체 문제이거나 PATH/환경변수 문제입니다.
방법 2. cron 로그 확인.
Ubuntu에서 cron 실행 기록은 /var/log/syslog에 쌓입니다.
# cron 관련 로그만 필터링grep CRON /var/log/syslog | tail -20# 실시간으로 보기tail -f /var/log/syslog | grep CRON
로그 예시입니다.
Apr 24 09:00:01 myserver CRON[12345]: (ubuntu) CMD (/home/ubuntu/scripts/backup.sh >> /var/log/backup.log 2>&1)
Apr 24 09:00:02 myserver CRON[12346]: (CRON) info (No MTA installed, discarding output)
No MTA installed는 이메일 발송 실패이지 스크립트 실패가 아닙니다. 리다이렉션을 추가하면 됩니다.
방법 3. 스크립트에 로깅 추가.
스크립트 자체에서 실행 여부와 에러를 기록하게 만듭니다.
#!/usr/bin/env bash# 파일: /home/ubuntu/scripts/backup.shLOG="/var/log/backup.log"log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $*" >> "$LOG"}log "=== 백업 시작 ==="log "PATH: $PATH"log "USER: $USER"log "HOME: $HOME"# 실제 작업...log "=== 백업 완료 ==="
실습: 실패하는 cron 찾아 수정
의도적으로 실패하는 crontab 설정을 만들고, 원인을 찾아 수정해봅시다.
먼저 테스트용 스크립트를 만듭니다.
mkdir -p /home/ubuntu/scriptscat > /home/ubuntu/scripts/cron_test.sh << 'EOF'#!/usr/bin/env bashLOG="/tmp/cron_test.log"echo "$(date) - 실행됨, USER=$USER, PATH=$PATH" >> "$LOG"# python3가 PATH에 있는지 확인if command -v python3 &>/dev/null; then echo "$(date) - python3 위치: $(which python3)" >> "$LOG"else echo "$(date) - ERROR: python3를 찾을 수 없음" >> "$LOG"fiEOF# 실행 권한 부여chmod +x /home/ubuntu/scripts/cron_test.sh
crontab에 의도적으로 잘못된 설정을 추가합니다. (2분 후 실행)
crontab -e
다음 줄을 추가합니다 (현재 시각 기준 2분 후로 맞춥니다).
# 잘못된 설정 (PATH 없음)
*/2 * * * * /home/ubuntu/scripts/cron_test.sh
2분 뒤 로그를 확인합니다.
cat /tmp/cron_test.log
출력 예시입니다.
Mon Apr 24 09:02:01 KST 2026 - 실행됨, USER=ubuntu, PATH=/usr/bin:/bin
Mon Apr 24 09:02:01 KST 2026 - ERROR: python3를 찾을 수 없음
PATH가 짧은 것을 확인했습니다. crontab을 수정합니다.
PATH=/usr/local/bin:/usr/bin:/bin
*/2 * * * * /home/ubuntu/scripts/cron_test.sh
다시 2분 뒤 로그를 확인합니다.
Mon Apr 24 09:04:01 KST 2026 - 실행됨, USER=ubuntu, PATH=/usr/local/bin:/usr/bin:/bin
Mon Apr 24 09:04:01 KST 2026 - python3 위치: /usr/bin/python3
이제 정상적으로 python3를 찾습니다. 테스트가 끝나면 crontab에서 해당 줄을 제거합니다.
crontab -e# 추가했던 줄 삭제 후 저장