您好,登錄后才能下訂單哦!
這篇文章主要講解了“如何使用 systemd 定時器代替 cron 作業”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“如何使用 systemd 定時器代替 cron 作業”吧!
定時器提供了比 cron 作業更為細粒度的事件控制。
我正在致力于將我的 cron 作業遷移到 systemd 定時器上。我已經使用定時器多年了,但通常來說,我的學識只足以支撐我當前的工作。但在我研究 systemd 系列 的過程中,我發現 systemd 定時器有一些非常有意思的能力。
與 cron 作業類似,systemd 定時器可以在特定的時間間隔觸發事件(shell 腳本和程序),例如每天一次或在一個月中的特定某一天(或許只有在周一生效),或在從上午 8 點到下午 6 點的工作時間內每隔 15 分鐘一次。定時器也可以做到 cron 作業無法做到的一些事情。舉個例子,定時器可以在特定事件發生后的一段時間后觸發一段腳本或者程序去執行,例如開機、啟動、上個任務完成,甚至于定時器調用的上個服務單元的完成的時刻。
當在一個新系統上安裝 Fedora 或者是任意一個基于 systemd 的發行版時,作為系統維護過程的一部分,它會在 Linux 宿主機的后臺中創建多個定時器。這些定時器會觸發事件來執行必要的日常維護任務,比如更新系統數據庫、清理臨時目錄、輪換日志文件,以及更多其他事件。
作為示例,我會查看一些我的主要工作站上的定時器,通過執行 systemctl status *timer
命令來展示主機上的所有定時器。星號的作用與文件通配相同,所以這個命令會列出所有的 systemd 定時器單元。
[root@testvm1 ~]# systemctl status *timer● mlocate-updatedb.timer - Updates mlocate database every day Loaded: loaded (/usr/lib/systemd/system/mlocate-updatedb.timer; enabled; vendor preset: enabled) Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago Trigger: Fri 2020-06-05 00:00:00 EDT; 15h left Triggers: ● mlocate-updatedb.service Jun 02 08:02:33 testvm1.both.org systemd[1]: Started Updates mlocate database every day. ● logrotate.timer - Daily rotation of log files Loaded: loaded (/usr/lib/systemd/system/logrotate.timer; enabled; vendor preset: enabled) Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago Trigger: Fri 2020-06-05 00:00:00 EDT; 15h left Triggers: ● logrotate.service Docs: man:logrotate(8) man:logrotate.conf(5) Jun 02 08:02:33 testvm1.both.org systemd[1]: Started Daily rotation of log files. ● sysstat-summary.timer - Generate summary of yesterday's process accounting Loaded: loaded (/usr/lib/systemd/system/sysstat-summary.timer; enabled; vendor preset: enabled) Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago Trigger: Fri 2020-06-05 00:07:00 EDT; 15h left Triggers: ● sysstat-summary.service Jun 02 08:02:33 testvm1.both.org systemd[1]: Started Generate summary of yesterday's process accounting. ● fstrim.timer - Discard unused blocks once a week Loaded: loaded (/usr/lib/systemd/system/fstrim.timer; enabled; vendor preset: enabled) Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago Trigger: Mon 2020-06-08 00:00:00 EDT; 3 days left Triggers: ● fstrim.service Docs: man:fstrim Jun 02 08:02:33 testvm1.both.org systemd[1]: Started Discard unused blocks once a week. ● sysstat-collect.timer - Run system activity accounting tool every 10 minutes Loaded: loaded (/usr/lib/systemd/system/sysstat-collect.timer; enabled; vendor preset: enabled) Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago Trigger: Thu 2020-06-04 08:50:00 EDT; 41s left Triggers: ● sysstat-collect.service Jun 02 08:02:33 testvm1.both.org systemd[1]: Started Run system activity accounting tool every 10 minutes. ● dnf-makecache.timer - dnf makecache --timer Loaded: loaded (/usr/lib/systemd/system/dnf-makecache.timer; enabled; vendor preset: enabled) Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago Trigger: Thu 2020-06-04 08:51:00 EDT; 1min 41s left Triggers: ● dnf-makecache.service Jun 02 08:02:33 testvm1.both.org systemd[1]: Started dnf makecache –timer. ● systemd-tmpfiles-clean.timer - Daily Cleanup of Temporary Directories Loaded: loaded (/usr/lib/systemd/system/systemd-tmpfiles-clean.timer; static; vendor preset: disabled) Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago Trigger: Fri 2020-06-05 08:19:00 EDT; 23h left Triggers: ● systemd-tmpfiles-clean.service Docs: man:tmpfiles.d(5) man:systemd-tmpfiles(8) Jun 02 08:02:33 testvm1.both.org systemd[1]: Started Daily Cleanup of Temporary Directories.
每個定時器至少有六行相關信息:
定時器的第一行有定時器名字和定時器目的的簡短介紹
第二行展示了定時器的狀態,是否已加載,定時器單元文件的完整路徑以及預設信息。
第三行指明了其活動狀態,包括該定時器激活的日期和時間。
第四行包括了該定時器下次被觸發的日期和時間和距離觸發的大概時間。
第五行展示了被定時器觸發的事件或服務名稱。
部分(不是全部)systemd 單元文件有相關文檔的指引。我虛擬機上輸出中有三個定時器有文檔指引。這是一個很好(但非必要)的信息。
最后一行是計時器最近觸發的服務實例的日志條目。
你也許有一些不一樣的定時器,取決于你的主機。
盡管我們可以解構一個或多個現有的計時器來了解其工作原理,但讓我們創建我們自己的 服務單元 和一個定時器去觸發它。為了保持簡單,我們將使用一個相當簡單的例子。當我們完成這個實驗之后,就能更容易理解其他定時器的工作原理以及發現它們正在做什么。
首先,創建一個運行基礎東西的簡單的服務,例如 free
命令。舉個例子,你可能想定時監控空余內存。在 /etc/systemd/system
目錄下創建如下的 myMonitor.server
單元文件。它不需要是可執行文件:
# This service unit is for testing timer units# By David Both# Licensed under GPL V2# [Unit]Description=Logs system statistics to the systemd journalWants=myMonitor.timer [Service]Type=oneshotExecStart=/usr/bin/free [Install]WantedBy=multi-user.target
這大概是你能創建的最簡單的服務單元了。現在我們查看一下服務狀態同時測試一下服務單元確保它和我們預期一樣可用。
[root@testvm1 system]# systemctl status myMonitor.service● myMonitor.service - Logs system statistics to the systemd journal Loaded: loaded (/etc/systemd/system/myMonitor.service; disabled; vendor preset: disabled) Active: inactive (dead)[root@testvm1 system]# systemctl start myMonitor.service[root@testvm1 system]#
輸出在哪里呢?默認情況下,systemd 服務單元執行程序的標準輸出(STDOUT
)會被發送到系統日志中,它保留了記錄供現在或者之后(直到某個時間點)查看。(在本系列的后續文章中,我將介紹系統日志的記錄和保留策略)。專門查看你的服務單元的日志,而且只針對今天。-S
選項,即 --since
的縮寫,允許你指定 journalctl
工具搜索條目的時間段。這并不代表你不關心過往結果 —— 在這個案例中,不會有過往記錄 —— 如果你的機器以及運行了很長時間且堆積了大量的日志,它可以縮短搜索時間。
[root@testvm1 system]# journalctl -S today -u myMonitor.service-- Logs begin at Mon 2020-06-08 07:47:20 EDT, end at Thu 2020-06-11 09:40:47 EDT. --Jun 11 09:12:09 testvm1.both.org systemd[1]: Starting Logs system statistics to the systemd journal...Jun 11 09:12:09 testvm1.both.org free[377966]: total used free shared buff/cache availableJun 11 09:12:09 testvm1.both.org free[377966]: Mem: 12635740 522868 11032860 8016 1080012 11821508Jun 11 09:12:09 testvm1.both.org free[377966]: Swap: 8388604 0 8388604Jun 11 09:12:09 testvm1.both.org systemd[1]: myMonitor.service: Succeeded.[root@testvm1 system]#
由服務觸發的任務可以是單個程序、一組程序或者是一個腳本語言寫的腳本。通過在 myMonitor.service
單元文件里的 [Service]
塊末尾中添加如下行可以為服務添加另一個任務:
ExecStart=/usr/bin/lsblk
再次啟動服務,查看日志檢查結果,結果應該看上去像這樣。你應該在日志中看到兩條命令的結果輸出:
Jun 11 15:42:18 testvm1.both.org systemd[1]: Starting Logs system statistics to the systemd journal...Jun 11 15:42:18 testvm1.both.org free[379961]: total used free shared buff/cache availableJun 11 15:42:18 testvm1.both.org free[379961]: Mem: 12635740 531788 11019540 8024 1084412 11812272Jun 11 15:42:18 testvm1.both.org free[379961]: Swap: 8388604 0 8388604Jun 11 15:42:18 testvm1.both.org lsblk[379962]: NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTJun 11 15:42:18 testvm1.both.org lsblk[379962]: sda 8:0 0 120G 0 diskJun 11 15:42:18 testvm1.both.org lsblk[379962]: ├─sda1 8:1 0 4G 0 part /bootJun 11 15:42:18 testvm1.both.org lsblk[379962]: └─sda2 8:2 0 116G 0 partJun 11 15:42:18 testvm1.both.org lsblk[379962]: ├─VG01-root 253:0 0 5G 0 lvm /Jun 11 15:42:18 testvm1.both.org lsblk[379962]: ├─VG01-swap 253:1 0 8G 0 lvm [SWAP]Jun 11 15:42:18 testvm1.both.org lsblk[379962]: ├─VG01-usr 253:2 0 30G 0 lvm /usrJun 11 15:42:18 testvm1.both.org lsblk[379962]: ├─VG01-tmp 253:3 0 10G 0 lvm /tmpJun 11 15:42:18 testvm1.both.org lsblk[379962]: ├─VG01-var 253:4 0 20G 0 lvm /varJun 11 15:42:18 testvm1.both.org lsblk[379962]: └─VG01-home 253:5 0 10G 0 lvm /homeJun 11 15:42:18 testvm1.both.org lsblk[379962]: sr0 11:0 1 1024M 0 romJun 11 15:42:18 testvm1.both.org systemd[1]: myMonitor.service: Succeeded.Jun 11 15:42:18 testvm1.both.org systemd[1]: Finished Logs system statistics to the systemd journal.
現在你知道了你的服務可以按預期工作了,在 /etc/systemd/system
目錄下創建 myMonitor.timer
定時器單元文件,添加如下代碼:
# This timer unit is for testing# By David Both# Licensed under GPL V2# [Unit]Description=Logs some system statistics to the systemd journalRequires=myMonitor.service [Timer]Unit=myMonitor.serviceOnCalendar=*-*-* *:*:00 [Install]WantedBy=timers.target
在 myMonitor.timer
文件中的 OnCalendar
時間格式,*-*-* *:*:00
,應該會每分鐘觸發一次定時器去執行 myMonitor.service
單元。我會在文章的后面進一步探索 OnCalendar
設置。
到目前為止,在服務被計時器觸發運行時觀察與之有關的日志記錄。你也可以跟蹤計時器,跟蹤服務可以讓你接近實時的看到結果。執行 journalctl
時帶上 -f
選項:
[root@testvm1 system]# journalctl -S today -f -u myMonitor.service-- Logs begin at Mon 2020-06-08 07:47:20 EDT. --
執行但是不啟用該定時器,看看它運行一段時間后發生了什么:
[root@testvm1 ~]# systemctl start myMonitor.service[root@testvm1 ~]#
一條結果立即就顯示出來了,下一條大概在一分鐘后出來。觀察幾分鐘日志,看看你有沒有跟我發現同樣的事情:
[root@testvm1 system]# journalctl -S today -f -u myMonitor.service-- Logs begin at Mon 2020-06-08 07:47:20 EDT. --Jun 13 08:39:18 testvm1.both.org systemd[1]: Starting Logs system statistics to the systemd journal...Jun 13 08:39:18 testvm1.both.org systemd[1]: myMonitor.service: Succeeded.Jun 13 08:39:19 testvm1.both.org free[630566]: total used free shared buff/cache availableJun 13 08:39:19 testvm1.both.org free[630566]: Mem: 12635740 556604 10965516 8036 1113620 11785628Jun 13 08:39:19 testvm1.both.org free[630566]: Swap: 8388604 0 8388604Jun 13 08:39:18 testvm1.both.org systemd[1]: Finished Logs system statistics to the systemd journal.Jun 13 08:39:19 testvm1.both.org lsblk[630567]: NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTJun 13 08:39:19 testvm1.both.org lsblk[630567]: sda 8:0 0 120G 0 diskJun 13 08:39:19 testvm1.both.org lsblk[630567]: ├─sda1 8:1 0 4G 0 part /bootJun 13 08:39:19 testvm1.both.org lsblk[630567]: └─sda2 8:2 0 116G 0 partJun 13 08:39:19 testvm1.both.org lsblk[630567]: ├─VG01-root 253:0 0 5G 0 lvm /Jun 13 08:39:19 testvm1.both.org lsblk[630567]: ├─VG01-swap 253:1 0 8G 0 lvm [SWAP]Jun 13 08:39:19 testvm1.both.org lsblk[630567]: ├─VG01-usr 253:2 0 30G 0 lvm /usrJun 13 08:39:19 testvm1.both.org lsblk[630567]: ├─VG01-tmp 253:3 0 10G 0 lvm /tmpJun 13 08:39:19 testvm1.both.org lsblk[630567]: ├─VG01-var 253:4 0 20G 0 lvm /varJun 13 08:39:19 testvm1.both.org lsblk[630567]: └─VG01-home 253:5 0 10G 0 lvm /homeJun 13 08:39:19 testvm1.both.org lsblk[630567]: sr0 11:0 1 1024M 0 romJun 13 08:40:46 testvm1.both.org systemd[1]: Starting Logs system statistics to the systemd journal...Jun 13 08:40:46 testvm1.both.org free[630572]: total used free shared buff/cache availableJun 13 08:40:46 testvm1.both.org free[630572]: Mem: 12635740 555228 10966836 8036 1113676 11786996Jun 13 08:40:46 testvm1.both.org free[630572]: Swap: 8388604 0 8388604Jun 13 08:40:46 testvm1.both.org lsblk[630574]: NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTJun 13 08:40:46 testvm1.both.org lsblk[630574]: sda 8:0 0 120G 0 diskJun 13 08:40:46 testvm1.both.org lsblk[630574]: ├─sda1 8:1 0 4G 0 part /bootJun 13 08:40:46 testvm1.both.org lsblk[630574]: └─sda2 8:2 0 116G 0 partJun 13 08:40:46 testvm1.both.org lsblk[630574]: ├─VG01-root 253:0 0 5G 0 lvm /Jun 13 08:40:46 testvm1.both.org lsblk[630574]: ├─VG01-swap 253:1 0 8G 0 lvm [SWAP]Jun 13 08:40:46 testvm1.both.org lsblk[630574]: ├─VG01-usr 253:2 0 30G 0 lvm /usrJun 13 08:40:46 testvm1.both.org lsblk[630574]: ├─VG01-tmp 253:3 0 10G 0 lvm /tmpJun 13 08:40:46 testvm1.both.org lsblk[630574]: ├─VG01-var 253:4 0 20G 0 lvm /varJun 13 08:40:46 testvm1.both.org lsblk[630574]: └─VG01-home 253:5 0 10G 0 lvm /homeJun 13 08:40:46 testvm1.both.org lsblk[630574]: sr0 11:0 1 1024M 0 romJun 13 08:40:46 testvm1.both.org systemd[1]: myMonitor.service: Succeeded.Jun 13 08:40:46 testvm1.both.org systemd[1]: Finished Logs system statistics to the systemd journal.Jun 13 08:41:46 testvm1.both.org systemd[1]: Starting Logs system statistics to the systemd journal...Jun 13 08:41:46 testvm1.both.org free[630580]: total used free shared buff/cache availableJun 13 08:41:46 testvm1.both.org free[630580]: Mem: 12635740 553488 10968564 8036 1113688 11788744Jun 13 08:41:46 testvm1.both.org free[630580]: Swap: 8388604 0 8388604Jun 13 08:41:47 testvm1.both.org lsblk[630581]: NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTJun 13 08:41:47 testvm1.both.org lsblk[630581]: sda 8:0 0 120G 0 diskJun 13 08:41:47 testvm1.both.org lsblk[630581]: ├─sda1 8:1 0 4G 0 part /bootJun 13 08:41:47 testvm1.both.org lsblk[630581]: └─sda2 8:2 0 116G 0 partJun 13 08:41:47 testvm1.both.org lsblk[630581]: ├─VG01-root 253:0 0 5G 0 lvm /Jun 13 08:41:47 testvm1.both.org lsblk[630581]: ├─VG01-swap 253:1 0 8G 0 lvm [SWAP]Jun 13 08:41:47 testvm1.both.org lsblk[630581]: ├─VG01-usr 253:2 0 30G 0 lvm /usrJun 13 08:41:47 testvm1.both.org lsblk[630581]: ├─VG01-tmp 253:3 0 10G 0 lvm /tmpJun 13 08:41:47 testvm1.both.org lsblk[630581]: ├─VG01-var 253:4 0 20G 0 lvm /varJun 13 08:41:47 testvm1.both.org lsblk[630581]: └─VG01-home 253:5 0 10G 0 lvm /homeJun 13 08:41:47 testvm1.both.org lsblk[630581]: sr0 11:0 1 1024M 0 romJun 13 08:41:47 testvm1.both.org systemd[1]: myMonitor.service: Succeeded.Jun 13 08:41:47 testvm1.both.org systemd[1]: Finished Logs system statistics to the systemd journal.
別忘了檢查下計時器和服務的狀態。
你在日志里大概至少注意到兩件事。第一,你不需要特地做什么來讓 myMonitor.service
單元中 ExecStart
觸發器產生的 STDOUT
存儲到日志里。這都是用 systemd 來運行服務的一部分功能。然而,它確實意味著你需要小心對待服務單元里面執行的腳本和它們能產生多少 STDOUT
。
第二,定時器并不是精確在每分鐘的 :00 秒執行的,甚至每次執行的時間間隔都不是剛好一分鐘。這是特意的設計,但是有必要的話可以改變這種行為(如果只是它挑戰了你的系統管理員的敏感神經)。
這樣設計的初衷是為了防止多個服務在完全相同的時刻被觸發。舉個例子,你可以用例如 Weekly,Daily 等時間格式。這些快捷寫法都被定義為在某一天的 00:00:00 執行。當多個定時器都這樣定義的話,有很大可能它們會同時執行。
systemd 定時器被故意設計成在規定時間附近隨機波動的時間點觸發,以避免同一時間觸發。它們在一個時間窗口內半隨機觸發,時間窗口開始于預設的觸發時間,結束于預設時間后一分鐘。根據 systemd.timer
的手冊頁,這個觸發時間相對于其他已經定義的定時器單元保持在穩定的位置。你可以在日志條目中看到,定時器在啟動后立即觸發,然后在每分鐘后的 46 或 47 秒觸發。
大部分情況下,這種概率抖動的定時器是沒事的。當調度類似執行備份的任務,只需要它們在下班時間運行,這樣是沒問題的。系統管理員可以選擇確定的開始時間來確保不和其他任務沖突,例如 01:05:00 這樣典型的 cron 作業時間,但是有很大范圍的時間值可以滿足這一點。在開始時間上的一個分鐘級別的隨機往往是無關緊要的。
然而,對某些任務來說,精確的觸發時間是個硬性要求。對于這類任務,你可以向單元文件的 Timer
塊中添加如下聲明來指定更高的觸發時間跨度精確度(精確到微秒以內):
AccuracySec=1us
時間跨度可用于指定所需的精度,以及定義重復事件或一次性事件的時間跨度。它能識別以下單位:
usec
,us
,µs
msec
,ms
seconds
,second
,sec
,s
minutes
,minute
,min
,m
hours
,hour
,hr
,h
days
,day
,d
weeks
,week
,w
months
,month
,M
(定義為 30.44 天)
years
,year
,y
(定義為 365.25 天)
所有 /usr/lib/systemd/system
中的定時器都指定了一個更寬松的時間精度,因為精準時間沒那么重要。看看這些系統創建的定時器的時間格式:
[root@testvm1 system]# grep Accur /usr/lib/systemd/system/*timer/usr/lib/systemd/system/fstrim.timer:AccuracySec=1h/usr/lib/systemd/system/logrotate.timer:AccuracySec=1h/usr/lib/systemd/system/logwatch.timer:AccuracySec=12h/usr/lib/systemd/system/mlocate-updatedb.timer:AccuracySec=24h/usr/lib/systemd/system/raid-check.timer:AccuracySec=24h/usr/lib/systemd/system/unbound-anchor.timer:AccuracySec=24h[root@testvm1 system]#
看下 /usr/lib/systemd/system
目錄下部分定時器單元文件的完整內容,看看它們是如何構建的。
在本實驗中不必讓這個定時器在啟動時激活,但下面這個命令可以設置開機自啟:
[root@testvm1 system]# systemctl enable myMonitor.timer
你創建的單元文件不需要是可執行的。你同樣不需要啟用服務,因為它是被定時器觸發的。如果你需要的話,你仍然可以在命令行里手動觸發該服務單元。嘗試一下,然后觀察日志。
關于定時器精度、事件時間規格和觸發事件的詳細信息,請參見 systemd.timer 和 systemd.time 的手冊頁。
systemd 定時器還有一些在 cron 中找不到的功能,cron 只在確定的、重復的、具體的日期和時間觸發。systemd 定時器可以被配置成根據其他 systemd 單元狀態發生改變時觸發。舉個例子,定時器可以配置成在系統開機、啟動后,或是某個確定的服務單元激活之后的一段時間被觸發。這些被稱為單調計時器。“單調”指的是一個持續增長的計數器或序列。這些定時器不是持久的,因為它們在每次啟動后都會重置。
表格 1 列出了一些單調定時器以及每個定時器的簡短定義,同時有 OnCalendar
定時器,這些不是單調的,它們被用于指定未來有可能重復的某個確定時間。這個信息來自于 systemd.timer
的手冊頁,有一些不重要的修改。
定時器 | 單調性 | 定義 |
---|---|---|
OnActiveSec= | X | 定義了一個與定時器被激活的那一刻相關的定時器。 |
OnBootSec= | X | 定義了一個與機器啟動時間相關的計時器。 |
OnStartupSec= | X | 定義了一個與服務管理器首次啟動相關的計時器。對于系統定時器來說,這個定時器與 OnBootSec= 類似,因為系統服務管理器在機器啟動后很短的時間后就會啟動。當以在每個用戶服務管理器中運行的單元進行配置時,它尤其有用,因為用戶的服務管理器通常在首次登錄后啟動,而不是機器啟動后。 |
OnUnitActiveSec= | X | 定義了一個與將要激活的定時器上次激活時間相關的定時器。 |
OnUnitInactiveSec= | X | 定義了一個與將要激活的定時器上次停用時間相關的定時器。 |
OnCalendar= | 定義了一個有日期事件表達式語法的實時(即時鐘)定時器。查看 systemd.time(7) 的手冊頁獲取更多與日歷事件表達式相關的語法信息。除此以外,它的語義和 OnActiveSec= 類似。 |
Table 1: systemd 定時器定義
單調計時器可使用同樣的簡寫名作為它們的時間跨度,即我們之前提到的 AccuracySec
表達式,但是 systemd 將這些名字統一轉換成了秒。舉個例子,比如你想規定某個定時器在系統啟動后五天觸發一次事件;它可能看起來像 OnBootSec=5d
。如果機器啟動于 2020-06-15 09:45:27
,這個定時器會在 2020-06-20 09:45:27
或在這之后的一分鐘內觸發。
日歷事件格式是定時器在所需的重復時間觸發的關鍵。我們開始看下一些 OnCalendar
設置一起使用的格式。
與 crontab 中的格式相比,systemd 及其計時器使用的時間和日歷格式風格不同。它比 crontab 更為靈活,而且可以使用類似 at
命令的方式允許模糊的日期和時間。它還應該足夠熟悉使其易于理解。
systemd 定時器使用 OnCalendar=
的基礎格式是 DOW YYYY-MM-DD HH:MM:SS
。DOW(星期幾)是選填的,其他字段可以用一個星號(*
)來匹配此位置的任意值。所有的日歷時間格式會被轉換成標準格式。如果時間沒有指定,它會被設置為 00:00:00
。如果日期沒有指定但是時間指定了,那么下次匹配的時間可能是今天或者明天,取決于當前的時間。月份和星期可以使用名稱或數字。每個單元都可以使用逗號分隔的列表。單元范圍可以在開始值和結束值之間用 ..
指定。
指定日期有一些有趣的選項,波浪號(~
)可以指定月份的最后一天或者最后一天之前的某幾天。/
可以用來指定星期幾作為修飾符。
這里有幾個在 OnCalendar
表達式中使用的典型時間格式例子。
日期事件格式 | 描述 |
---|---|
DOW YYYY-MM-DD HH:MM:SS | |
*-*-* 00:15:30 | 每年每月每天的 0 點 15 分 30 秒 |
Weekly | 每個周一的 00:00:00 |
Mon *-*-* 00:00:00 | 同上 |
Mon | 同上 |
Wed 2020-*-* | 2020 年每個周三的 00:00:00 |
Mon..Fri 2021-*-* | 2021 年的每個工作日(周一到周五)的 00:00:00 |
2022-6,7,8-1,15 01:15:00 | 2022 年 6、7、8 月的 1 到 15 號的 01:15:00 |
Mon *-05~03 | 每年五月份的下個周一同時也是月末的倒數第三天 |
Mon..Fri *-08~04 | 任何年份 8 月末的倒數第四天,同時也須是工作日 |
*-05~03/2 | 五月末的倒數第三天,然后 2 天后再來一次。每年重復一次。注意這個表達式使用了波浪號(~ )。 |
*-05-03/2 | 五月的第三天,然后每兩天重復一次直到 5 月底。注意這個表達式使用了破折號(- )。 |
Table 2: OnCalendar
事件時間格式例子
systemd 提供了一個絕佳的工具用于檢測和測試定時器中日歷時間事件的格式。systemd-analyze calendar
工具解析一個時間事件格式,提供標準格式和其他有趣的信息,例如下次“經過”(即匹配)的日期和時間,以及距離下次觸發之前大概時間。
首先,看看未來沒有時間的日(注意 Next elapse
和 UTC
的時間會根據你當地時區改變):
[student@studentvm1 ~]$ systemd-analyze calendar 2030-06-17 Original form: 2030-06-17 Normalized form: 2030-06-17 00:00:00 Next elapse: Mon 2030-06-17 00:00:00 EDT (in UTC): Mon 2030-06-17 04:00:00 UTC From now: 10 years 0 months left [root@testvm1 system]#
現在添加一個時間,在這個例子中,日期和時間是當作無關的部分分開解析的:
[root@testvm1 system]# systemd-analyze calendar 2030-06-17 15:21:16 Original form: 2030-06-17 Normalized form: 2030-06-17 00:00:00 Next elapse: Mon 2030-06-17 00:00:00 EDT (in UTC): Mon 2030-06-17 04:00:00 UTC From now: 10 years 0 months left Original form: 15:21:16 Normalized form: *-*-* 15:21:16 Next elapse: Mon 2020-06-15 15:21:16 EDT (in UTC): Mon 2020-06-15 19:21:16 UTC From now: 3h 55min left [root@testvm1 system]#
為了把日期和時間當作一個單元來分析,可以把它們包在引號里。你在定時器單元里 OnCalendar=
時間格式中使用的時候記得把引號去掉,否則會報錯:
[root@testvm1 system]# systemd-analyze calendar "2030-06-17 15:21:16"Normalized form: 2030-06-17 15:21:16 Next elapse: Mon 2030-06-17 15:21:16 EDT (in UTC): Mon 2030-06-17 19:21:16 UTC From now: 10 years 0 months left [root@testvm1 system]#
現在我們測試下 Table2 里的例子。我尤其喜歡最后一個:
[root@testvm1 system]# systemd-analyze calendar "2022-6,7,8-1,15 01:15:00" Original form: 2022-6,7,8-1,15 01:15:00Normalized form: 2022-06,07,08-01,15 01:15:00 Next elapse: Wed 2022-06-01 01:15:00 EDT (in UTC): Wed 2022-06-01 05:15:00 UTC From now: 1 years 11 months left[root@testvm1 system]#
讓我們看一個例子,這個例子里我們列出了時間表達式的五個經過時間。
[root@testvm1 ~]# systemd-analyze calendar --iterations=5 "Mon *-05~3" Original form: Mon *-05~3 Normalized form: Mon *-05~03 00:00:00 Next elapse: Mon 2023-05-29 00:00:00 EDT (in UTC): Mon 2023-05-29 04:00:00 UTC From now: 2 years 11 months left Iter. #2: Mon 2028-05-29 00:00:00 EDT (in UTC): Mon 2028-05-29 04:00:00 UTC From now: 7 years 11 months left Iter. #3: Mon 2034-05-29 00:00:00 EDT (in UTC): Mon 2034-05-29 04:00:00 UTC From now: 13 years 11 months left Iter. #4: Mon 2045-05-29 00:00:00 EDT (in UTC): Mon 2045-05-29 04:00:00 UTC From now: 24 years 11 months left Iter. #5: Mon 2051-05-29 00:00:00 EDT (in UTC): Mon 2051-05-29 04:00:00 UTC From now: 30 years 11 months left [root@testvm1 ~]#
這些應該為你提供了足夠的信息去開始測試你的 OnCalendar
時間格式。systemd-analyze
工具可用于其他有趣的分析,我會在這個系列的下一篇文章來探索這些。
systemd 定時器可以用于執行和 cron 工具相同的任務,但是通過按照日歷和單調時間格式去觸發事件的方法提供了更多的靈活性。
雖然你為此次實驗創建的服務單元通常是由定時器調用的,你也可以隨時使用 systemctl start myMonitor.service
命令去觸發它。可以在一個定時器中編寫多個維護任務的腳本;它們可以是 Bash 腳本或者其他 Linux 程序。你可以通過觸發定時器來運行所有的腳本來運行服務,也可以按照需要執行單獨的腳本。
我會在下篇文章中更加深入的探索 systemd 時間格式的用處。
我還沒有看到任何跡象表明 cron 和 at 將被廢棄。我希望這種情況不會發生,因為至少 at
在執行一次性調度任務的時候要比 systemd 定時器容易的多。
感謝各位的閱讀,以上就是“如何使用 systemd 定時器代替 cron 作業”的內容了,經過本文的學習后,相信大家對如何使用 systemd 定時器代替 cron 作業這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。