systemd timer 설정, OnCalendar로 주기 실행하려면

요약

한 줄 답: systemd timer OnCalendar 설정을 사용하여 주기 작업을 실행하려면 서비스와 이름이 짝을 이루는 .timer 유닛을 만들고 [Timer] 섹션에 OnCalendar= 표현식을 지정합니다. 시스템이 꺼져 있어 놓친 실행은 Persistent=true로 보완할 수 있습니다.

cron과 비교하면, systemd timer는 같은 서비스 인프라를 그대로 사용하므로 환경 변수 관리와 journalctl 로그 확인을 통일된 방식으로 처리할 수 있습니다. 이 글은 timer 유닛과 service 유닛을 짝짓는 방법, OnCalendar= 표현식 작성법, 놓친 실행을 Persistent=로 처리하는 방법을 다룹니다.

timer 유닛은 service와 어떻게 짝짓나?

한 줄 답: .timer 파일은 이름이 같은 .service 파일을 기본 실행 대상으로 찾습니다.

예를 들어 backup.timer는 별도로 지정하지 않아도 backup.service를 실행 대상으로 삼습니다. 두 유닛 파일은 각각 다음과 같이 작성합니다.

# /etc/systemd/system/backup.service
[Unit]
Description=Backup job

[Service]
ExecStart=/usr/local/bin/backup.sh
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup.service on a schedule

[Timer]
OnCalendar=daily

[Install]
WantedBy=timers.target

유닛 파일을 저장한 뒤에는 서비스가 아니라 타이머를 활성화합니다.

systemctl enable --now backup.timer

타이머가 정해진 시각에 서비스를 대신 시작해주므로, backup.service 자체는 별도로 enable하지 않는 편이 일반적입니다.

OnCalendar 표현은 어떻게 쓰나?

한 줄 답: OnCalendar=요일 연-월-일 시:분:초 형식을 따르며, *는 임의의 값을 나타냅니다.

자주 쓰는 표현은 다음과 같습니다.

  • 매일 자정: OnCalendar=*-*-* 00:00:00 (단축 표현 OnCalendar=daily도 같은 의미입니다.)
  • 매주 월요일 오전 9시: OnCalendar=Mon *-*-* 09:00:00
  • 매시간: OnCalendar=hourly

표현식을 실행 전에 검증하려면 systemd-analyze calendar 명령으로 다음 실행 시각을 미리 확인합니다.

systemd-analyze calendar "Mon *-*-* 09:00:00"

이 명령은 유닛을 실제로 등록하지 않고도 표현식이 의도한 시각과 일치하는지 미리 확인할 수 있어 편리합니다.

놓친 실행을 Persistent로 어떻게 다루나?

한 줄 답: [Timer] 섹션에 Persistent=true를 추가하면 시스템이 꺼져 있어 놓친 실행을 부팅 직후에 대신 실행합니다.

예정된 실행 시각에 시스템이 종료되어 있었다면 해당 실행은 그대로 지나갑니다. Persistent=true를 지정하면 타이머는 마지막 실행 시각을 기록해두고, 다음 부팅 시 놓친 실행이 있었는지 확인해 즉시 실행합니다.

# /etc/systemd/system/backup.timer
[Timer]
OnCalendar=daily
Persistent=true

이 동작은 cron 환경에서 anacron이 하는 역할과 비슷합니다. 서버가 항상 켜져 있지 않은 환경에서 주기 작업을 놓치지 않으려면 이 옵션을 함께 지정하는 편이 안전합니다.

타이머 상태와 로그는 어떻게 확인하나?

한 줄 답: systemctl list-timers로 다음 실행 시각을 확인하고, journalctl로 서비스 실행 로그를 확인합니다.

현재 등록된 타이머와 다음/이전 실행 시각은 다음 명령으로 확인합니다.

systemctl list-timers --all

타이머 자체는 실행 트리거만 담당하므로, 실제 작업 로그는 타이머가 호출하는 서비스 쪽에서 확인합니다.

journalctl -u backup.service

타이머가 예상대로 동작하지 않을 때는 먼저 list-timers로 다음 실행 예정 시각이 맞는지 확인한 뒤, journalctl로 서비스가 실제로 실행되었는지 대조하는 순서가 편리합니다.

자주 묻는 질문은 무엇인가?

타이머 이름과 서비스 이름이 다르면 어떻게 됩니까?

[Timer] 섹션에 Unit= 옵션으로 대상 서비스를 직접 지정할 수 있습니다.

cron 대신 꼭 timer를 써야 합니까?

필수는 아니지만, systemd 서비스 인프라와 로그를 그대로 쓰려면 timer가 유리합니다.

표현식이 맞는지 어떻게 미리 확인합니까?

systemd-analyze calendar로 다음 실행 시각을 미리 확인합니다.

정리하면 어떻게 되나?

timer 유닛은 이름이 같은 service 유닛을 기본 대상으로 삼고, OnCalendar= 표현식으로 실행 시각을 지정합니다. 여기에 Persistent=true를 더하면 시스템이 꺼져 있던 동안 놓친 실행도 부팅 후 보완할 수 있습니다.