본문 바로가기

Linux/systemd

systemd timer로 cron 대체하기

앞으로 티스토리 대신 blog.stackframe.dev에서 블로깅을 합니다. 이 블로그는 남겨 둘 예정입니다.

리눅스 init으로 많이 사용되는 systemd의 기능 중에 timer가 있습니다. 이 timer는 이름 그대로 일정 시간이 지난 이후에 작업을 수행하도록 하는 기능입니다. 예전의 리눅스에서는 cron이란 프로그램으로 crontab 설정파일을 통하여 일정 시간마다 프로그램을 실행시켰습니다만 가독성이 그리 좋지 못합니다.

systemd에서는 가독성이 좋으면서 부가적인 옵션이 많으며 간단하게 설정이 가능하고, 리눅스가 실행되는 도중에는 절대 죽지 않기 때문에 사용자도 모르게 cron 서비스가 죽어버리는 사태도 막을 수 있습니다. 그러므로 만약 지금까지 cron을 사용하셨다면 systemd로 넘어오는게 시스템 자동화와 일률적인 관리 편의성을 위해서라도 바람직할거라 생각합니다.


systemd는 모든 설정을 Unit이란 단위로 관리합니다. 그러므로 서비스도 유닛, 타이머도 유닛, 장치 마운트도 유닛으로 취급 할 수 있습니다. 여기서 다룰 타이머는 .timer 라는 확장자를 가집니다. 그리고 또 하나 중요한 점은 사용자가 정의하여 시스템에 사용되는 유닛들은 모두 /etc/systemd/system/ 디렉토리에 저장되어야 합니다. 그러므로 사용자가 타이머를 정의하여 사용하려면 .timer 유닛을 만들어서 /etc/systemd/system/ 에 저장되어야 합니다.


이러한 설명은 예시를 들어 설명하는 것이 가장 이해가 빠르므로 "화요일과 목요일"이면서 "10일에서 20일 사이" "오후 2시"에 작동하는 타이머를 만들어 보겠습니다.


먼저 /etc/systemd/system/에 .timer 확장자를 가진 유닛을 만듭니다. 저는 mytimer.timer 라는 이름으로 만들겠습니다.

# vim /etc/systemd/system/mytimer.timer

timer 유닛은 [Timer] 섹션이 있어야하고 저희가 만들고 싶은 것은 실제 시간에 따라 작동하는 타이머이므로 realtime timer 옵션인 OnCalendar= 옵션을 정의합니다. OnCalendar 옵션은 직관적인 시간 값을 입력할 수 있습니다. 


여기서 입력하는 포맷에 대해 설명하자면 아래와 같습니다.

["요일"] "년"-"월"-"일" "시":"분":"초" [timezone]

맨 처음에 있는 요일은 있어도 되고 없어도 됩니다. 대신 요일은 영어로 앞 세글자를 따서 표기합니다.(Monday : Mon, Thursday : Thu)

여기서 요일, 년, 월, 일, 시, 분, 초 값에는 .. 을 통해 범위를 설정할 수 있습니다. 만약 화요일부터 목요일까지로 설정하고 싶다면 Tus..Thu 로 표기할 수 있겠습니다.

또한 값을 하나하나 설정하고 싶다면 , 를 사용하시면 됩니다. 그리고 어떠한 값이라도 매치가 되려면 *를 사용합니다. 년도에 상관없이 작동하려면 년 부분에 *를 넣으시면 됩니다.

timezone은 설정하지 않는다면 시스템 시간이 기본적으로 사용됩니다.(date 명령을 통해 확인가능합니다.)


위의 예시의 타이머를 만들면 아래와 같이 표기할 수 있습니다.

Tue,Thu *-*-10..20 14:00:00

참고)

단순하며 많이 쓰이는 시간 간격 또한 저 포맷을 지켜서 입력하는 것이 귀찮다는 것을 알았는지 특별한 입력 값들이 존재합니다.


minutely, hourly, daily, monthly, weekly, yearly, quarterly, semiannually


이 값 중에 하나를 OnCalendar 입력 값으로 사용하면 이름대로 작동합니다.


화요일과 목요일에 년도와 월은 상관없이 10일 부터 20일 사이의 14시에 실행한다는 아주 직관적인 설정입니다. 이를 토대로 설정파일을 만든다면 아래와 같이 만들어집니다.

[Timer]
OnCalendar=Tue,Thu *-*-10..20 14:00:00
Unit=myService.service

여기서 못보던 옵션이 하나 나옵니다. Timer에서 서비스를 실행하려면 해당 서비스에 대한 설정파일이 존재해야 합니다. cron 에서는 단순히 쉘 스크립트 경로나 명령을 입력했지만 systemd에서는 모든 설정을 유닛으로 관리하기 때문에 이런 방법으로 실행할 프로그램을 지정해야 합니다. 그래서 저는 단순히 /usr/bin/wall echo!! 라는 명령을 수행하는 서비스 유닛을 임시로 만들었습니다. 이 또한 사용자 정의 서비스이므로 /etc/systemd/system/ 에 저장해야 합니다.

[Unit]
Description=my Service

[Service]
ExecStart=/usr/bin/wall echo!!

이 서비스를 실행하면 단순히 열려있는 모든 콘솔에 echo!!를 출력합니다.

위의 두 설정파일을 저장했다면 이제 타이머를 실행해야 합니다. 타이머 실행은 서비스 관리와 동일하게 systemctl start mytimer.timer로 이루어집니다. systemd 서비스 관리에 대해 잘 모르겠다면 저의 다른 게시물을 참고하시기 바랍니다.


추가적으로 중요한 명령으로는 현재 실행중인 타이머들을 보고싶다면 systemctl list-timers 라는 명령을 실행하면 됩니다.

제가 만든 mytimer.timer 이외에도 4개의 타이머가 존재하는 것을 볼 수 있습니다. mytimer의 다음 실행 날짜는 2019년 1월 10일 목요일 14시이고, 실행될 것은 myService.service라는 것을 보여줍니다.


이렇게 systemd를 사용하여 cron의 기능을 구현하는 방법을 알아보았습니다. systemd에서는 cron보다 더 많은 옵션이 있다고 말씀드렸는데 OnActiveSec, OnBootSec, OnStartupSec 등 단조 타이머에 대한 옵션이 존재합니다. 옵션 이름만으로도 직관적으로 어떤 기능인지 바로 알 수 있을겁니다. 더 자세한 정보를 알고싶다면 systemd.timer man 페이지를 참고하시기 바랍니다.

$ man systemd.timer


'Linux > systemd' 카테고리의 다른 글

systemd 사용자 유닛 만들기  (0) 2019.01.09
리눅스 시스템 시간 동기화하기  (0) 2018.12.30
systemd로 서비스 관리하기  (0) 2018.12.27
systemd란 무엇인가  (0) 2018.12.27
systemd-resolved 사용하기  (2) 2018.12.23