리눅스 crontab 사용법 - 시간 설정 형식과 예약 작업 등록
이 명령어를 언제 쓰는가
매일 새벽에 DB를 백업하거나, 5분마다 헬스체크를 돌리거나, 매월 1일에 로그를 정리하는 등 정해진 시각에 반복 실행할 작업을 등록할 때 쓴다.
crontab은 사용자별 예약 작업 목록을 편집·조회하는 명령이다. 파일을 직접 열어 고치는 것이 아니라 반드시 이 명령을 거쳐야 cron 데몬이 변경을 인식한다.
기본 형식
crontab [-u 사용자] [-l | -e | -r]
등록하는 각 줄의 형식은 다음과 같다.
분(0-59) 시(0-23) 일(1-31) 월(1-12) 요일(0-7) 실행할명령
- 요일은 0과 7이 모두 일요일이다.
*는 매번,*/5는 5단위마다,1,15는 나열,1-5는 범위다.- 일과 요일을 둘 다 지정하면 OR로 동작한다.
0 0 1 * 1은 "매월 1일 또는 매주 월요일"이다.
자주 쓰는 옵션과 표기
| 옵션 / 표기 | 의미 | 예시 |
|---|---|---|
-l | 등록된 작업 목록 출력 | crontab -l |
-e | 편집(저장 시 문법 검사 후 반영) | crontab -e |
-r | 전체 삭제(확인 없이 지운다) | crontab -r |
-u 사용자 | 다른 계정의 crontab을 다룸(root 필요) | sudo crontab -l -u deploy |
*/5 * * * * | 5분마다 | 헬스체크 |
0 3 * * * | 매일 새벽 3시 정각 | DB 백업 |
30 2 * * 0 | 매주 일요일 02:30 | 주간 정리 작업 |
0 9 1 * * | 매월 1일 09:00 | 월간 리포트 |
@reboot | 부팅 직후 1회 | @reboot /srv/app/start.sh |
실전 예제
1. 등록된 작업을 확인한다. 서버를 인계받으면 계정별로 다 확인한다. 사용자 crontab은 계정마다 따로 있어서 자기 것만 보면 놓친다.
crontab -l
sudo crontab -l -u deploy
sudo ls -l /etc/cron.d/ /etc/cron.daily/
sudo cat /etc/crontab
2. 매일 새벽 DB를 백업한다. crontab -e로 열고 다음을 추가한다.
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=""
0 3 * * * /usr/local/bin/db-backup.sh >> /var/log/db-backup.log 2>&1
2>&1로 표준오류까지 같은 파일에 남기는 것이 핵심이다. 이게 없으면 실패했을 때 아무 기록도 남지 않는다.
3. 5분마다 헬스체크를 돌리되 중복 실행을 막는다. 앞 작업이 5분 넘게 걸리면 프로세스가 겹쳐 쌓이므로 flock으로 잠근다.
*/5 * * * * /usr/bin/flock -n /tmp/healthcheck.lock /usr/local/bin/healthcheck.sh >> /var/log/healthcheck.log 2>&1
4. 평일 업무시간에만 30분마다 실행한다.
*/30 9-18 * * 1-5 /usr/local/bin/sync-orders.sh >> /var/log/sync-orders.log 2>&1
5. 스크립트를 crontab에 넣기 전에 cron과 같은 환경에서 검증한다. 이 단계를 건너뛰어서 나는 사고가 가장 많다.
env -i /bin/bash --noprofile --norc -c '/usr/local/bin/db-backup.sh; echo "exit=$?"'
환경변수를 모두 비운 채 돌려서 성공하면 cron에서도 대체로 돈다.
6. 작업이 실제로 돌았는지 확인한다. 로그 위치가 배포판마다 다르다.
# Ubuntu/Debian
sudo grep CRON /var/log/syslog
# RHEL/CentOS/Rocky
sudo cat /var/log/cron
# systemd 환경 공통
sudo journalctl -u cron --since today # Debian 계열
sudo journalctl -u crond --since today # RHEL 계열
함정과 주의점
- cron은 로그인 셸의 환경을 물려받지 않는다.
PATH가/usr/bin:/bin수준으로만 잡히고.bashrc도 읽지 않는다. 터미널에서 잘 되던 스크립트가 cron에서만command not found로 죽는 대표 원인이다. 명령은 절대 경로로 쓰고, 필요한 환경변수는 crontab 상단이나 스크립트 안에서 직접 정의한다. Java, Node, Python 가상환경을 쓰는 스크립트라면 특히 주의한다. crontab -r는 확인 없이 전부 지운다.-e옆에 있는 키라 오타로 누르기 쉬운데, 되돌릴 방법이 없다. 편집 전에crontab -l > ~/crontab.bak.$(date +%F)로 백업하는 습관을 들이고, crontab 내용 자체를 git으로 관리하는 편이 안전하다.%는 줄바꿈으로 해석된다.date +%F를 그대로 쓰면date +에서 명령이 끊긴다. 반드시\%로 이스케이프한다.0 3 * * * /usr/bin/mysqldump mydb > /backup/db-$(date +\%F).sql- 출력을 버리지 않으면 메일이 쌓이고, 다 버리면 실패를 모른다.
> /dev/null 2>&1로 완전히 죽이면 장애를 놓친다. 로그 파일에 남기고 그 파일을 모니터링하거나, 최소한 표준오류만은 남긴다. - 사용자 crontab과 시스템 crontab의 형식이 다르다.
/etc/crontab과/etc/cron.d/*는 시각 다섯 칸 뒤에 실행 사용자 칸이 하나 더 있다. 사용자 crontab 형식을 그대로 복사해 넣으면 사용자 이름 자리에 명령이 들어가 실행되지 않는다. - 서버 타임존을 확인한다. UTC로 도는 서버에서
0 3 * * *은 한국 시간 정오다.timedatectl로 확인하고, 필요하면 crontab 상단에CRON_TZ=Asia/Seoul을 지정한다(cron 구현에 따라 지원 여부가 다르다).
함께 보면 좋은 명령어
systemctl list-timers— systemd 타이머로 예약된 작업. 최신 서버는 로그 정리 등을 여기로 옮겼다.flock— 예약 작업의 중복 실행을 막는다.at— 반복이 아니라 한 번만 실행할 작업을 예약한다.logrotate— cron으로 직접 로그를 지우는 대신 쓰는 표준 도구.