本篇介紹如何在各種 Linux 下使用 systemctl 指令管理 Systemd 的系統服務。

傳統上的 Linux 都是靠 System V 的 init 來啟動各項系統服務,而後來新的 Systemd 出現之後,許多主流的 Linux 發行版都改用 Systemd 來管理系統服務,新的 Systemd 跟傳統 System V 的 init 相比,開機速度更快、效能更好、具有相依性檢查功能。


以下我們將介紹 Systemd 的使用與管理方式,這裡所講述的內容適用於各種 Linux 發行版,例如 Ubuntu、Debian、CentOS、Fedora、Red Hat 等。

Systemd 基本服務管理

在 Systemd 中每一個系統服務就稱為一個服務單位(unit),而服務單位又可以區分為 service、socket、target、path、snapshot、timer 等多種不同的類型(type),我們可以從設定檔的附檔名來判斷該服務單位所屬的類型,最常見的就是以 .service 結尾的系統服務,大部分的伺服器都是屬於這種。

如果要管理 Systemd 中的各種服務,可以使用 systemctl 這個指令,配合各種操作指令來進行各種操作。

systemctl 操作指令 服務名稱.service

若要啟動系統服務,可以使用 start 操作指令,例如啟動 Nginx 網頁伺服器:

# 啟動 nginx 網頁伺服器服務
sudo systemctl start nginx.service

若要顯示指定的系統服務狀態,可以使用 status 操作指令:

# 顯示 nginx 服務狀態
systemctl status nginx.service

若要停止指定的系統服務狀態,可以使用 stop 操作指令:

# 停止 nginx 服務
sudo systemctl stop nginx.service

當我們在指定服務名稱時,可以將結尾的 .service 省略,這樣可以少打一些字,例如:

# 啟動 nginx 網頁伺服器服務
sudo systemctl start nginx

# 顯示 nginx 服務狀態
systemctl status nginx

# 停止 nginx 服務
sudo systemctl stop nginx

啟用、停用開機自動啟動服務

systemctlstartstop 兩個操作指令是用來控制目前服務的狀態,如果想要設定開機自動啟動服務的話,就要改用 enabledisable

# 設定開機自動啟動 nginx 網頁伺服器
sudo systemctl enable nginx

# 取消開機自動啟動 nginx 網頁伺服器
sudo systemctl disable nginx

檢測系統服務狀態

以下是一些用來檢測系統服務狀態的操作指令:

# 檢查 nginx 服務是否正在運行
systemctl is-active nginx.service

# 檢查 nginx 服務是否有設定開機自動啟動
systemctl is-enabled nginx.service

# 檢查 nginx 服務是否啟動失敗
systemctl is-failed nginx.service

這幾個指令在撰寫系統管理的 shell 指令稿時會很好用,以下是一個範例:

# 判斷服務狀態的 Bash 指令稿
IS_ACT=`systemctl is-active nginx.service`
if [ "$IS_ACT" == "active" ]; then
  echo "Nginx is active."
else
  echo "Nginx is not active."
fi

假設我們想要撰寫一個指令稿,定期檢查特定服務,在服務出問題的時候自動重新啟動,或是發送 Email 通知,就可以從這段指令稿來修改。

列出 Systemd 所有服務

若想要列出所有已啟動的服務,可以使用 list-units 操作指令:

# 列出所有已啟動的服務
systemctl list-units
UNIT                                      LOAD   ACTIVE SUB     DESCRIPTION
atd.service                               loaded active running ATD daemon
avahi-daemon.service                      loaded active running Avahi mDNS/DNS-SD Stack
dbus.service                              loaded active running D-Bus System Message Bus
[略]

list-units 的輸出包含許多欄位,以下是各個欄位的說明。

欄位說明
UNITSystemd 服務單位(unit)名稱。
LOAD該服務單位設定檔是否有被 Systemd 載入至記憶體中。
ACTIVE是否已經正常啟動。
SUB更詳細的狀態說明,值會因為不同服務有所不同。
DESCRIPTION關於此服務的簡單說明。

事實上 systemctl 的預設動作就是列出所有已啟動的服務,所以也可以省略 list-units

# 列出所有已啟動的服務
systemctl

如果想要列出系統上所有的服務(包含已啟動與未啟動的),可以加上 --all 參數:

# 列出系統上所有的服務
systemctl list-units --all

如果想列出未啟動的所有服務,可以加上 --state=inactive

# 列出系統上所有未啟動的服務
systemctl list-units --all --state=inactive

只列出系統上所有 service 類型的服務也是很常用的:

# 只列出系統上所有 service 類型的服務
systemctl list-units --type=service

服務內部設定與狀態

如果想要查看指定服務的 Systemd 設定檔內容,可以用 cat 操作指令將設定檔印出來:

# 查看服務內部設定檔
systemctl cat atd.service
# /usr/lib/systemd/system/atd.service
[Unit]
Description=Job spooling tools
After=syslog.target systemd-user-sessions.service

[Service]
EnvironmentFile=/etc/sysconfig/atd
ExecStart=/usr/sbin/atd -f $OPTS
IgnoreSIGPIPE=no

[Install]
WantedBy=multi-user.target

Systemd 會自動處理服務的相依性問題,如果想要查看特定服務的相依服務,可以使用 list-dependencies 操作指令:

# 查看特定服務的相依服務
systemctl list-dependencies sshd.service
sshd.service
● ├─sshd-keygen.service
● ├─system.slice
● └─basic.target
●   ├─firewalld.service
[略]

若想要查看特定服務的底層設定值,可以使用 show 操作指令:

# 查看特定服務的底層設定值
systemctl show sshd.service
Type=notify
Restart=on-failure
NotifyAccess=main
RestartUSec=42s
TimeoutStartUSec=1min 30s
TimeoutStopUSec=1min 30s
[略]

由於底層設定值非常多,如果只想要查看特定的設定值,可以用 -p 參數來指定:

# 查看特定服務的特定設定值
systemctl show sshd.service -p MainPID
MainPID=9898

遮蔽特定服務

在某些情況下我們可能會希望停用某項服務,避免它被手動或自動啟動,這時候就可以利用 mask 操作指令,將特定的服務遮蔽起來:

# 遮蔽特定服務
sudo systemctl mask nginx.service

服務被遮蔽之後,就會無法啟動:

# 嘗試啟動被遮蔽的服務
sudo systemctl start nginx.service
Failed to start nginx.service: Unit nginx.service is masked.

如果想恢復被遮蔽的服務,可以使用 unmask 操作指令:

# 恢復被遮蔽的服務
sudo systemctl unmask nginx.service

編輯服務設定

如果想要更改某些服務的設定,可以使用 edit 操作指令:

# 編輯服務設定
sudo systemctl edit nginx.service

執行這行指令之後,會開啟一個空白的檔案,讓管理者將新的設定值寫在裡面,存檔離開後,Systemd 會在 /etc/systemd/system/ 目錄之下,建立一個服務名稱加上 .d 的子目錄(以這個例子來說就是 nginx.service.d),然後將新增的設定寫在這個子目錄下的 override.conf 中,之後 Systemd 在載入服務設定檔時,就會自動優先採用此處的設定。

如果想要直接編輯完整的設定檔,可以加上 --full 參數:

# 編輯服務設定(顯示完整設定內容)
sudo systemctl edit --full nginx.service

這樣的修改方式就會直接把完整的設定寫入 /etc/systemd/system/ 目錄底下,而 Systemd 會優先採用此處的設定值。

如果想要移除先前用 edit 修改的設定,只要直接刪除對應的 .d 目錄即可:

# 刪除自己修改的設定
sudo rm -r /etc/systemd/system/nginx.service.d

如果是以 --full 模式修改的話,就要刪除對應的設定檔,然後重新載入 Systemd:

# 刪除自己修改的設定(full 模式)
sudo rm /etc/systemd/system/nginx.service

# 重新載入 Systemd
sudo systemctl daemon-reload

如果想要自己新增 Systemd 的服務單位,可參考 Linux 建立自訂 Systemd 服務教學文章

參考資料:鳥哥的 Linux 私房菜Digital OceanDigital Ocean