Crontab 스케줄러 가이드 — 크론 표현식과 실전 예제

cron이란?

cron은 Linux/Unix에서 반복 작업을 예약 실행하는 시스템 데몬입니다. 백업, 로그 정리, 보고서 생성, 데이터 동기화 같은 정기 작업을 사람이 수동으로 실행하지 않아도 자동으로 처리합니다.

cron 관련 용어를 정리합니다.

용어설명
cron daemon (crond)백그라운드에서 돌아가는 스케줄러 프로세스
crontab크론 작업 목록을 정의하는 설정 파일
cron jobcrontab에 등록된 개별 작업
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이 설정이 더 간편합니다.

이 글이 도움이 되었나요?