---
tags: notes, timer, systemd
---
# 使用 systemd timer 取代 crontab
- 現代主流的 Linux 系統,預設使用 systemd 做系統管理
- systemd timer 可取代 crontab,較易 debug 和操作,重要的工作推薦花時間改寫
- 避免文章過於複雜,簡化功能描述
- 本文假設用戶有 root 權限
- 本文連結 : https://hackmd.io/@kmo/notes_systemd_timer
## systemd timer 優點
::: spoiler
- 較容易 debug
- 當上一時間步 `foo.service` 還處於執行狀態,下一時間步到了也不會重複執行 `foo.service`,可以避免重複執行造成 process 壘加,導致系統異常
- 舉例來說:
每 5 分鐘執行一次 `foo.service`,當 09 點 10 分到了,結果 09 點 05 分的 `foo.service` 還在執行中,`foo.timer` 判斷 `foo.service` 還是處於`activating` 狀態,就不會再啟動 `foo.service`
- systemd timer 可精確到秒,以秒執行,而 crontab 較難以實現。比如 30 秒執行一次腳本,使用 systemd timer 可輕易實現
- 可透過 `foo.service` 承接 Linux 的功能,比如限制使用的 CPU 和記憶體等
:::
## systemd timer 缺點
::: spoiler
- 相對於 crontab,使用 systemd timer 需要撰寫 2 個檔案
- 學習曲線相對高。需要對 Linux 系統較高的熟悉度,才會較好理解,也比較不容易出錯
:::
## systemd 基本介紹
::: spoiler
- systemd 常見於系統以下 2 位置
```bash=
# 用戶自定義檔案,也是接下來會用到路徑
/etc/systemd/system/*
# 通常為系統安裝套件預設放置位置 (ex: deb, rpm...)
/usr/lib/systemd/system/*
```
- systemctl 基本指令
```bash=
# 立即執行 or 停止指定的 service
systemctl {start,stop} foo.service
# 啟用 or 取消開機時會自動執行指定的 service
systemctl {enable,disable} foo.service
# 重啟指定的 service
systemctl restart foo.service
# 當有編輯 systemd,記得 reload
systemctl daemon-reload
```
- systemctl 操作以上指令,會記錄到作業系統的 syslog,如 CentOS 7 作業系統的 `/var/log/messages`
- 當使用 `systemctl` 指令操作時,若沒有加結尾,預設你是指 `.service`
舉例如下,以下是相同指令
```bash=
systemctl status foo
systemctl status foo.service
```
- 其他結尾有特定功能。例如本文介紹 `*.timer`,`*.timer` 會去執行和自己同樣名稱的 `*.service`。如 `foo.timer` 時間到會去執行`foo.service`
:::
## systemd timer 範例
- 為最簡單範例,只留下必要設定
### 情境
- 每 5 分鐘執行一次腳本 `/opt/foo.sh`
### 撰寫 systemd 的檔案
::: spoiler
- 分別撰寫 2 個檔案,`foo.service` 和 `foo.timer` 放底下指定路徑
- service 功能 : 定義執行什麼工作 (what)
- timer 功能 : 定義何時執行 (when)
- `/etc/systemd/system/foo.service`
```bash=
[Service]
Type=oneshot
ExecStart=/opt/foo.sh
[Install]
WantedBy=multi-user.target
```
- `/etc/systemd/system/foo.timer`
```bash=
[Timer]
OnBootSec=5min
OnUnitActiveSec=5min
AccuracySec=1min
[Install]
WantedBy=timers.target
```
- 當有編輯 systemd 記得 reload
```bash=
systemctl daemon-reload
```
:::
### systemd 檔案參數說明
::: spoiler
- `/etc/systemd/system/foo.service`
```bash=
Type=oneshot #oneshot 是指執行一次
ExecStart=/opt/foo.sh #這邊指定你要執行的腳本路徑,權限要可執行
```
- `/etc/systemd/system/foo.timer`
```bash=
OnBootSec=5min #開機後 5 分鐘執行
OnUnitActiveSec=5min #每 5 分鐘執行一次
AccuracySec=1min #精確到分鐘
```
:::
### 測試及啟用 systemd
::: spoiler
- 主要腳本是透過 service 執行,先執行一次 `foo.service`,確認能成功執行
```bash=
# start
systemctl start foo.service
# check status
systemctl status foo.service
```
- 執行 `foo.timer`,當設定的每 5 分鐘時間到了,`foo.timer` 會自動執行 `foo.service`
```bash=
# start
systemctl start foo.timer
```
- 列出 timer 並查看 `foo.timer` 執行的狀態 (很重要的功能)
```bash=
systemctl list-timers
```
- 確認符合預期後,啟用讓他開機能自動執行
```bash=
systemctl enable foo.timer
```
:::
## 後記
::: spoiler
- 由於沒有詳盡到每個參數解釋,網路上也已經有很多不同詳細中文/英文資料說明 systemd,當有不懂推薦可以先 google 關鍵字查看看 :)
:::
## 參考連結
::: spoiler
- [ ubuntu 論壇網友回覆](https://askubuntu.com/a/1083647): 本文參考此網友說明的概念
- [arch linux 的 wiki](https://wiki.archlinux.org/title/systemd): 針對 systemd 說明文件,非常簡潔清楚
- [systemd unit 的官方文件](https://www.freedesktop.org/software/systemd/man/systemd.unit.html)
- [systemd timer 的官方文件](https://www.freedesktop.org/software/systemd/man/systemd.timer.html)
:::
---
{%hackmd @kmo/widget_license %}