Systemd 타이머 유닛 생성 및 관리 방법

실용적인 `.timer`, `.service`, `systemctl`, `journalctl` 예제를 통해 systemd 타이머 유닛을 생성, 활성화, 모니터링 및 문제 해결하는 방법을 알아봅니다.

Systemd 타이머 유닛 생성 및 관리 방법

Systemd 타이머 유닛은 cron에 의존하지 않고 Linux에서 작업을 예약합니다. 서버에서 백업, 정리 작업, 상태 확인 또는 보고서를 예측 가능한 시간에 실행해야 하는 경우 systemd 타이머는 예약, 서비스 격리, 종속성 처리 및 로그를 한 곳에서 제공합니다.

핵심 아이디어는 간단합니다. .timer 파일은 실행 시점을 정의하고 .service 파일은 실행할 작업을 정의합니다. 이러한 분리를 통해 systemctl로 타이머를 쉽게 검사하고 journalctl로 쉽게 디버깅할 수 있습니다.

Systemd 타이머 유닛 구조 이해하기

systemd 타이머 유닛은 항상 활성화하려는 해당 서비스 유닛(또는 다른 유닛 유형)과 쌍을 이룹니다. 타이머 유닛 자체는 연결된 유닛이 언제 활성화되어야 하는지 정의하고, 서비스 유닛은 수행할 작업을 정의합니다. 두 유닛 모두 일반적으로 동일한 디렉토리(사용자 정의 유닛의 경우 주로 /etc/systemd/system/)에 있습니다.

일반적인 타이머 유닛 파일은 .timer 확장자를 가지며, 연결된 서비스 유닛 파일은 .service 확장자를 갖습니다. 예를 들어 mytask.service에 정의된 작업을 예약하려면 mytask.timer 파일을 생성합니다.

예시: mytask.timer

[Unit]
Description=사용자 정의 작업을 매일 실행

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

주요 섹션을 분석해 보겠습니다.

  • [Unit] 섹션:

    • Description: 타이머에 대한 사람이 읽을 수 있는 설명입니다. 상태 출력에서 식별하는 데 유용합니다.
  • [Timer] 섹션: 타이머 유닛의 핵심으로, 일정을 정의합니다.

    • OnCalendar=daily: 이 지시문은 타이머가 활성화되어야 하는 시점을 지정합니다. daily는 매일 자정을 의미하는 약어입니다. 다른 예시는 다음과 같습니다.
      • hourly: 매시간.
      • weekly: 매주 (Mon *-*-* 00:00:00과 동일).
      • Sun *-*-* 10:00: 매주 일요일 오전 10시.
      • *-*-15 14:30: 매월 15일 오후 2시 30분.
      • Mon..Fri *-*-* 09:00: 평일 오전 9시.
    • Persistent=true: 이 값을 true로 설정하면 시스템이 꺼져 있는 동안 이벤트가 발생한 경우 타이머가 가능한 한 빨리 활성화됩니다. OnCalendar 타이머의 경우 예약된 시간에 시스템이 꺼져 있었다면 시스템이 부팅되고 타이머가 활성화될 때 타이머가 한 번 트리거됨을 의미합니다.
    • OnBootSec=: 시스템 부팅 후 지정된 시간이 지나면 타이머를 활성화합니다. 예를 들어 OnBootSec=15min은 부팅 후 15분 후에 트리거됩니다.
    • OnUnitActiveSec=: 활성화하는 유닛이 마지막으로 활성화된 후 지정된 시간이 지나면 타이머를 활성화합니다. 예를 들어 OnUnitActiveSec=1h는 연결된 서비스가 마지막으로 활성화된 후 1시간 후에 다른 실행을 예약합니다.
    • OnUnitInactiveSec=: 활성화하는 유닛이 마지막으로 비활성화된 후 지정된 시간이 지나면 타이머를 활성화합니다.
    • AccuracySec=: 타이머의 정확도를 지정합니다. Systemd는 이벤트가 이 시간 창 내에 있는 경우에만 타이머를 위해 시스템을 깨우려고 시도하여 전력 소비를 줄이는 데 도움을 줍니다. 기본값은 1min입니다.
    • RandomizedDelaySec=: 타이머 트리거에 지정된 기간까지 무작위 지연을 추가합니다. 부하 분산에 유용합니다.
  • [Install] 섹션: 이 섹션은 타이머 유닛을 활성화하는 방법을 정의합니다.

    • WantedBy=timers.target: 이 지시문은 타이머가 활성화될 때 모든 활성 타이머를 포함하는 표준 대상인 timers.target의 일부가 되도록 합니다. 즉, 활성화되면 타이머가 부팅 시 자동으로 시작됩니다.

예시: mytask.service

[Unit]
Description=내 사용자 정의 작업 서비스

[Service]
Type=oneshot
ExecStart=/usr/local/bin/my_custom_script.sh
User=myuser
Group=mygroup

[Install]
WantedBy=multi-user.target
  • [Unit] 섹션:

    • Description: 서비스에 대한 설명입니다.
  • [Service] 섹션: 서비스 자체를 정의합니다.

    • Type=oneshot: 한 번 실행되고 종료되는 작업에 적합합니다. 장기 실행 데몬에는 다른 유형이 있습니다.
    • ExecStart: 실행할 명령입니다. 스크립트에 실행 권한이 있는지 확인하십시오.
    • User/Group: 명령을 실행할 사용자와 그룹을 지정합니다. 꼭 필요한 경우가 아니라면 루트로 작업을 실행하지 않는 것이 좋습니다.
  • [Install] 섹션: 이 섹션은 타이머로만 시작되어야 하는 oneshot 서비스에는 일반적으로 필요하지 않습니다. 서비스가 아닌 타이머를 활성화하십시오.

타이머 유닛 생성 및 활성화

systemd 타이머 유닛을 생성하고 관리하려면 다음 단계를 따르십시오.

  1. 서비스 유닛 파일 생성: .service 파일에 작업을 정의합니다. /etc/systemd/system/ (또는 사용자별 타이머의 경우 ~/.config/systemd/user/)에 배치합니다.

    sudo nano /etc/systemd/system/mytask.service
    

    위의 예시 서비스 내용을 붙여넣고 저장합니다.

  2. 타이머 유닛 파일 생성: 해당 .timer 파일에 일정을 정의합니다. 서비스 파일과 동일한 디렉토리에 배치합니다.

    sudo nano /etc/systemd/system/mytask.timer
    

    위의 예시 타이머 내용을 붙여넣고 저장합니다.

  3. Systemd 데몬 다시 로드: 유닛 파일을 생성하거나 수정한 후에는 systemd에 구성을 다시 로드하도록 지시해야 합니다.

    sudo systemctl daemon-reload
    
  4. 타이머 활성화: 부팅 시 타이머가 자동으로 시작되도록 하려면 활성화합니다.

    sudo systemctl enable mytask.timer
    

    참고: 서비스 파일이 오로지 타이머에 의해서만 트리거되도록 의도된 경우에는 활성화하지 않습니다.

  5. 타이머 시작: 타이머를 즉시 시작합니다. 그러면 일정에 따라 실행됩니다.

    sudo systemctl start mytask.timer
    

타이머 유닛 관리 및 모니터링

Systemd는 타이머를 관리하고 모니터링하기 위한 몇 가지 systemctl 명령을 제공합니다.

  • 모든 타이머 나열: 활성 및 비활성 타이머를 모두 확인합니다.

    systemctl list-timers
    

    이 명령은 다음과 같은 출력을 제공합니다.

    NEXT                        LEFT        LAST        PASSED      UNIT          ACTIVATES
    Tue 2023-10-27 08:00:00 UTC 10h left    Wed 2023-10-26 08:00:00 UTC 14h ago       mytask.timer  mytask.service
    

    타이머가 다음에 실행되도록 예약된 시간, 실행까지 남은 시간, 마지막 실행 시간, 활성화하는 서비스를 보여줍니다.

  • 특정 유닛에 대한 타이머 나열: 특정 서비스와 관련된 타이머를 확인하려는 경우.

    systemctl list-timers --all | grep mytask.service
    
  • 타이머 상태 확인: 특정 타이머에 대한 자세한 정보를 얻습니다.

    systemctl status mytask.timer
    

    타이머가 활성 상태인지, 다음 실행 예정 시간, 최근 로그 항목을 표시합니다.

  • 서비스 로그 보기: 타이머가 실행한 작업의 출력 및 상태를 확인하려면 연결된 서비스의 로그를 확인합니다.

    journalctl -u mytask.service
    

    실시간으로 로그를 추적할 수도 있습니다.

    journalctl -f -u mytask.service
    
  • 타이머 중지: 타이머를 일시적으로 비활성화해야 하는 경우.

    sudo systemctl stop mytask.timer
    
  • 타이머 비활성화: 부팅 시 타이머가 시작되지 않도록 하고 실행 중이면 중지합니다.

    sudo systemctl disable --now mytask.timer
    

고급 타이머 구성

특정 간격 설정

daily 또는 hourly 대신 더 정확한 간격을 정의할 수 있습니다.

  • 매 N분마다: OnUnitActiveSec=15min (서비스가 마지막으로 활성화된 후 15분 후에 실행).
  • 특정 시간: OnCalendar=*-*-* 02:30:00 (매일 오전 2시 30분에 실행).
  • 조건 결합: OnCalendar=Mon..Fri *-*-* 08:00:00 (평일 오전 8시에 실행).

전력 절약을 위한 AccuracySec 사용

작업이 정확한 순간에 실행될 필요가 없는 경우 AccuracySec 사용을 고려하십시오. 예를 들어 AccuracySec=5min은 systemd에 예약된 시간으로부터 5분 이내에 시스템을 깨워도 괜찮다고 알립니다. 이렇게 하면 systemd가 타이머 이벤트를 묶어 시스템을 더 오랫동안 낮은 전력 상태로 유지할 수 있습니다.

[Timer]
OnCalendar=hourly
AccuracySec=5min

Persistent vs. WakeSystem

  • Persistent=true는 시스템이 꺼져 있어서 OnCalendar 이벤트가 누락된 경우 다음 부팅 시 한 번 실행되도록 합니다. 이는 건너뛰면 안 되는 작업에 중요합니다.
  • WakeSystem=true는 시스템과 하드웨어가 지원하는 경우 systemd가 타이머를 위해 시스템을 절전 모드에서 깨우도록 요청합니다. 이는 시스템이 AC 전원 또는 배터리로 작동 중인지 여부를 결정하는 것과는 다릅니다.

타이머 vs. Cron

기능 Systemd 타이머 Cron
통합 systemd 서비스, 대상과의 긴밀한 통합 독립 실행형 유틸리티
예약 유연함 (달력, 상대적, 부팅 기반) 주로 시간 기반 표현식
로깅 journalctl을 통한 중앙 집중식 분산 (/var/log/syslog, /var/log/cron.log)
오류 처리 서비스 실패에 작업 연결 가능 기본 메일 알림
종속성 다른 서비스가 활성화되어 있어야 함 제한적
실행 특정 사용자, 그룹으로 실행 가능 crontab을 통해 특정 사용자로 실행 가능
전원 관리 전력 절약을 위해 최적화 가능 (AccuracySec) 덜 직접적인 제어

Systemd 타이머를 선택해야 하는 경우:

  • 다른 systemd 서비스와 더 긴밀한 통합이 필요할 때.
  • 중앙 집중식 로깅과 더 쉬운 디버깅이 우선 순위일 때.
  • 더 고급 예약 옵션(예: 마지막 실행 이후 시간)이 필요할 때.
  • 시스템 상태 또는 전원 관리와 관련된 작업의 경우.

Cron이 여전히 선호될 수 있는 경우:

  • systemd를 완전히 채택하지 않은 시스템에서 매우 간단한 독립 실행형 작업의 경우.
  • 다양한 Linux 배포판 및 이전 시스템에서 최대 호환성을 위해.

일반적인 문제 해결

  • 작업이 실행되지 않음:
    • 타이머 상태 확인: systemctl status mytask.timer. Active: activeTriggered... 메시지를 찾습니다.
    • 서비스 로그 확인: journalctl -u mytask.service. 스크립트가 실행 가능하고 오류가 없는지 확인합니다.
    • OnCalendar 구문 확인: systemd-analyze calendar 'your-calendar-string'을 사용하여 테스트합니다.
    • 타이머가 활성화되고 시작되었는지 확인: systemctl list-timers --all.
  • 작업이 너무 일찍/늦게 실행됨:
    • AccuracySecRandomizedDelaySec를 확인합니다.
    • 시스템 시계가 정확한지 확인합니다 (timedatectl status).
  • 권한 오류:
    • .service 파일에 지정된 UserGroup이 스크립트와 액세스하는 모든 파일에 대해 필요한 권한을 가지고 있는지 확인합니다.
    • 사용자가 지정되지 않은 경우 기본값은 root입니다. root 권한은 주의해서 사용하십시오.

결론

작업이 시스템의 서비스 계층에 속하는 경우(백업, 정리 작업, 모니터링 확인, 인증서 갱신 후크 및 기타 운영 작업) systemd 타이머를 사용하십시오. 먼저 서비스를 생성하고, 다음으로 타이머를 생성한 후 systemctl daemon-reload를 실행하고, 타이머를 활성화 및 시작한 다음 systemctl list-timers --alljournalctl -u your.service로 확인하십시오.