前言
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
但是這兩種方式均有如下缺點:
- 啟動時間長。init 程序是序列啟動,只有前一個程序啟動完,才會啟動下一個程序。
- 啟動指令碼複雜。init 程序只是執行啟動指令碼,不管其他事情。指令碼需要自己處理各種情況,這往往使得指令碼變得很長。
systemd
systemd 就是為了解決這些問題而誕生的。它的設計目標是,為系統的啟動和管理提供一套完整的解決方案。
根據 Linux 慣例,字母d是守護程序(daemon)的縮寫。 systemd 這個名字的含義,就是它要守護整個系統。
使用了 systemd,就不需要再用 init 了。systemd 取代了initd,成為系統的第一個程序(pid 等於 1),其他程序都是它的子程序。
systemd 的優點是功能強大,使用方便,缺點是體系龐大,非常複雜。systemd 並不是一個命令,而是一組命令,涉及到系統管理的方方面面。systemctl 是 systemd 的主命令,用於管理系統。
總結
- 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
總結如下
- 我們要註冊的服務,啟動要做的操作為:開啟一個程序,每隔10秒,向 while_sh.log 日誌檔案追加一條日誌記錄
- 停止要做的操作為:將上面的程序給 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:註冊系統服務