Linux 강좌 / cron과 systemd 타이머로 정기 작업 자동화하기
리눅스의 정기 작업은 간단한 일정에는 cron, 서비스 상태·로그와 함께 관리할 작업에는 systemd 타이머를 사용할 수 있습니다. 등록됐다는 사실만 확인하지 말고 예약 해석, 실제 실행 기록, 결과 파일과 실패 상태를 각각 확인해야 합니다.
예약할 명령은 Bash 스크립트 기초처럼 직접 실행해 결과를 확인한 뒤 등록하세요. 사용자 systemd 관리자의 로그아웃 이후 동작과 linger 설정은 실제 VM에서 확인해야 하며, 타이머 등록만으로 계속 실행된다고 가정하지 않습니다.
시스템 설정 실습의 기준은 Ubuntu 26.04 LTS와 Rocky Linux 9 계열의 일반 설치 VM입니다. 컨테이너·WSL·다른 릴리스에서는 서비스와 패키지 구성이 다를 수 있습니다. 가상 머신 실습 환경 만들기에서 콘솔 복구와 버전 확인을 먼저 준비하세요.
cron과 타이머의 선택 기준
| 기준 | cron | systemd 타이머 |
|---|---|---|
| 설정 단위 | 시간 필드와 명령 한 줄 | timer와 service 유닛 |
| 실행 확인 | 작업 출력·배포판별 로그 | 서비스 상태·저널 |
| 환경 | 로그인 셸과 다른 제한된 환경 | 유닛에 정한 실행 환경 |
| 놓친 일정 | 일반 cron은 보통 소급하지 않음 | OnCalendar와 Persistent 설정 검토 |
cron 데몬 이름과 설치 여부는 배포판마다 다릅니다. Ubuntu에서는 보통 cron, Rocky Linux에서는 cronie·crond를 사용합니다. systemd 타이머 예제는 사용자 systemd 관리자가 실행되는 환경이 필요합니다. 일반 cron의 동작과 anacron 같은 보완 도구의 동작도 구분해야 합니다.
cron 표현식과 환경을 먼저 읽기
crontab -e는 현재 사용자의 작업을 편집합니다. 사용자 crontab의 다섯 시간 필드는 분·시·일·월·요일이며 뒤에는 명령이 옵니다. 아래는 매일 02:15에 실행하는 형식 예시로, /home/USER를 실제 절대 경로로 바꿔야 합니다. /etc/crontab은 명령 앞에 사용자 필드가 추가되는 별도 형식입니다.
15 2 * * * /bin/bash /home/USER/bin/job.sh >> /home/USER/job.log 2>&1
cron은 터미널의 PATH, 현재 디렉터리, 환경 변수를 그대로 상속하지 않습니다. 절대 경로를 쓰고 스크립트 안에서 작업 디렉터리를 정하며 비밀값을 crontab에 직접 나열하지 마세요. 일과 요일을 동시에 제한하면 구현의 OR 조건 때문에 기대와 다른 날에도 실행될 수 있습니다. 시간대·일광 절약 시간과 백분율 문자의 특별 처리도 사용하는 cron 매뉴얼에서 확인합니다.
사용자 서비스와 타이머 파일 만들기
아래 이름의 유닛이 이미 있다면 덮어쓰지 말고 다른 실습 이름을 사용합니다. 이 예제는 1분 간격으로 날짜를 저널에 출력하며 시스템 서비스나 root 권한이 필요하지 않습니다. /usr/bin/date 경로는 먼저 command -v date로 확인하고 실제 경로가 다르면 ExecStart를 맞춥니다.
mkdir -p "$HOME/.config/systemd/user"
cat > "$HOME/.config/systemd/user/linux-course-clock.service" <<'EOF'
[Unit]
Description=Linux course timestamp exercise
[Service]
Type=oneshot
ExecStart=/usr/bin/date --iso-8601=seconds
EOF
cat > "$HOME/.config/systemd/user/linux-course-clock.timer" <<'EOF'
[Unit]
Description=Run the course clock every minute
[Timer]
OnCalendar=*-*-* *:*:00
AccuracySec=1s
Persistent=true
[Install]
WantedBy=timers.target
EOF
systemd-analyze calendar '*-*-* *:*:00'
systemctl --user daemon-reload
systemctl --user enable --now linux-course-clock.timer
같은 기본 이름의 timer는 대응하는 service를 실행합니다. OnCalendar는 달력 기반 일정이고 AccuracySec는 실행을 모을 수 있는 허용 폭이며 실시간 실행을 보장하지 않습니다. Persistent=true는 정지 중 놓친 일정이 있으면 재활성화 때 보완 실행을 시도하지만 놓친 횟수만큼 모두 실행하지는 않습니다.
다음 실행 시각과 실제 실행 결과 확인하기
systemctl --user list-timers --all linux-course-clock.timer
systemctl --user status linux-course-clock.timer
journalctl --user -u linux-course-clock.service --since "5 minutes ago" --no-pager
systemctl --user show linux-course-clock.service -p Result -p ExecMainStatus
timedatectl
다음 실행 시각을 확인한 뒤 1~2분이 지나면 저널에서 날짜 출력과 종료 기록을 봅니다. oneshot 서비스는 작업이 끝나면 inactive 상태여도 성공했을 수 있으므로 Result와 ExecMainStatus를 함께 확인합니다. timedatectl의 시간대와 시각 동기화 상태를 보고 서버의 현지 시간과 원하는 업무 시간대가 일치하는지 검토하세요.
로그아웃 뒤에도 사용자 작업이 계속되어야 한다면 사용자 관리자 수명과 linger 정책을 확인해야 합니다. 단순히 enable했다는 이유로 로그아웃 이후·재부팅 이후 모든 조건에서 실행된다고 가정하지 마세요. 시스템 타이머로 운영할 때는 전용 계정, 절대 경로, 최소 권한과 자원 제한을 별도로 설계합니다.
중복 실행·실패를 관리하고 실습 해제하기
일반 cron 작업이 주기보다 오래 걸리면 다음 실행과 겹칠 수 있으므로 지원되는 환경에서 flock 등 잠금 방식을 검토합니다. systemd 타이머가 이미 실행 중인 같은 서비스 유닛을 다시 활성화하려 해도 별도의 두 인스턴스를 자동 생성하지는 않습니다. 그러나 다른 유닛·수동 실행과 자원을 공유할 수 있으므로 애플리케이션 수준의 동시 실행 조건은 여전히 필요합니다.
systemctl --user disable --now linux-course-clock.timer
rm -- "$HOME/.config/systemd/user/linux-course-clock.timer" "$HOME/.config/systemd/user/linux-course-clock.service"
systemctl --user daemon-reload
systemctl --user list-timers --all linux-course-clock.timer
제거 명령은 이 실습에서 만든 두 파일만 대상으로 합니다. cron 실습 줄을 추가했다면 crontab -e로 그 줄만 삭제하고 crontab -l로 확인합니다. 기존 전체 crontab을 지우지 마세요. 실제 자동화에서는 성공 알림보다 실패·미실행을 발견할 수 있는 별도 점검과 복구 절차가 중요합니다.




