cron이란?
cron은 Linux/Unix에서 반복 작업을 예약 실행하는 시스템 데몬입니다. 백업, 로그 정리, 보고서 생성, 데이터 동기화 같은 정기 작업을 사람이 수동으로 실행하지 않아도 자동으로 처리합니다.
cron 관련 용어를 정리합니다.
| 용어 | 설명 |
|---|---|
| cron daemon (crond) | 백그라운드에서 돌아가는 스케줄러 프로세스 |
| crontab | 크론 작업 목록을 정의하는 설정 파일 |
| cron job | crontab에 등록된 개별 작업 |
| cron expression | 실행 시간을 지정하는 5자리 표현식 |
크론 표현식 문법
크론 표현식은 5개의 필드로 실행 시간을 지정합니다.
┌───────────── 분 (0-59)
│ ┌───────────── 시 (0-23)
│ │ ┌───────────── 일 (1-31)
│ │ │ ┌───────────── 월 (1-12)
│ │ │ │ ┌───────────── 요일 (0-7, 0과 7 모두 일요일)
│ │ │ │ │
* * * * * 실행할 명령어
자주 사용하는 패턴입니다.
# 매분 실행
* * * * * /opt/scripts/healthcheck.sh
# 매시 정각 실행
0 * * * * /opt/scripts/hourly-report.sh
# 매일 새벽 3시 실행
0 3 * * * /opt/scripts/daily-backup.sh
# 매주 월요일 오전 9시 실행
0 9 * * 1 /opt/scripts/weekly-report.sh
# 매월 1일 자정 실행
0 0 1 * * /opt/scripts/monthly-cleanup.sh
# 평일(월~금) 오전 8시 실행
0 8 * * 1-5 /opt/scripts/workday-task.sh
# 10분마다 실행
*/10 * * * * /opt/scripts/check-service.sh
# 매일 오전 9시와 오후 6시 실행
0 9,18 * * * /opt/scripts/sync-data.sh
# 1~3월 매일 새벽 2시 실행
0 2 * 1-3 * /opt/scripts/quarterly-job.sh
특수 문자의 의미입니다.
| 문자 | 의미 | 예시 |
|---|---|---|
* | 모든 값 | * * * * * (매분) |
, | 여러 값 | 0,30 * * * * (0분, 30분) |
- | 범위 | 1-5 (월~금) |
/ | 간격 | */15 (15마다) |
crontab 명령어
crontab 파일을 편집하고 관리하는 명령어입니다.
# 현재 사용자의 crontab 편집
crontab -e
# 현재 사용자의 crontab 목록 확인
crontab -l
# 0 3 * * * /opt/scripts/daily-backup.sh
# */10 * * * * /opt/scripts/healthcheck.sh
# 특정 사용자의 crontab 확인 (root 권한 필요)
sudo crontab -u deploy -l
# crontab 전체 삭제 (주의!)
crontab -r
# 삭제 전 확인 프롬프트
crontab -ri
crontab에서 환경변수를 설정하는 방법입니다.
# crontab 환경변수 설정 (crontab -e로 편집)
# cron은 최소한의 환경에서 실행되므로 PATH 지정 필수
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=admin@example.com
# 환경변수 파일을 로드하여 실행
0 3 * * * source /opt/my-app/.env && /opt/scripts/backup.sh
# 또는 절대 경로로 명시
0 3 * * * /usr/bin/env bash -c 'source /opt/my-app/.env && /opt/scripts/backup.sh'
MAILTO를 설정하면 cron 작업의 출력(stdout/stderr)이 이메일로 전송됩니다. 메일이 불필요하면 출력을 리다이렉트하세요.
로그 확인
cron 작업이 실행되었는지, 에러가 발생했는지 확인하는 방법입니다.
# cron 데몬 로그 (Ubuntu/Debian)
sudo grep CRON /var/log/syslog
# Mar 5 03:00:01 server CRON[1234]: (deploy) CMD (/opt/scripts/daily-backup.sh)
# cron 데몬 로그 (CentOS/RHEL)
sudo grep CRON /var/log/cron
# 최근 cron 실행 기록만 확인
sudo grep CRON /var/log/syslog | tail -20
# 특정 사용자의 cron 실행 기록
sudo grep "CRON.*deploy" /var/log/syslog
cron 작업 자체의 출력을 로그 파일로 저장하는 패턴입니다.
# stdout과 stderr를 모두 로그 파일에 기록
0 3 * * * /opt/scripts/backup.sh >> /var/log/my-backup.log 2>&1
# 날짜별 로그 파일 생성
0 3 * * * /opt/scripts/backup.sh >> /var/log/backup-$(date +\%Y\%m\%d).log 2>&1
# 출력 완전 무시 (비권장 — 에러 추적 불가)
0 3 * * * /opt/scripts/backup.sh > /dev/null 2>&1
crontab에서 %는 줄바꿈으로 해석됩니다. 명령어 안에서 %를 사용하려면 반드시 \%로 이스케이프해야 합니다.
실전 자동화 예제
데이터베이스 백업 스크립트
#!/bin/bash
# /opt/scripts/backup-db.sh
# PostgreSQL 일간 백업 스크립트
# 환경변수
BACKUP_DIR="/opt/backups/db"
DB_NAME="myapp_production"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=7
# 백업 디렉토리 생성
mkdir -p "${BACKUP_DIR}"
# pg_dump로 백업 (gzip 압축)
pg_dump "${DB_NAME}" | gzip > "${BACKUP_DIR}/${DB_NAME}_${DATE}.sql.gz"
# 백업 성공 여부 확인
if [ $? -eq 0 ]; then
echo "[$(date)] 백업 성공: ${DB_NAME}_${DATE}.sql.gz"
# 오래된 백업 삭제 (7일 이전)
find "${BACKUP_DIR}" -name "*.sql.gz" -mtime +${RETENTION_DAYS} -delete
echo "[$(date)] ${RETENTION_DAYS}일 이전 백업 정리 완료"
else
echo "[$(date)] 백업 실패: ${DB_NAME}" >&2
exit 1
fi
로그 정리 스크립트
#!/bin/bash
# /opt/scripts/cleanup-logs.sh
# 오래된 로그 파일 정리 스크립트
LOG_DIRS=(
"/var/log/my-app"
"/var/log/nginx"
"/opt/my-app/logs"
)
RETENTION_DAYS=30
for dir in "${LOG_DIRS[@]}"; do
if [ -d "${dir}" ]; then
# 지정 일수보다 오래된 로그 파일 삭제
deleted=$(find "${dir}" -name "*.log" -mtime +${RETENTION_DAYS} -delete -print | wc -l)
# 압축된 로그도 삭제
deleted_gz=$(find "${dir}" -name "*.log.gz" -mtime +${RETENTION_DAYS} -delete -print | wc -l)
echo "[$(date)] ${dir}: ${deleted}개 로그, ${deleted_gz}개 압축 로그 삭제"
fi
done
# 디스크 사용량 보고
echo "[$(date)] 디스크 사용량:"
df -h / | tail -1
crontab 등록
# crontab -e로 등록
# 매일 새벽 3시 DB 백업
0 3 * * * /opt/scripts/backup-db.sh >> /var/log/backup-db.log 2>&1
# 매주 일요일 새벽 4시 로그 정리
0 4 * * 0 /opt/scripts/cleanup-logs.sh >> /var/log/cleanup.log 2>&1
# 5분마다 서비스 헬스체크
*/5 * * * * curl -sf http://localhost:3000/health > /dev/null || systemctl restart my-app
cron 작업 디버깅
cron 작업이 예상대로 동작하지 않을 때 확인할 사항입니다.
# 1. 스크립트에 실행 권한이 있는지 확인
ls -l /opt/scripts/backup-db.sh
chmod +x /opt/scripts/backup-db.sh
# 2. 스크립트를 수동으로 실행하여 에러 확인
/opt/scripts/backup-db.sh
# 3. cron 환경에서 테스트 (최소 환경 시뮬레이션)
env -i SHELL=/bin/bash PATH=/usr/bin:/bin HOME=/home/deploy /opt/scripts/backup-db.sh
# 4. cron 데몬이 실행 중인지 확인
systemctl status cron
# ● cron.service - Regular background program processing daemon
# Active: active (running)
# 5. 크론 표현식 검증 (crontab.guru 사이트 활용)
# https://crontab.guru/#0_3_*_*_*
실전 팁
- 절대 경로 사용: cron은 사용자의
.bashrc/.profile을 로드하지 않아 PATH가 제한적입니다. 스크립트 내 모든 명령어에 절대 경로(/usr/bin/python3)를 사용하거나, 스크립트 상단에 PATH를 명시하세요. - 출력 리다이렉트 필수: cron 작업의 출력을 로그 파일로 리다이렉트(
>> /var/log/xxx.log 2>&1)하지 않으면, 출력이 메일로 쌓이거나 유실됩니다. - 특수 단축 표현:
@reboot(부팅 시),@daily(매일 자정),@hourly(매시 정각),@weekly(매주 일요일 자정),@monthly(매월 1일 자정) 같은 단축 표현도 지원합니다. - 동시 실행 방지: 오래 걸리는 작업은
flock으로 중복 실행을 방지하세요.0 * * * * flock -n /tmp/mylock.lock /opt/scripts/long-task.sh처럼 사용합니다. - systemd timer와 비교: 새 프로젝트에서는 systemd timer도 고려하세요. cron보다 로그 관리가 편리하고, 놓친 실행을 보완하는
Persistent=true옵션을 지원합니다. 다만 간단한 반복 작업은 cron이 설정이 더 간편합니다.