哈嘍大家好,我是鹹魚。 說到 Linux 定時任務,大家用得最多的就是 crond 服務,但其實 systemd 也有類似的功能。我們不但可以通過 systemd 來管理服務,還能設置定時任務,那就是 systemd timer。 與 crond 相比,systemd 定時任務具有以下優點: 更高的 ...
哈嘍大家好,我是鹹魚。
說到 Linux 定時任務,大家用得最多的就是 crond 服務,但其實 systemd 也有類似的功能。我們不但可以通過 systemd 來管理服務,還能設置定時任務,那就是 systemd timer。
與 crond 相比,systemd 定時任務具有以下優點:
- 更高的精度:systemd 定時任務可以精確到秒,而 crond 只能精確到分鐘。
- 可以限制資源使用:使用 systemd 定時任務可以設置記憶體和 CPU 的使用限制,比如最多使用 50% 的 CPU。
- 更靈活的配置:systemd 定時任務可以通過條件、依賴關係等進行配置,以控制任務的執行。相比之下,crond 的配置相對簡單,靈活性較低。
舉個例子,假設我們要通過 crond 配置多個大文件的遠程備份(使用 scp、rsync 或 ftp 的方式),但由於大文件的網路傳輸時間不確定,因此下一個文件的備份任務開始時間幾乎都是按照經驗估計的。
這可能導致上一個任務的網路傳輸尚未完成,下一個任務已經開始,同時占用網路帶寬,然後又啟動了下一個任務,形成惡性迴圈。
而使用 systemd timer 可以建立任務之間的依賴關係,例如在第一個備份任務完成後再啟動第二個備份任務,以此類推。
systemd timer 原理
systemd 定時任務基於 systemd 的單元管理器。它使用兩種類型的單元來管理定時任務:.timer
單元和 .service
單元。
.timer
單元:.timer
單元定義了定時規則,包括啟動時間、間隔時間等。- 每個
.timer
單元都對應一個或多個關聯的.service
單元。
.service
單元:.service
單元定義了要在計時器觸發時運行的服務或命令。- 當
.timer
觸發時,相關聯的.service
單元將被啟動。
systemd 定時任務原理是:systemd 定期檢查每個 .timer
單元中定義的定時規則,以確定是否觸發相應的定時器。一旦定時器觸發,systemd 將啟動與該定時器關聯的 .service
單元,從而執行預定的任務。
在正式介紹 systemd 定時任務之前,我們先要瞭解什麼是單元(unit)。
systemd 單元
簡單來講,單元就是 systemd 的最小管理單位,是單個進程的描述。一個個單元相互調用和依賴,組成一個龐大的任務管理系統。
systemd 中的 unit 有很多類型,下麵是一些常見的 unit 類型:
.service
:service 單元,也就是我們常說的系統服務.target
:target 單元,其實就是一堆 unit 的集合,比如常見的multi-user.target
.timer
:timer 單元,負責定時任務。.slice
:slice 單元,負責資源的分配。
每個 unit 都有一個描述文件(unit 負責乾什麼、怎麼乾...),它們分散在三個目錄:
/lib/systemd/system
:系統預設的 unit 文件/etc/systemd/system
:包含用戶自定義的 unit 文件,如果設置了開機自啟動,則該目錄下的 unit 描述文件會創建一個符號鏈接。/usr/lib/systemd/system
:用戶自己定義的 unit 文件,也會包含一些系統預設的 unit 文件
大多數 linux 發行版中
/lib
是/usr/lib
的軟鏈接,所以 1 和 3 其實是同一目錄,作用自然應該是相同的。
其實可以簡單分成兩類:
/etc/systemd/system
:用戶自定義的 unit 文件/usr/lib/systemd/system
:系統預設的 unit 文件和用戶安裝軟體的 unit 文件
# 查看所有 unit
$ systemctl list-unit-files
# 查看所有 Service unit
$ systemctl list-unit-files --type service
# 查看所有 Timer unit
$ systemctl list-unit-files --type timer
關於 systemd unit 相關的內容這裡就不細講了,大家可以看我之前的文章:《systemctl 命令設置開機自啟動失敗 》
設置 systemd 定時任務
有一個檢查 https 證書是否過期的腳本 check_https.sh
,我們現在需要系統定期執行這個腳本,除此之外,系統在開機之後也會執行這個腳本。
首先創建一個 service unit
[root@localhost ~]# cat /usr/lib/systemd/system/check-https.service
[Unit]
Description=check https certificates
[Service]
Type=oneshot
ExecStart=check_https.sh
[Install]
WantedBy=multi-user.target
Type=oneshot
表示 service 以一次性(Oneshot)方式運行。這意味著當啟動 service 時,它將執行一次,併在完成後退出。
然後我們創建一個 timer unit
Service unit 只是定義瞭如何執行任務,要定時執行這個 Service,還必須定義 Timer unit
[root@localhost ~]# cat /usr/lib/systemd/system/check-https.timer
[Unit]
Description=Runs check https every day
[Timer]
OnUnitActiveSec=24h
Unit=check-https.service
[Install]
WantedBy=multi-user.target
我們著重來看下 [Timer] 部分:
OnActiveSec
:定時任務生效後,多少時間開始執行任務OnBootSec
:系統啟動後,多少時間開始執行任務OnStartupSec
:Systemd 進程啟動後,多少時間開始執行任務OnUnitActiveSec
:該 unit 上次執行後,等多少時間再次執行OnUnitInactiveSec
: 定時任務上次關閉後多少時間,再次執行OnCalendar
:基於絕對時間,而不是相對時間執行AccuracySec
:如果因為各種原因,任務必須推遲執行,推遲的最大秒數,預設是60秒Unit
:真正要執行的任務,預設是同名的帶有.service
尾碼的 unitPersistent
:如果設置了該欄位,即使定時任務到時沒有啟動,也會自動執行相應的 unitWakeSystem
:如果系統休眠,是否自動喚醒系統
上面的 timer 文件里,OnUnitActiveSec=24h
表示 24 小時執行一次任務。
下麵是其他的寫法:
1、在系統啟動 15 分鐘後執行,併在系統運行時,每周執行一次
[Timer]
OnBootSec=15min
OnUnitActiveSec=1w
Unit=check-https.service
2、每周周一執行,如果到時定時任務沒有啟動,會立即執行
[Timer]
OnCalendar=weekly
Persistent=true
Unit=check-https.service
3、每周日凌晨三點執行(時間格式:Year-Month-Day Hour:Minute:Second
)
[Timer]
OnCalendar=Sun *-*-* 03:00:00
Unit=check-https.service
官方文檔:https://www.freedesktop.org/software/systemd/man/latest/systemd.time.html
然後我們啟動這個定時任務,並設置開機自啟動
# 重新載入配置
systemctl daemon-reload
systemctl start check-https.timer
systemctl enable check-https.timer
其他一些定時任務命令:
# 查看所有正在運行的定時任務
systemctl list-timers
# 關閉定時任務
systemctl stop check-https.timer
# 查看定時任務狀態
systemctl status check-https.timer