Linux 服務管理之 syste

簡介

systemd 是一種用於 Linux 操作系統的初始化系統和服務管理器,由 Lennart Poettering 主導開發並在 LGPL 2.1 及其後續版本許可證下開源發佈。自 2010 年代中期以來,systemd 已經廣泛被多數主流 Linux 發行版採用,如 Ubuntu、Fedora、openSUSE、Debian 和 CentOS/RHEL 7 及以後版本,作爲默認的初始化系統取代了傳統的 System V init 和 Upstart 等系統。

主要功能和特點

  1. 並行啓動服務:systemd 引入了服務間的依賴關係管理,允許並行啓動多個不相互依賴的服務,顯著縮短了系統啓動時間。

  2. Unit 文件:每個系統資源(如服務、掛載點、設備、sockets、計時器等)都被定義爲一個 “單元”(Unit),並由一個相應的配置文件(Unit file)來描述。這些文件通常位於 /etc/systemd/system/ 或 /usr/lib/systemd/system/ 目錄下,擁有 .service、.socket、.target 等後綴。

  3. 依賴關係管理:systemd 允許精確地定義服務之間的依賴關係,確保服務按照正確的順序啓動或停止。

  4. 系統目標(Targets):類似於 System V init 的運行級別,但更加靈活,代表一組服務的集合,定義了系統的某種運行狀態(如 multi-user.target 對應傳統的運行級別 3)。

  5. journal 日誌:systemd 提供了一個名爲 journal 的日誌系統,用於收集和查看系統日誌,支持快速過濾和查詢。

  6. Socket 激活:服務可以根據實際需求(如客戶端連接)動態激活,而不是一直運行等待請求,提高了資源利用率。

  7. 環境變量與資源限制:Unit 文件中可以設定服務的環境變量、資源使用限制(如內存、CPU 時間)等。

  8. 用戶服務:除了系統級別的服務外,systemd 還支持用戶級別的服務,通過 user@.service 類型的單元。

  9. 網絡命名和管理:systemd 提供了一個叫做 networkd 的組件,用於網絡接口的配置和管理。

  10. 系統狀態與管理工具:systemctl 命令是與 systemd 交互的主要工具,用於啓動、停止、重啓服務,查看服務狀態,管理系統目標等。

原理概述

1.Systemd 初始化過程:

2.Service Unit 文件:

3.systemctl 命令功能:

4.systemctl 命令處理流程:

5. 啓用與禁用服務:

6.Cgroups 和命名空間:

    通過上述機制,systemctl 和 systemd 一起提供了強大且靈活的系統服務管理功能,提升了系統的響應速度和管理效率。

設計單元 unit

systemd 設計的單元(Units)是用於描述系統資源和服務的配置文件,它們代表了 systemd 可以管理的各種不同類型的對象。這些單元類型允許 systemd 根據配置來啓動、停止、重啓或管理相應的系統組件。以下是 systemd 支持的主要單元類型分類:

  1. 服務單元 (.service):這是最常用的單元類型,用於定義系統服務,如守護進程(daemon)及其相關進程。服務單元控制着服務的啓動、停止、重載等操作。

  2. 套接字單元 (.socket):用於管理系統中的本地 IPC(進程間通信)或網絡套接字,支持基於套接字激活服務,即當套接字上有連接請求時自動啓動相應服務。

  3. 目標單元 (.target):作爲一組單元的集合,用於定義系統狀態或運行級別,如多用戶目標(multi-user.target)或圖形界面目標(graphical.target)。切換目標實際上就是啓動或停止與該目標相關聯的一組服務。

  4. 設備單元 (.device):代表系統中的硬件設備,可以用於基於設備的激活,即當設備接入或移除時執行特定操作。

  5. 掛載單元 (.mount):控制文件系統的掛載點,定義如何以及何時掛載或卸載文件系統。

  6. 路徑單元 (.path):監控文件或目錄的存在、不存在、修改等變化,並基於這些變化觸發動作。

  7. 計時器單元 (.timer):用於定義定時任務,可以在特定的時間間隔執行其他單元。

  8. 交換單元 (.swap):管理交換分區或文件,控制交換空間的啓用和禁用。

  9. 自動掛載點單元 (.automount):用於自動掛載文件系統,當訪問到掛載點時才實際掛載,不訪問時自動卸載,節省資源。

  10. Snapshot 單元 (.snapshot):用於保存和恢復系統狀態快照,是系統狀態的即時備份,可用於快速回滾。

  11. Slice 單元 (.slice):用於組織和管理 cgroup 層級,控制資源分配,特別是對於一組相關的進程。

這些單元通過它們的配置文件來定義,並且 systemd 通過解析這些文件來確定如何處理不同的系統組件和服務。每個單元類型都服務於特定的系統管理目的,共同構建了一個強大且靈活的初始化系統和服務管理框架。

服務單元 service

一個典型的. service 服務單元文件示例是管理 SSH 服務的配置文件。SSH 服務允許用戶通過加密的網絡連接遠程登錄系統。下面是一個簡化版的 ssh.service 服務單元文件示例,通常位於 / usr/lib/systemd/system/ssh.service 或 / etc/systemd/system/ssh.service:

[Unit]
Description=OpenSSH server daemon
After=network.target auditd.service
[Service]
Type=notify
ExecStart=/usr/sbin/sshd -D $OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s
[Install]
WantedBy=multi-user.target

這個文件分爲三個部分:

1.[Unit] 部分:描述了單元的元數據和依賴關係。

2.[Service] 部分:定義了服務的具體行爲。

3.[Install] 部分:定義瞭如何將服務安裝到系統中,即決定服務應該在哪種系統目標(target)下啓用。

通過這個服務單元文件,systemd 知道如何控制 SSH 服務的啓動、停止、重啓以及如何響應服務的失敗情況,從而實現了對 SSH 服務的精細管理。

套接字單元. socket

一個套接字單元(.socket)的用例是用於配置監聽特定網絡端口或 Unix 域套接字的服務,以便當有連接請求到達時自動激活相應的服務單元。這有助於減少資源消耗,因爲服務只有在真正需要時才啓動。下面是一個簡單的 HTTP 服務(例如使用 nginx 作爲 Web 服務器)的套接字單元示例,文件可能位於 / etc/systemd/system/nginx.socket:

[Unit]
Description=nginx Web Server Socket
[Socket]
ListenStream=80
Accept=yes
[Install]
WantedBy=sockets.target

這個. socket 單元的各部分解釋如下:

1.[Unit] 部分:描述了單元的基本信息。

2.[Socket] 部分:定義了套接字的具體配置。

3.[Install] 部分:定義瞭如何將套接字單元安裝到系統中。

配合這個. socket 單元,還需要一個對應的服務單元(通常是. service),例如 nginx.service,來定義當套接字接收連接時應執行的服務啓動命令。在服務單元中,通常會使用 Socket = 指令來引用相應的套接字單元,以確保服務只在有實際連接請求時被激活。這樣,當有 HTTP 請求到達 80 端口時,systemd 會自動啓動或喚醒 nginx.service 來處理請求,提高了資源的使用效率。

目標單元. target

一個目標單元(.target)的例子是 multi-user.target,它是 systemd 中一個非常基礎且常用的目標,代表了多用戶、非圖形界面的系統運行狀態。這個目標意味着系統已經完成了初始化並準備好了 shell 接入和其他多用戶服務,但沒有啓動圖形桌面環境。許多服務器系統默認啓動到這個目標。

multi-user.target 並不需要一個顯式的單元文件來定義,因爲它是 systemd 內部預設的目標之一,但理解其概念和用途是非常重要的。下面簡要概述其行爲,雖然實際中你可能不會直接編輯一個 multi-user.target 的配置文件,但可以通過查看其依賴關係來理解它所包含的服務:

[Unit]
Description=Multi-User System
Documentation=man:systemd.special(7)
Requires=basic.target
Conflicts=rescue.service rescue.target
After=sysinit.target basic.target
AllowIsolate=yes

這段描述是示意性的,說明了 multi-user.target 的一些關鍵屬性:

當系統啓動並指定了 multi-user.target 作爲默認目標時,systemd 會啓動所有依賴於 multi-user.target 的服務單元,如 SSH 服務、數據庫服務、Web 服務器等,但不包括 X Window 系統或 GNOME、KDE 等桌面環境服務。這對於大多數服務器場景是理想的,因爲它減少了不必要的圖形界面資源消耗。

設備單元. device

設備單元(.device)是 systemd 用於管理系統中的硬件設備的配置單元。這些單元自動由 udev 規則創建,並且可以用來基於設備的狀態變化(如插入或移除)執行動作。下面是一個簡單的設備單元示例,假設我們要爲一個特定的 USB 存儲設備定義一些自動化行爲,這個設備單元可能被命名爲 / etc/systemd/system/usb_storage_device.device:

[Unit]
Description=USB Storage Device
Wants=usb_storage.mount
[Device]
KernelMatchSubsystem=block
KernelMatchAttributes=idVendor=1234,idProduct=5678
[Install]
WantedBy=dev-block-sda.device

在這個例子中,設備單元定義了以下內容:

1.[Unit] 部分:

2.[Device] 部分:

3.[Install] 部分:

通過這樣的設備單元配置,當系統檢測到符合特定條件的 USB 存儲設備插入時,systemd 可以自動掛載它,或者執行其他定義好的操作,提供了對硬件事件響應的自動化機制。

掛載單元 mount

掛載單元(.mount)用於定義文件系統的掛載點及其掛載參數。這些單元允許 systemd 在系統啓動時自動掛載文件系統,並能夠管理這些掛載點的生命週期。下面是一個掛載單元的例子,用於自動掛載一個名爲 data-disk 的硬盤分區到 / mnt/data 目錄:

[Unit]
Description=Mount for Data Disk
Before=local-fs.target
[Mount]
What=/dev/disk/by-label/data-disk
Where=/mnt/data
Type=ext4
Options=noatime,nodiratime
[Install]
WantedBy=multi-user.target

這個. mount 單元的各個部分說明如下:

1.[Unit] 部分:

2.[Mount] 部分:

3.[Install] 部分:

通過這個掛載單元配置,每當系統進入 multi-user.target 狀態時,systemd 會自動掛載標籤爲 data-disk 的硬盤分區到 / mnt/data 目錄,且遵循指定的掛載選項。

路徑單元 path

路徑單元(.path)用於監控文件或目錄是否存在、是否發生變化,然後基於這些變化來觸發其他單元的操作。下面是一個路徑單元的例子,用於監控日誌目錄 / var/log/app_logs 下是否有新創建的日誌文件,並在檢測到新文件時重新加載 app_logger.service 服務,以確保日誌服務能處理新的日誌條目:

[Unit]
Description=Watch for new log files in /var/log/app_logs
[Path]
PathModified=/var/log/app_logs/*.log
[Install]
WantedBy=multi-user.target

這個. path 單元的各部分含義如下:

1.[Unit] 部分:

2.[Path] 部分:

3.[Install] 部分:

爲了完整實現上述功能,還需要一個服務單元(.service)與之關聯,比如 app_logger.service,並且在該服務單元中使用適當的配置來響應路徑單元觸發的事件。例如,服務單元中可能會包含 ExecReload 指令來定義當路徑單元觸發時執行的重載命令。這樣,一旦 / var/log/app_logs 目錄中有新的日誌文件生成或修改,systemd 就會自動重新加載 app_logger.service,確保日誌處理邏輯能夠及時處理新日誌。

計時器單元 timer

計時器單元(.timer)在 Systemd 中用於安排服務單元或其他單元按指定的時間計劃執行。下面是一個. timer 單元的例子,該例設置了一個每天凌晨 3 點執行一次清理緩存任務的服務。

首先,需要有一個服務單元(如 cache-cleanup.service),定義實際執行的任務:

[Unit]
Description=Cleanup Cache Files
[Service]
Type=oneshot
ExecStart=/usr/local/bin/cleanup_cache.sh

在這個例子中,cleanup_cache.sh 是一個腳本,負責執行實際的緩存清理操作。

接下來是對應的計時器單元(cache-cleanup.timer),用於定時觸發上述服務:

[Unit]
Description=Daily Cache Cleanup Timer
[Timer]
OnCalendar=*-*-* 03:00:00  # 每天凌晨3點執行
Persistent=true          # 如果錯過執行時間,在下次機會立即執行
AccuracySec=1min        # 執行時間的精度,這裏設置爲1分鐘
[Install]
WantedBy=timers.target

[Timer] 部分的設置解釋如下:

最後,通過 [Install] 部分的 WantedBy=timers.target,確保此計時器在系統啓動時被啓用。

要使這個計時器生效,你需要通過 Systemd 的命令行工具進行啓用和啓動操作:

sudo systemctl enable cache-cleanup.timer
sudo systemctl start cache-cleanup.timer

這樣設置後,每天凌晨 3 點,cleanup_cache.service 就會自動執行,完成緩存清理任務。

slice 單元

Slice 單元(.slice)在 Systemd 中用於組織和管理一組相關進程的資源分配,特別是通過 Linux 控制組(cgroups)來實現對 CPU、內存等資源的限制。下面是一個 Slice 單元的例子,展示瞭如何創建一個名爲 user-1000.slice 的 Slice,用於管理屬於用戶 UID 1000 的進程,並設置一些資源限制:

示例:用戶 Slice 單元 (user-1000.slice)

[Unit]
Description=Slice for User with ID 1000
[Slice]
MemoryMax=500M     # 限制該Slice內所有進程的總內存使用量不超過500MB
CPUQuota=20%       # 限制該Slice內所有進程的CPU使用率不超過20%

在這個例子中,.slice 單元定義了幾個關鍵的資源限制:

  1. MemoryMax=500M:設置了該 Slice 內所有進程可使用的最大內存總量爲 500MB。

  2. CPUQuota=20%:限制了該 Slice 內所有進程可使用的 CPU 時間比例,不超過單個 CPU 核心 20% 的計算能力。

創建這樣一個 Slice 單元后,可以通過將用戶會話或者特定服務綁定到這個 Slice 中,來實現對這些進程資源使用的集體管理。例如,你可以通過修改用戶的登錄服務(假設爲 user@.service 模板實例)來指定 Slice:

# 在相應的用戶服務單元(如默認的getty服務)中
[Unit]
...
PartOf=user-1000.slice
[Service]
...

或者,如果要手動將一個已運行的進程移動到該 Slice,可以使用 systemctl set-property 命令調整其控制組歸屬:

sudo systemctl set-property --user my_service.service Slice=user-1000.slice

配置文件

systemd 的配置文件主要是單元(Unit)文件,這些文件定義了系統如何管理不同的實體,如服務、掛載點、設備、sockets、計時器等。以下是幾個主要的目錄及其用途:

1./etc/systemd/system/:此目錄存放系統管理員自定義或修改的單元文件,以及通過軟鏈接指向 / lib/systemd/system / 或其他地方的默認單元文件。管理員在這裏放置的文件優先級最高,可以覆蓋默認設置。開機啓動服務的配置通常通過在此目錄創建軟鏈接到實際的單元文件實現。

2./usr/lib/systemd/system/:這個目錄包含所有預裝服務的默認單元文件。這些是由軟件包安裝時提供的,代表了服務的標準配置。它們的優先級低於 / etc/systemd/system / 目錄中的文件。

3.run/systemd/system/:此目錄用於存放系統運行過程中動態生成的服務腳本或臨時修改的單元文件,這些變化不會永久保存。這個目錄的優先級高於上述兩個目錄,意味着這裏的配置會覆蓋任何靜態配置。

4。/usr/local/lib/systemd/system/:某些本地編譯安裝的軟件可能會將服務單元文件放在這裏,優先級介於 / usr/lib/systemd/system / 和 / etc/systemd/system / 之間。

理解這些目錄的關鍵在於它們的優先級和用途:

  1. lib/systemd/system/ 和 /usr/local/lib/systemd/system/ 存放的是系統或本地安裝的服務的標準配置。

  2. /etc/systemd/system/ 用於系統管理員進行定製化配置,可以覆蓋默認設置。

  3. /run/systemd/system/ 則用於臨時性的、即時生效的配置更改,適合在不希望永久改變配置時使用。

通過這些目錄的組織,systemd 允許系統管理員靈活地調整服務管理配置,同時保持了配置文件的清晰結構和可維護性。

常用命令

systemctl 是 Systemd 系統和服務管理器的主要命令行接口,它提供了一個統一的方式來管理 Linux 系統中的各種服務、系統狀態、以及相關的系統組件。

  1. 服務管理:
  1. 開機啓動管理:
  1. 系統狀態查詢:
  1. 時間安排與定時任務:
  1. 資源管理:
  1. 系統控制:
  1. 日誌查看:
  1. 配置重載:

小結

systemd 作爲一個全面的系統和服務管理框架,通過其高度集成的設計和豐富的功能集,爲 Linux 系統帶來了更快的啓動速度、更高的服務管理效率和更細緻的系統控制能力。儘管它的引入曾引發過爭議,但隨着其在各大發行版中的廣泛應用,systemd 已成爲現代 Linux 系統服務管理的重要組成部分。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/FFVuD09kQcRBub5CWi0pEw