轉自 https://segmentfault.com/a/1190000014740871
0x01 什么是Systemd Service
- Systemd 服務是一種以 .service 結尾的單元(unit)配置文件,用於控制由Systemd 控制或監視的進程。簡單說,用於后台以守護精靈(daemon)的形式運行程序。
- Systemd 廣泛應用於新版本的RHEL、SUSE Linux Enterprise、CentOS、Fedora和openSUSE中,用於替代舊有的服務管理器
service
。 - 基本命令:
systemctl command xxx.service
# 其中command可以是start、stop、restart、enable等,比如: systemctl start httpd.service #啟動Apache服務 systemctl stop httpd.service #停止Apache服務 systemctl restart httpd.service #停止Apache服務 systemctl enable mariadb.service #將MariaDB服務設為開機啟動
0x02 Systemd Service 存放的位置
- Systemd Service 位於
/etc/systemd/system
(供系統管理員和用戶使用),/usr/lib/systemd/system
(供發行版打包者使用),我們一般使用前者即可。
0x03 編寫Systemd Service
- Systemd 服務的內容主要分為三個部分,控制單元(unit)的定義、服務(service)的定義、以及安裝部分。
1. 定義控制單元 [Unit]
- 在 Systemd 中,所有引導過程中 Systemd 要控制的東西都是一個單元。基本的用法如下:
- Description:代表整個單元的描述,可根據需要任意填寫。
- Wants:本單元啟動了,它“想要”的單元也會被啟動。但是這個單元若啟動不成功,對本單元沒有影響。
- Requires: 這個單元啟動了,那么它“需要”的單元也會被啟動; 它“需要”的單元被停止了,它自己也活不了。但是請注意,這個設定並不能控制啟動順序,因為它“需要”的單元啟動也需要時間,若它“需要”的單元啟動還未完成,就開始啟動本單元,則本單元也無法啟動,所以不建議使用這個字段。
- OnFailure:若本單元啟動失敗了,那么啟動這個單元作為折衷。
- Before/After:指定啟動順序。
- 看一個實際的例子:
[Unit] Description=Protect ARP list Wants=network-online.target After=network.target
- 其中network.target代表有網路,network-online.target代表一個連通着的網絡。
2. 定義服務本體 [service]
- 在定義完了 Systemd 用來識別服務的單元后,我們來定義服務本體。基本的用法如下:
-
Type:服務的類型,各種類型的區別如下所示
- simple:默認,這是最簡單的服務類型。意思就是說啟動的程序就是主體程序,這個程序要是退出那么一切皆休。
- forking:標准 Unix Daemon 使用的啟動方式。啟動程序后會調用 fork() 函數,把必要的通信頻道都設置好之后父進程退出,留下守護精靈的子進程。
- oneshot:適用於那些被一次性執行的任務或者命令,它運行完成后便了無痕跡。因為這類服務運行完就沒有任何痕跡,我們經常會需要使用 RemainAfterExit=yes。意思是說,即使沒有進程存在,Systemd 也認為該服務啟動成功了。同時只有這種類型支持多條命令,命令之間用
;
分割,如需換行可以用\
。 - dbus:這個程序啟動時需要獲取一塊 DBus 空間,所以需要和 BusName= 一起用。只有它成功獲得了 DBus 空間,依賴它的程序才會被啟動。
- ExecStart:在輸入的命令是start時候執行的命令,這里的命令啟動的程序必須使用絕對路徑,比如你必須用
/sbin/arp
而不能簡單的以環境變量直接使用arp
。 - ExecStop:在輸入的命令是stop時候執行的命令,要求同上。
- ExecReload:這個不是必需,如果不寫則你的service就不支持restart命令。ExecStart和ExecStop是必須要有的。
- 看一個實際的例子:
[Service] Type=oneshot RemainAfterExit=yes ExecStart=/sbin/arp -f /etc/ip-mac ExecReload=/sbin/arp -f /etc/ip-mac ExecStop=/sbin/arp -d -a
- 這里在start和restart的時候會讀取並添加
/etc/ip-mac
文件中的ARP條目到ARP表中,而stop時清空ARP表。
3. 安裝服務 [install]
- 服務編寫完之后還需要被systemd裝載,定義安裝單元各個字段如下:
- WantedBy:設置服務被誰裝載,一般設置為
multi-user.target
- Alias:為service設置一個別名,可以使用多個名字來操作服務。
- Also:在安裝這個服務時候還需要的其他服務
4.完整的 Systemd Service 配置實例
- 組合上面的三個模塊,我們可以得到一個完整的 Systemd Service 配置實例:
[Unit] Description=Protect ARP list Wants=network-online.target After=network.target [Service] Type=oneshot RemainAfterExit=yes ExecStart=/sbin/arp -f /etc/ip-mac ExecReload=/sbin/arp -f /etc/ip-mac ExecStop=/sbin/arp -d -a [Install] WantedBy=multi-user.target
0x04 總結
- Systemd Service 是一種替代
/etc/init.d/
下腳本的更好方式,它可以靈活的控制你什么時候要啟動服務,一般情況下也不會造成系統無法啟動進入緊急模式。所以如果想設置一些開機啟動的東西,可以試着寫 Systemd Service。當然了,前提是你使用的Linux發行版是支持它的才行。
參考資料: openSUSE:How to write a systemd service
https://wiki.ubuntu.com/systemd
https://wiki.archlinux.org/index.php/Systemd
https://fedoraproject.org/wiki/User:Johannbg/Features/SysVtoSystemd