systemd timer?
Timer Unit
- 저번에 리눅스의 부팅과정을 봤을 때 systemd 가 특정 타겟을 보고 그에 맞는 서비스를 실행시킨다고 했었음
- 그리고 그 정보는 서비스 유닛에 작성되어 있다고 했음
- 그거랑 비슷함. 어떤 서비스를 실행시킬 지에 대한 정보가 타이머 유닛에 작성됨
Cron과의 차이점
- 이전 시간에는 Cron에 대해서 다뤘다 보니 차이점을 알아보고 싶어졌음
- cron은 독립적이지만 Timer Unit을 쓰면 systemd에 종속됨
- 그러다보니 기존에 systemd에서 처리해주던 일들과 관련해서 이득을 많이 봄
- 예시 : 실행 실패 확인, 상태 확인, 서비스 의존성 체크 가능 등등
Timer Unit 문법
- cron 보다 기능이 많지만 조건이 있는데, Service Unit이 작성되어 있어야 한다는 점임
- 그리고 Service Unit과 같은 위치에 Timer Unit이 있어야 함
[Unit]
Description=설명
After=특정 타겟 이후에 실행하도록
Requires=특정 타겟을 필요로 함
[Timer]
OnCalendar=정할 시간
Persistent=서버가 꺼져있는동안 이 작업을 실행하지 못했다면, 다시 켜졌을 때 이걸 실행할 것인지?
[Install]
WantedBy=특정 타겟에 도달했을 때 실행하도록- 예시
[Unit]
Description=Run backup daily at 02:00
[Timer]
OnCalendar=*-*-* 02:00:00 # 매일 2시에 작동
Persistent=true # 서버 꺼진 사이에 두시 지나면 켜졌을때 얘 실행됨
[Install]
WantedBy=timers.target # timers 타겟에 포함됨OnCalendar
- 언제마다 작동할 것인지 지정하는 부분
- cron에서 앞에 다섯 자리를 의미함
OnCalendar=YYYY-MM-DD HH:MM:SS- cron처럼 별표를 사용하면 와일드카드의 의미임
특수 문자열
- 특수 문자열은 아래의 표 참고
| systemd timer | 의미 | cron 대응 |
|---|---|---|
minutely | 매 분 | (직접 대응 없음) |
hourly | 매 시간 | @hourly |
daily | 매일 | @daily |
weekly | 매주 | @weekly |
monthly | 매월 | @monthly |
yearly | 매년 | @yearly / @annually |
annually | 매년 | @annually |
quarterly | 분기마다 (3개월) | ❌ (cron에 없음) |
semiannually | 반기마다 (6개월) | ❌ (cron에 없음) |
- 특수 문자열 사용 예시
OnCalendar=weekly Mon 09:00:00 # 매주 월요일 오전 9시에 실행
OnCalendar=monthly 12:00:00 # 매 달 1일 오후 12시에 실행매달 마지막 “날?”
-
cron에는 없는 기능인데, 연-월-일의 “마지막”을 특정해서 쓸 수 있음
-
예시
OnCalendar=*-*-~ 18:00:00 # 매달 "마지막 날" 오후 6시에 실행언제부터 언제까지
-
cron에서는 - 로 사용되던 기능임
-
systemd timer에서는 점 두 개(..) 를 사용함
-
예시
OnCalendar=Mon..Fri 09:00:00 # 월요일부터 금요일까지 오전 9시에 한 번씩 실행반복
-
cron에서는 */주기 로 사용되던 기능임 (ex. */5 ⇒ 5분마다)
-
systemd timer에서도 비슷하게 / 를 쓰기는 함
-
예시
OnCalendar=*:0/10:00 # 매 10분 마다
OnCalendar=*-*-* 0/2:00:00 # 매 2시간 마다복수의 조건 설정
- 한 줄에 확실한 조건이면 여러 개 달 수있음
- 예시
OnCalendar=Mon..Fri *-*-* 09..18:0/10:00
# 월요일부터 금요일까지
# 매 주
# 오전 9시부터 저녁 6시까지
# 10분 간격으로 실행참고
- cron에서는 한 줄에 겹치는 조건이 있다면 or 로 판단되기 때문에 한 줄이 여러 번 실행될 때도 있었지만,
- systemd timer는 한 줄에 확실한 한 가지 조건이 있어야 한다.
- 그리고 OnCalendar 줄을 추가해서 or 처럼 쓸 수 있다.
꿀팁
- systemd-analyze calendar “캘린더문법” 을 쓰면 적용되는 시간을 볼 수 있음
- 근데 systemd-analyze 가 나온지 그렇게 오래되지는 않아서 CentOS 7.9에서는 사용 불가.
그 이후
- Timer Unit을 만든 뒤에는 다음 두 가지 명령어를 작성한다.
systemctl daemon-reload # 유닛 파일 수정하면 해야됨 (캐싱)
systemctl enable <서비스이름> # 컴퓨터 킬 때 자동으로 시작되게 함실습
- crontab이랑 다르게 설정해야 하는 파일이 두 개나 있어서, 직접 만들어봄
- Service 파일
# /usr/lib/systemd/system/lsblk-log.service
[Unit]
Description=Log lsblk output
[Service]
Type=oneshot
ExecStart=/bin/lsblk
StandardOutput=append:/data/main/log/lsblk.log
StandardError=append:/data/main/log/lsblk.log- Timer 파일
[Timer]
OnCalendar=*:0/1:00 # 1분마다 실행되게
Persistent=true
[Install]
WantedBy=timers.target- 적용
systemctl daemon-reload
systemctl enable lsblk-log.service
systemctl start lsblk-log.service- 잘 살아있는지 보는 법
systemctl status lsblk-log.service
systemctl status lsblk-log.timer
journalctl -u lsblk-log.service그런데…
- 오류가 자꾸 나서 파일에 아무것도 안적힘
- 이유는 systemctl 버전 때문이었음
- 낮은 버전에서는 append: 문법을 지원을 안한다고 함
- 그래서 ExecStart에다가 cron마냥 직접 써줘야됨
- 그래서 변경된 service 파일
# /usr/lib/systemd/system/lsblk-log.service
[Unit]
Description=Log lsblk output
[Service]
Type=oneshot
ExecStart=/bin/bash -c '/bin/date "+%F %T" >> /data/main/log/lsblk_log.log && /bin/lsblk >> /data/main/log/lsblk_log.log 2>&1'