Devin.KR
로그인

리눅스 crontab 사용법 - 시간 설정 형식과 예약 작업 등록

개발자 조회 2

이 명령어를 언제 쓰는가

매일 새벽에 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으로 직접 로그를 지우는 대신 쓰는 표준 도구.