crontab 작성법과 빠른 참조표: 5개 필드와 기호의 의미, 자주 쓰는 예, 등록 명령
"매일 3시에 백업", "5분마다 모니터링 스크립트" 같은 정기 실행은 Linux에서는 crontab에 한 줄만 쓰면 설정할 수 있습니다. 하지만 "분 시 일 월 요일" 5개 필드와 * , - / 기호의 조합은 익숙해지기 전까지 잘못 읽기 쉬워서, 1시간에 60번 실행되거나 7분마다 돌리려던 것이 4분 간격이 되는 사고도 자주 일어납니다. 이 글에서는 crontab 작성법의 기본과 기호의 의미, 그대로 쓸 수 있는 빠른 참조표, crontab -e·-l·-r 사용법, 명령 부분을 쓸 때의 주의점을 예시 중심으로 설명합니다.
crontab 한 줄은 "5개 필드 + 명령"
crontab은 cron이라는 프로그램에 "언제 무엇을 실행할지"를 알려 주는 설정 파일입니다. 한 줄이 하나의 일정이며, 맨 앞에 시각을 나타내는 값 5개를 공백으로 구분해 나열하고 그 뒤에 실행할 명령을 씁니다.
| 순서 | 필드 | 쓸 수 있는 값 | 예 |
|---|---|---|---|
| 1번째 | 분 | 0~59 | 30 → 30분 |
| 2번째 | 시 | 0~23(24시간제) | 9 → 9시, 21 → 21시 |
| 3번째 | 일 | 1~31 | 1 → 1일 |
| 4번째 | 월 | 1~12(JAN~DEC도 가능) | 4 → 4월 |
| 5번째 | 요일 | 0~7(0과 7이 일요일, SUN~SAT도 가능) | 1 → 월요일, 5 → 금요일 |
예를 들어 "30 3 * * * /home/user/backup.sh"는 "분이 30, 시가 3, 일·월·요일은 상관없음"이므로 매일 3:30에 backup.sh를 실행한다는 뜻입니다. 순서는 "작은 단위에서 큰 단위로"이지만 요일만 맨 뒤에 온다는 점에 주의하세요. 시와 분의 순서를 반대로 쓰는 실수(9시 30분인데 "9 30"으로 쓰기)가 매우 많은데, 이 경우 "매일 30시 9분"이 되고 시 필드에 30은 쓸 수 없으므로 오류가 납니다.
기호의 의미: * , - / 4개만 알면 읽을 수 있다
숫자 외에 cron 식에서는 기호 4개를 씁니다. 어느 필드에서나 같은 의미로 쓰이므로 이 4개만 알면 대부분의 식을 읽을 수 있습니다.
| 기호 | 의미 | 예 | 예의 해석 |
|---|---|---|---|
| * | 모두(그 필드에서 제한하지 않음) | 0 9 * * * | 매일 9:00 |
| , | 여러 값을 나열 | 0 9,18 * * * | 매일 9:00과 18:00 |
| - | 범위(~부터 ~까지) | 0 9 * * 1-5 | 월~금 9:00 |
| / | 간격(~마다) | */15 * * * * | 매시 0·15·30·45분 |
| -와 / 조합 | 범위 안에서 간격 | 0 9-17/2 * * * | 9·11·13·15·17시 정각 |
| ,와 - 조합 | 범위를 여러 개 | 0 9 * * 1-3,5 | 월·화·수·금 9:00 |
/는 "그 필드의 첫 값부터 n씩 센다"는 뜻입니다. "*/15"는 "0부터 15씩"이므로 0·15·30·45분, "5-59/15"라면 5·20·35·50분이 됩니다. "15분이 지나면 다음"이라는 타이머가 아니라 어디까지나 "그 숫자의 분에 실행한다"는 지정이라고 이해해 두면 뒤에 나오는 함정을 피할 수 있습니다.
또한 @daily(매일 0:00), @hourly(매시 0분), @weekly(일요일 0:00), @monthly(매월 1일 0:00), @yearly(1월 1일 0:00), @reboot(부팅 시 1회)처럼 5개 필드 대신 쓸 수 있는 짧은 표기도 있습니다. 읽기 쉬운 대신 시각이 0:00으로 고정되므로 자정에 다른 처리와 겹치기 쉽다는 점에 주의하세요.
그대로 쓸 수 있는 crontab 빠른 참조표
자주 쓰는 지정을 목록으로 정리했습니다. 시각은 서버 시간대 기준입니다. 명령 부분은 생략했으니 식 뒤에 실행할 명령을 이어서 쓰세요.
| 하고 싶은 것 | cron 식 | 보충 |
|---|---|---|
| 1분마다 | * * * * * | 하루 1,440번 실행 |
| 5분마다 | */5 * * * * | 매시 0·5·10…55분 |
| 10분마다 | */10 * * * * | 매시 0·10·20…50분 |
| 30분마다 | */30 * * * * | 매시 0분과 30분 |
| 1시간마다(매시 정각) | 0 * * * * | @hourly와 같음 |
| 2시간마다 | 0 */2 * * * | 0·2·4…22시 |
| 6시간마다 | 0 */6 * * * | 0·6·12·18시 |
| 매일 0:00 | 0 0 * * * | @daily와 같음 |
| 매일 3:30(야간 배치) | 30 3 * * * | 자정 정각을 피하면 덜 붐빈다 |
| 매일 9:00과 18:00 | 0 9,18 * * * | 분이 같은 시각은 합칠 수 있다 |
| 평일(월~금) 9:00 | 0 9 * * 1-5 | |
| 평일 9~18시 30분마다 | */30 9-18 * * 1-5 | 18:30에도 실행된다 |
| 토·일 10:00 | 0 10 * * 0,6 | 일요일은 0이든 7이든 된다 |
| 매주 월요일 9:00 | 0 9 * * 1 | |
| 매주 금요일 17:30 | 30 17 * * 5 | |
| 매월 1일 0:00 | 0 0 1 * * | @monthly와 같음 |
| 매월 1일과 15일 9:00 | 0 9 1,15 * * | |
| 분기 첫날(1·4·7·10월 1일) | 0 0 1 */3 * | |
| 매년 1월 1일 0:00 | 0 0 1 1 * | @yearly와 같음 |
| 부팅할 때 1회 | @reboot | crontab(Linux)만의 표기 |
"매월 말일", "매월 둘째 화요일", "마지막 금요일"처럼 crontab의 5개 필드만으로는 정확히 쓸 수 없는 지정도 있습니다. 이런 것은 명령 쪽에서 날짜를 확인하는 방식이 필요하며, cron의 날짜·요일 OR 규칙과 n번째 요일·월말 작성법에서 자세히 설명합니다.
*/7은 7분마다가 아니다: 간격 지정의 함정
"*/n"은 "0부터 n씩 세다가 그 필드의 최댓값을 넘으면 끝"이라는 뜻입니다. 분 필드라면 0~59 안에서 세므로 60의 약수가 아닌 수를 지정하면 매시 0분에서 간격이 무너집니다.
| 식 | 실제로 실행되는 시각 | 무너지는 지점 |
|---|---|---|
| */7 * * * * | 매시 0·7·14·21·28·35·42·49·56분 | 56분 → 다음 0분까지 4분 간격 |
| */25 * * * * | 매시 0·25·50분 | 50분 → 다음 0분까지 10분 간격 |
| */45 * * * * | 매시 0·45분 | 45분 → 다음 0분까지 15분 간격 |
| 0 */5 * * * | 0·5·10·15·20시 | 20시 → 다음 날 0시까지 4시간 간격 |
| 0 */7 * * * | 0·7·14·21시 | 21시 → 다음 날 0시까지 3시간 간격 |
분이라면 1·2·3·4·5·6·10·12·15·20·30, 시라면 1·2·3·4·6·8·12처럼 60이나 24의 약수라면 간격이 고르게 됩니다. 그 밖의 간격으로 꼭 고르게 실행하고 싶다면 cron을 1분마다나 1시간마다 실행하고, 스크립트 안에서 지난번 실행 후 경과 시간을 보고 실행할지 정하는 방식으로 씁니다.
crontab -e·-l·-r 사용법과 실수로 지우지 않기 위한 주의
crontab 설정은 파일을 직접 여는 것이 아니라 crontab 명령으로 편집합니다. 사용자마다 별도의 crontab이 있으며, 명령을 실행한 사용자의 설정이 대상이 됩니다.
- 1
crontab -l로 현재 설정을 확인한다
등록된 줄이 모두 표시됩니다. 아무것도 등록되어 있지 않으면 "no crontab for 사용자명"이 나옵니다. 편집 전에 crontab -l > ~/crontab.bak으로 백업해 두면 안심입니다.
- 2
crontab -e로 편집한다
편집기가 열리면 한 줄에 일정 하나씩 쓰고 저장·종료합니다. 저장하는 순간 cron에 반영되며 cron을 재시작할 필요는 없습니다. 형식에 오류가 있으면 저장할 때 오류가 나고 다시 편집할지 묻습니다.
- 3
마지막 줄 뒤에 줄바꿈을 넣는다
마지막 줄에 줄바꿈이 없으면 그 줄을 읽지 않는 cron 구현이 있습니다. 마지막 줄 뒤에서 Enter를 누른 다음 저장하는 습관을 들이세요.
- 4
root나 다른 사용자의 설정은 sudo crontab -u
sudo crontab -u www-data -l처럼 -u로 대상 사용자를 지정합니다. 어떤 사용자로 등록했는지에 따라 파일 권한과 쓸 수 있는 환경 변수가 달라집니다.
참고로 /etc/crontab이나 /etc/cron.d/ 아래의 파일은 형식이 조금 달라서 5개 필드와 명령 사이에 "실행할 사용자명" 필드가 들어갑니다(예: 30 3 * * * root /usr/local/bin/backup.sh). 사용자 crontab과 같은 형식으로 복사하면 명령 이름이 사용자명으로 읽혀 실행되지 않습니다.
명령 부분을 쓸 때의 4가지 주의점
시각의 5개 필드가 맞더라도 명령을 쓰는 방식 때문에 "직접 실행하면 되는데 cron에서는 안 된다"는 일이 자주 있습니다. cron은 로그인했을 때와 다른 최소한의 환경에서 명령을 실행하기 때문입니다.
- 명령과 파일은 절대 경로로 쓴다. cron의 PATH는 /usr/bin:/bin 정도뿐이라 /usr/local/bin 등에 있는 명령은 찾지 못한다
- %는 이스케이프한다. crontab 명령 안의 %는 줄바꿈으로 취급되므로 date +%Y%m%d는 date +\%Y\%m\%d로 쓴다
- 출력을 로그로 남긴다. 끝에 ">> /var/log/backup.log 2>&1"을 붙이면 오류까지 포함해 이어 쓰기로 기록할 수 있다
- 셸은 /bin/sh. bash 전용 문법([[ ]]나 배열 등)을 쓰려면 bash 스크립트로 만들고 첫 줄에 #!/bin/bash를 쓴다
이를 반영하면, 예를 들어 "평일 9:00에 날짜가 들어간 파일명으로 보고서를 출력하는" 설정은 "0 9 * * 1-5 /usr/local/bin/report.sh > /home/user/report-$(date +\%Y\%m\%d).txt 2>&1"처럼 됩니다. 그래도 실행되지 않을 때 조사하는 방법은 cron이 실행되지 않는 원인 체크리스트에서 순서대로 설명합니다.
쓴 식이 의도대로인지 확인하려면 cron 식 검사기에 crontab 줄을 그대로 붙여 넣는 것이 간편합니다. "평일(월~금) 9:00"처럼 해석해 주고 다음 실행 일시를 10개 나열하므로 요일이나 시각을 잘못 쓴 것을 바로 알아챌 수 있습니다. 명령 부분에서 %의 이스케이프를 빠뜨린 것도 알려 줍니다.
자주 묻는 질문
- crontab에서 5분마다 실행하려면 어떻게 쓰나요?
- "*/5 * * * * 명령"이라고 씁니다. 매시 0·5·10…55분에 실행되어 1시간에 12번, 하루에 288번 실행됩니다. 평일 9~18시에만 실행하려면 "*/5 9-18 * * 1-5"처럼 시와 요일 필드로 범위를 좁힙니다.
- crontab 요일 숫자에서 월요일은 몇 번인가요?
- 0이 일요일, 1이 월요일, 2가 화요일…6이 토요일이며 7도 일요일로 취급됩니다. 평일(월~금)은 1-5, 토·일은 0,6입니다. MON이나 FRI 같은 영어 세 글자로도 쓸 수 있습니다. AWS EventBridge에서는 1이 일요일로 하나 밀리니 주의하세요.
- crontab을 편집하면 cron을 재시작해야 하나요?
- crontab -e로 편집했다면 저장하는 순간 자동으로 반영되므로 재시작할 필요가 없습니다. 서버 시간대를 바꿨을 때는 cron이 예전 시간대로 계속 동작할 수 있으므로 cron(또는 crond) 서비스를 재시작합니다.
- crontab -r로 지운 설정을 복구할 수 있나요?
- crontab -r은 확인 없이 설정을 삭제하며 되돌리는 기능이 없습니다. 백업(crontab -l 출력을 저장한 파일)이 있다면 crontab 파일명으로 되돌릴 수 있습니다. 백업이 없다면 cron 로그(syslog 등)에 남은 실행 기록을 단서로, 어떤 명령이 언제 실행됐는지 보고 다시 써야 합니다.
- "*/7"이 7분마다가 되지 않는 이유는?
- */7은 "0분부터 7씩 세어 59분까지"라는 뜻이라 0·7·14…56분에 실행됩니다. 56분 다음은 63분이 아니라 다음 시간의 0분이므로 그 구간만 간격이 4분이 됩니다. 60의 약수인 5·10·15·20·30 등을 쓰면 간격이 고르게 됩니다.
이 글에서 소개한 도구
함께 읽으면 좋은 글
GitHub Actions cron을 일본 시간으로 실행하기: UTC 변환표와 요일 밀림·지연 대책
GitHub Actions의 schedule에 "0 9 * * 1-5"라고 썼는데 워크플로가 일본 시간 오후 6시에 실행됐다면, 오타가 아니라 GitHub Actions의 cron이 항상 UTC(협정 세계시)로 해석되기 때문입니다. 이 글에서는 일본 시간(JST)을 UTC cron 식으로 바꾸는 계산과 변환표, 오전 0~8시를 지정할 때 생기는 "요일·날짜가 전날로 밀리는" 문제, 한 줄로 쓸 수 없을 때 두 줄로 나누는 방법, schedule이 늦거나 실행되지 않을 때의 원인과 대책을 정리합니다. 한국 표준시(KST)도 UTC+9라서 같은 표를 그대로 쓸 수 있습니다.
글 읽기 →cron의 날짜와 요일은 OR: 둘째 월요일·월말·마지막 금요일·격주를 올바르게 쓰는 법
"매월 첫째 월요일 9시"라는 생각으로 "0 9 1-7 * 1"이라고 썼더니 매주 월요일에 더해 매월 1~7일 매일에도 실행됐다. cron에서 아주 흔한 이 실수는 날짜와 요일을 둘 다 지정하면 "둘 중 하나"에 해당하는 날에 실행된다는 cron 특유의 규칙 때문입니다. 이 글에서는 날짜와 요일이 OR이 되는 원리와 예외, crontab에서 n번째 요일·월말·마지막 금요일·격주를 올바르게 실행하는 방법, AWS EventBridge와 Spring에서 쓸 수 있는 L·#·W 표기까지 실제 실행 날짜 예시와 함께 설명합니다.
글 읽기 →EventBridge cron 식 작성법: ?의 의미·요일 숫자·일본 시간 지정과 crontab에서 바꿔 쓰기
AWS에서 Lambda나 ECS 태스크를 정기 실행할 때 쓰는 EventBridge cron 식은 Linux crontab과 비슷해 보이지만 필드 수, ? 사용법, 요일 숫자, 시간대가 조금씩 다릅니다. crontab 감각으로 "0 9 * * 1-5"라고 쓰면 오류가 나고, 요일 숫자를 그대로 옮기면 하루가 밀리며, 시각은 UTC로 해석되어 9시간 어긋나는 등 걸림돌이 겹칩니다. 이 글에서는 EventBridge cron 식의 6개 필드와 ? 규칙, 요일 숫자, L·W·# 사용법, rate 식과의 차이, 규칙과 Scheduler에서 일본 시간을 다루는 방법, crontab·Kubernetes·Spring·systemd와의 변환표까지 정리합니다.
글 읽기 →