Linux中國

在 Linux 上使用 systemd 設置定時器

之前,我們看到了如何手動的在開機與關機時在啟用某個設備時在文件系統發生改變時 啟用與禁用 systemd 服務。

定時器增加了另一種啟動服務的方式,基於……時間。儘管與定時任務很相似,但 systemd 定時器稍微地靈活一些。讓我們看看它是怎麼工作的。

「定時運行」

讓我們展開本系列前兩篇文章你所設置的 Minetest 伺服器作為如何使用定時器單元的第一個例子。如果你還沒有讀過那幾篇文章,可以現在去看看。

你將通過創建一個定時器來「改進」 Minetest 伺服器,使得在伺服器啟動 1 分鐘後運行遊戲伺服器而不是立即運行。這樣做的原因可能是,在啟動之前可能會用到其他的服務,例如發郵件給其他玩家告訴他們遊戲已經準備就緒,你要確保其他的服務(例如網路)在開始前完全啟動並運行。

最終,你的 minetest.timer 單元看起來就像這樣:

# minetest.timer
[Unit]
Description=Runs the minetest.service 1 minute after boot up

[Timer]
OnBootSec=1 m
Unit=minetest.service

[Install]
WantedBy=basic.target

一點也不難吧。

如以往一般,開頭是 [Unit] 和一段描述單元作用的信息,這兒沒什麼新東西。[Timer] 這一節是新出現的,但它的作用不言自明:它包含了何時啟動服務,啟動哪個服務的信息。在這個例子當中,OnBootSec 是告訴 systemd 在系統啟動後運行服務的指令。

其他的指令有:

  • OnActiveSec=,告訴 systemd 在定時器啟動後多長時間運行服務。
  • OnStartupSec=,同樣的,它告訴 systemd 在 systemd 進程啟動後多長時間運行服務。
  • OnUnitActiveSec=,告訴 systemd 在上次由定時器激活的服務啟動後多長時間運行服務。
  • OnUnitInactiveSec=,告訴 systemd 在上次由定時器激活的服務停用後多長時間運行服務。

繼續 minetest.timer 單元,basic.target 通常用作 後期引導服務 late boot services 同步點 synchronization point 。這就意味著它可以讓 minetest.timer 單元運行在安裝完 本地掛載點 local mount points 或交換設備,套接字、定時器、路徑單元和其他基本的初始化進程之後。就像在第二篇文章中 systemd 單元里解釋的那樣,targets 就像 舊的運行等級 old run levels 一樣,可以將你的計算機置於某個狀態,或像這樣告訴你的服務在達到某個狀態後開始運行。

在前兩篇文章中你配置的 minetest.service 文件最終看起來就像這樣:

# minetest.service
[Unit]
Description= Minetest server
Documentation= https://wiki.minetest.net/Main_Page

[Service]
Type= simple
User=

ExecStart= /usr/games/minetest --server
ExecStartPost= /home//bin/mtsendmail.sh "Ready to rumble?" "Minetest Starting up"

TimeoutStopSec= 180
ExecStop= /home//bin/mtsendmail.sh "Off to bed. Nightie night!" "Minetest Stopping in 2 minutes"
ExecStop= /bin/sleep 120
ExecStop= /bin/kill -2 $MAINPID

[Install]
WantedBy= multi-user.target

這兒沒什麼需要修改的。但是你需要將 mtsendmail.sh(發送你的 email 的腳本)從:

#!/bin/bash
# mtsendmail
sleep 20
echo $1 | mutt -F /home/<username>/.muttrc -s "$2" my_minetest@mailing_list.com
sleep 10

改成:

#!/bin/bash
# mtsendmail.sh
echo $1 | mutt -F /home/paul/.muttrc -s "$2" pbrown@mykolab.com

你做的事是去除掉 Bash 腳本中那些蹩腳的停頓。Systemd 現在來做等待。

讓它運行起來

確保一切運作正常,禁用 minetest.service

sudo systemctl disable minetest

這使得系統啟動時它不會一同啟動;然後,相反地,啟用 minetest.timer

sudo systemctl enable minetest.timer

現在你就可以重啟伺服器了,當運行 sudo journalctl -u minetest.* 後,你就會看到 minetest.timer 單元執行後大約一分鐘,minetest.service 單元開始運行。

![minetest timer](/data/attachment/album/201811/01/221418yyzjjv5060jv0a5e.png "minetest timer")

圖 1:minetest.timer 運行大約 1 分鐘後 minetest.service 開始運行

時間的問題

minetest.timer 在 systemd 的日誌里顯示的啟動時間為 09:08:33 而 minetest.service 啟動時間是 09:09:18,它們之間少於 1 分鐘,關於這件事有幾點需要說明一下:首先,請記住我們說過 OnBootSec= 指令是從引導完成後開始計算服務啟動的時間。當 minetest.timer 的時間到來時,引導已經在幾秒之前完成了。

另一件事情是 systemd 給自己設置了一個 誤差幅度 margin of error (默認是 1 分鐘)來運行東西。這有助於在多個 資源密集型進程 resource-intensive processes 同時運行時分配負載:通過分配 1 分鐘的時間,systemd 可以等待某些進程關閉。這也意味著 minetest.service 會在引導完成後的 1~2 分鐘之間啟動。但精確的時間誰也不知道。

順便一提,你可以用 AccuracySec= 指令修改誤差幅度

你也可以檢查系統上所有的定時器何時運行或是上次運行的時間:

systemctl list-timers --all

![check timer](/data/attachment/album/201811/01/221426vizdi0z11zjr42mu.png "check timer")

圖 2:檢查定時器何時運行或上次運行的時間

最後一件值得思考的事就是你應該用怎樣的格式去表示一段時間。Systemd 在這方面非常靈活:2 h2 hours2hr 都可以用來表示 2 個小時。對於「秒」,你可以用 secondssecondsecs。「分」也是同樣的方式:minutesminuteminm。你可以檢查 man systemd.time 來查看 systemd 能夠理解的所有時間單元。

下一次

下次你會看到如何使用日曆中的日期和時間來定期運行服務,以及如何通過組合定時器與設備單元在插入某些硬體時運行服務。

回頭見!

在 Linux 基金會和 edx 上通過免費課程 「Introduction to Linux」 學習更多關於 Linux 的知識。

via: https://www.linux.com/blog/learn/intro-to-linux/2018/7/setting-timer-systemd-linux

作者:Paul Brown 選題:lujun9972 譯者:LuuMing 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國