如何編寫一個Systemd Service(轉)


轉自 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM