Linux下注冊系統服務

strongmore發表於2024-04-20

前言

init

歷史上,Linux 的啟動一直採用 init 程序。在類 Unix 的計算機作業系統中,init(初始化的簡稱)是在啟動計算機系統期間啟動的第一個程序。init 是一個守護程序,它將持續執行,直到系統關閉。它是所有其他程序的直接或間接的父程序。因為 init 的引數全在/etc/init.d目錄下,所以使用 init 啟動一個服務,應該這樣做:

sudo /etc/init.d/nginx start

service

service 是一個執行System V init的指令碼命令。那麼什麼是 System V init 呢?也就是 /etc/init.d 目錄下的引數。所以分析可知 service 是去/etc/init.d目錄下執行相關程式,服務配置檔案的存放目錄就是/etc/init.d。

使用 service 啟動一個服務

service nginx start

可以理解成 service 就是 init.d 的一種實現方式。
所以這兩者啟動方式(或者是停止、重啟)並沒有什麼區別。

sudo /etc/init.d/nginx start
// 等價於
service nginx start

但是這兩種方式均有如下缺點:

  1. 啟動時間長。init 程序是序列啟動,只有前一個程序啟動完,才會啟動下一個程序。
  2. 啟動指令碼複雜。init 程序只是執行啟動指令碼,不管其他事情。指令碼需要自己處理各種情況,這往往使得指令碼變得很長。

systemd

systemd 就是為了解決這些問題而誕生的。它的設計目標是,為系統的啟動和管理提供一套完整的解決方案。
根據 Linux 慣例,字母d是守護程序(daemon)的縮寫。 systemd 這個名字的含義,就是它要守護整個系統。

使用了 systemd,就不需要再用 init 了。systemd 取代了initd,成為系統的第一個程序(pid 等於 1),其他程序都是它的子程序。

systemd 的優點是功能強大,使用方便,缺點是體系龐大,非常複雜。systemd 並不是一個命令,而是一組命令,涉及到系統管理的方方面面。systemctl 是 systemd 的主命令,用於管理系統。

Linux下注冊系統服務

總結

  • init 是最初的程序管理方式
  • service 是 init 的另一種實現
  • systemd 則是一種取代 initd 的解決方案

使用

將程式註冊為系統服務,需要編輯 xxx.service 配置檔案,並將檔案儲存到 /usr/lib/systemd/system/ 目錄下

配置檔案介紹

[Unit] 區塊:啟動順序與依賴關係。
  • Description:簡短描述
  • Documentation:文件地址
  • Requires:當前 Unit 依賴的其他 Unit,如果它們沒有執行,當前 Unit 會啟動失敗
  • Wants:與當前 Unit 配合的其他 Unit,如果它們沒有執行,當前 Unit 不會啟動失敗
  • BindsTo:與Requires類似,它指定的 Unit 如果退出,會導致當前 Unit 停止執行
  • Before:如果該欄位指定的 Unit 也要啟動,那麼必須在當前 Unit 之後啟動
  • After:如果該欄位指定的 Unit 也要啟動,那麼必須在當前 Unit 之前啟動
[Service] 區塊:啟動行為
  • Type:定義啟動時的程序行為。它有以下幾種值。
    • Type=simple:預設值,執行ExecStart指定的命令,啟動主程序
    • Type=forking:以 fork 方式從父程序建立子程序,建立後父程序會立即退出
    • Type=oneshot:一次性程序,Systemd 會等當前服務退出,再繼續往下執行
    • Type=dbus:當前服務透過D-Bus啟動
    • Type=notify:當前服務啟動完畢,會通知Systemd,再繼續往下執行
    • Type=idle:若有其他任務執行完畢,當前服務才會執行
  • ExecStart:啟動當前服務的命令
  • ExecStartPre:啟動當前服務之前執行的命令
  • ExecStartPost:啟動當前服務之後執行的命令
  • ExecReload:重啟當前服務時執行的命令
  • ExecStop:停止當前服務時執行的命令
  • ExecStopPost:停止當其服務之後執行的命令
  • RestartSec:自動重啟當前服務間隔的秒數
  • Restart:定義何種情況 Systemd 會自動重啟當前服務,可能的值包括always(總是重啟)、on-success、on-failure、on-abnormal、on-abort、on-watchdog
  • TimeoutSec:定義 Systemd 停止當前服務之前等待的秒數
  • Environment:指定環境變數

注意:Type=simple 時,如果啟動指令碼中 以 nohup & 形式啟動程序時,此時啟動指令碼後會自動 kill 當前服務。

[Install] 區塊

定義如何安裝這個配置檔案,即怎樣做到開機啟動。

  • WantedBy欄位:表示該服務所在的 Target。

Target的含義是服務組,表示一組服務。預設的啟動 Target 就是 multi-user.target(多使用者命令列))。在這個組裡的所有服務,都將開機啟動。這就是為什麼 systemctl enable 命令能設定開機啟動的原因。

程式準備

這裡我們註冊的服務名為 test_systemd.service

[Unit]
Description=test program
After=network.target
Wants=network.target

[Service]
Type=simple
ExecStart=/root/test_systemd/test_systemd_start.sh
ExecStop=/bin/kill -9 $MAINPID
ExecReload=/bin/kill -s HUP $MAINPID

[Install]
WantedBy=multi-user.target

服務啟動要執行的程式為 test_systemd_start.sh

#!/bin/bash
/root/test_systemd/test_while.sh >> /dev/null

test_while.sh 程式內容為

#!/bin/bash
i=1
while [ $i -le 10000  ];do
    let i=$i+1
    sleep 10
    echo `date` >> /root/test_systemd/while_sh.log
done

總結如下

  1. 我們要註冊的服務,啟動要做的操作為:開啟一個程序,每隔10秒,向 while_sh.log 日誌檔案追加一條日誌記錄
  2. 停止要做的操作為:將上面的程序給 kill 掉

驗證

chmod a+x test_systemd_start.sh # 新增執行許可權
chmod a+x test_while.sh
cp test_systemd.service /usr/lib/systemd/system/ # 將配置檔案複製到指定目錄
systemctl daemon-reload # 重新載入配置檔案
systemctl start test_systemd # 等價於 systemctl start test_systemd.service
tail -f /root/test_systemd/while_sh.log

常用命令為

systemctl  status  xxx      # 檢視服務狀態
systemctl  start  xxx       # 啟動服務
systemctl  stop  xxx        # 停止服務
systemctl  restart  xxx     # 重啟服務
systemctl  enable  xxx      # 啟用服務開機自啟動
systemctl  disable  xxx     # 禁止服務開機自啟動

如果啟動失敗,可以透過以下命令排查

systemctl  status  xxx
journalctl -xe

參考

Systemd 入門教程:命令篇
Systemd 入門教程:實戰篇
Linux init、service、systemctl 三者區別
Linux:註冊系統服務

相關文章