博客 / 詳情

返回

如何使用Systemd定時服務

我上一篇文章中介紹的locate文件查找命令,需要依賴updatedb更新索引才能快速查找文件,因此需要定時運行該命令來更新文件索引。我們知道在Linux和類Unix系統上通常使用crontab來創建定時任務。

在Ubuntu上我們使用apt install mlocate之後,會安裝一個腳本文件到 /etc/cron.daily/mlocate,也就是通過Cron機制來每天執行updatedb。然而在我的openSUSE上卻並未發現有相關的Crontab配置,但我發現索引文件還是在每天的零點進行了更新,那這個定時任務是誰來執行的呢?

我通過查找與mlocate相關的文件,發現了以下幾個文件:

❯ locate "mlocate"
/etc/systemd/system/timers.target.wants/mlocate.timer
/usr/lib/systemd/system/mlocate.service
/usr/lib/systemd/system/mlocate.timer

原來在openSUSE系統上,使用的是Systemd的定時單元來實現的。Systemd是一種Linux系統服務管理程序,在我之前的文章在OPENSUSE上使用SYSTEMCTL管理系統服務中介紹過。

那這裏我們將重點介紹下Systemd的定時服務(systemd timer unit)。

systemd定時單元

類似與Cron,systemd的定時單元在Linux系統上提供了機制來調度任務,相比於Cron機制,其他具有以下特性(在使用systemd作為初始化和服務管理的系統上):

  • 調度的任務可以依賴於其他systemd服務
  • 可以使用systemctl命令來管理定時單元,類似與管理systemd服務
  • 除了類似Cron的循環實時定時任務(realtime)之外,還支持一種基於非時間事件觸發的任務(monotonic)
  • 定時單元記錄日誌到systemd的日誌系統(journal),因此方便於統一監控和診斷

systemd定時任務的類型

上面的特性中,我們提到其支持兩種類型 - realtime 和 monotonic

  • Realtime - 類似於Cron,這種類型的定時任務由定義的絕對時間來觸發,在配置文件中通過 OnCalendar 選項來定義
  • Monotonic - 這種類型的定時任務將會在指定的事件(例如系統啓動,服務激活)一定時間後觸發,在配置文件中通過 OnBootSecOnUnitActiveSecOnStartupSec 等選項來定義,並且該類型的定時任務觸發時間不是固定的,在每一次系統重啓之後都會被重置

systemd定時任務的配置

在文章開始,我們在尋找mlocate更新文件索引的定時任務時看到,有文件 /usr/lib/systemd/system/mlocate.timer ,沒錯,就是通過以 .timer 作為擴展名的systemd單元文件來定義systemd的定時單元的

[Unit]
Description=Daily locate database update
Documentation=man:updatedb

[Timer]
OnCalendar=daily
AccuracySec=12h
Unit=mlocate.service
Persistent=true

[Install]
WantedBy=timers.target

可以看到文件格式與systemd服務的單元文件類似,不過需要 [Timer] 段,在該段定義瞭如下選項

  • OnCalendar=daily,意思是每天觸發
  • AccuracySec=12h,意思是由於某些原因需要推測執行的時間
  • Unit=mlocate.service,這裏就是指定了需要執行的任務服務
  • Persistent=true,指定如果由於關機等原因到時了為能執行任務的情況下,啓動會立即觸發該任務

那該定時單元指定了 mlocate.service 作為觸發執行的任務,也就是 /usr/lib/systemd/system/mlocate.service 裏定義的服務,那服務裏就是定義使用 updatedb 命令去更新文件索引。

對於 OnCalendar ,其值支持的格式為 DayOfWeek Year-Month-Day Hour:Minute:Second,例如

  • OnCalendar=--* 5:00:00,指定在每天早上的5點執行
  • OnCalendar=Fri 18:00:00,指定在每個月的週五下午6點執行

在一個配置文件中,還可以指定多個 OnCalendar ,例如

OnCalendar=Mon..Fri 10:00
OnCalendar=Sat,Sun 22:00

上面的配置就指定了在週一到週五的每天上午10點,以及在週末兩天的晚上10點執行。

下面我們來舉一個使用monotonic類型定時任務的例子,在目錄 /etc/systemd/system/ 下服務單元文件 foo.service

[Unit]
Description="Foo shell script"

[Service]
ExecStart=/usr/local/bin/foo.sh

同時創建一個定時單元文件 foo.timer

[Unit]
Description="Run foo shell script"

[Timer]
OnBootSec=5min
OnUnitActiveSec=24h
Unit=foo.service

[Install]
WantedBy=multi-user.target

這裏我們看到在 [Timer] 段,我們定義一下選項

  • OnBootSec=5min,指定了在系統啓動5分鐘後觸發指定服務的執行
  • OnUnitActiveSec=24h,指定了在服務在激活之後的24小時執行,也就是每天都會執行一次(但是執行的具體時間取決於開機時間)
  • Unit=foo.service,指定了觸發的任務是我們上面定義的foo服務,也就是執行 foo.sh 腳本

管理timer單元

上面的特性中,我們説道timer單元可以通過 systemctl 命令進行管理,類似管理服務單元

  • sudo systemctl start foo.timer ,啓動指定的定時單元
  • sudo systemctl enable foo.timer ,開啓定時單元自動激活(開機自啓)
  • sudo systemctl list-timers ,列出當前系統已激活的定時單元

例如

❯ sudo systemctl list-timers
NEXT                         LEFT                LAST                         PASSED      UNIT                         ACTIVATES
Fri 2021-12-03 17:00:00 CST  22min left          Fri 2021-12-03 16:00:03 CST  37min ago   snapper-timeline.timer       snapper-timeline.service
Sat 2021-12-04 00:00:00 CST  7h left             Fri 2021-12-03 00:00:03 CST  16h ago     logrotate.timer              logrotate.service
Sat 2021-12-04 00:00:00 CST  7h left             Fri 2021-12-03 00:00:03 CST  16h ago     mandb.timer                  mandb.service
Sat 2021-12-04 00:00:00 CST  7h left             Fri 2021-12-03 00:00:03 CST  16h ago     mlocate.timer                mlocate.service

我們還可以直接使用 journalctl 來查看相關日誌,例如

❯ sudo journalctl -u mlocate
-- Logs begin at Thu 2021-12-02 06:58:59 CST, end at Fri 2021-12-03 16:41:26 CST. --
Dec 03 00:00:03 linux-dev systemd[1]: Starting Update locate database...
Dec 03 00:00:03 linux-dev su[864]: (to nobody) root on none
Dec 03 00:00:06 linux-dev systemd[1]: Started Update locate database.

同時查看mlocate定時單元和服務的日誌。

關於更多的配置細節,可以參考官方文檔 。

總結

如果你的系統使用的Systemd作為初始化和服務管理系統,並且想使用到我們之前提到的特性,那麼我們可以使用systemd的timer單元來定義我們的定時任務。當然大部分系統還是支持Crontab機制的定時任務。

同時發佈在 Mengz's Blog
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.