Systemd 入門教程:命令篇

阮一峰發表於2016-03-07

Systemd 是 Linux 系統工具,用來啟動守護程式,已成為大多數發行版的標準配置。

本文介紹它的基本用法,分為上下兩篇。今天介紹它的主要命令,下一篇介紹如何用於實戰。

一、由來

歷史上,Linux 的啟動一直採用init程式。

下面的命令用來啟動服務。

這種方法有兩個缺點。

一是啟動時間長。init程式是序列啟動,只有前一個程式啟動完,才會啟動下一個程式。

二是啟動指令碼複雜。init程式只是執行啟動指令碼,不管其他事情。指令碼需要自己處理各種情況,這往往使得指令碼變得很長。

二、Systemd 概述

Systemd 就是為了解決這些問題而誕生的。它的設計目標是,為系統的啟動和管理提供一套完整的解決方案。

根據 Linux 慣例,字母d是守護程式(daemon)的縮寫。 Systemd 這個名字的含義,就是它要守護整個系統。

(上圖為 Systemd 作者 Lennart Poettering)

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

上面的命令檢視 Systemd 的版本。

Systemd 的優點是功能強大,使用方便,缺點是體系龐大,非常複雜。事實上,現在還有很多人反對使用 Systemd,理由就是它過於複雜,與作業系統的其他部分強耦合,違反”keep simple, keep stupid”的Unix 哲學。

(上圖為 Systemd 架構圖)

三、系統管理

Systemd 並不是一個命令,而是一組命令,涉及到系統管理的方方面面。

3.1 systemctl

systemctl是 Systemd 的主命令,用於管理系統。

3.2 systemd-analyze

systemd-analyze命令用於檢視啟動耗時。

3.3 hostnamectl

hostnamectl命令用於檢視當前主機的資訊。

3.4 localectl

localectl命令用於檢視本地化設定。

3.5 timedatectl

timedatectl命令用於檢視當前時區設定。

3.6 loginctl

loginctl命令用於檢視當前登入的使用者。

四、Unit

4.1 含義

Systemd 可以管理所有系統資源。不同的資源統稱為 Unit(單位)。

Unit 一共分成12種。

  • Service unit:系統服務
  • Target unit:多個 Unit 構成的一個組
  • Device Unit:硬體裝置
  • Mount Unit:檔案系統的掛載點
  • Automount Unit:自動掛載點
  • Path Unit:檔案或路徑
  • Scope Unit:不是由 Systemd 啟動的外部程式
  • Slice Unit:程式組
  • Snapshot Unit:Systemd 快照,可以切回某個快照
  • Socket Unit:程式間通訊的 socket
  • Swap Unit:swap 檔案
  • Timer Unit:定時器

systemctl list-units命令可以檢視當前系統的所有 Unit 。

4.2 Unit 的狀態

systemctl status命令用於檢視系統狀態和單個 Unit 的狀態。

除了status命令,systemctl還提供了三個查詢狀態的簡單方法,主要供指令碼內部的判斷語句使用。

4.3 Unit 管理

對於使用者來說,最常用的是下面這些命令,用於啟動和停止 Unit(主要是 service)。

4.4 依賴關係

Unit 之間存在依賴關係:A 依賴於 B,就意味著 Systemd 在啟動 A 的時候,同時會去啟動 B。

systemctl list-dependencies命令列出一個 Unit 的所有依賴。

上面命令的輸出結果之中,有些依賴是 Target 型別(詳見下文),預設不會展開顯示。如果要展開 Target,就需要使用--all引數。

五、Unit 的配置檔案

5.1 概述

每一個 Unit 都有一個配置檔案,告訴 Systemd 怎麼啟動這個 Unit 。

Systemd 預設從目錄/etc/systemd/system/讀取配置檔案。但是,裡面存放的大部分檔案都是符號連結,指向目錄/usr/lib/systemd/system/,真正的配置檔案存放在那個目錄。

systemctl enable命令用於在上面兩個目錄之間,建立符號連結關係。

如果配置檔案裡面設定了開機啟動,systemctl enable命令相當於啟用開機啟動。

與之對應的,systemctl disable命令用於在兩個目錄之間,撤銷符號連結關係,相當於撤銷開機啟動。

配置檔案的字尾名,就是該 Unit 的種類,比如sshd.socket。如果省略,Systemd 預設字尾名為.service,所以sshd會被理解成sshd.service

5.2 配置檔案的狀態

systemctl list-unit-files命令用於列出所有配置檔案。

這個命令會輸出一個列表。

這個列表顯示每個配置檔案的狀態,一共有四種。

  • enabled:已建立啟動連結
  • disabled:沒建立啟動連結
  • static:該配置檔案沒有[Install]部分(無法執行),只能作為其他配置檔案的依賴
  • masked:該配置檔案被禁止建立啟動連結

注意,從配置檔案的狀態無法看出,該 Unit 是否正在執行。這必須執行前面提到的systemctl status命令。

一旦修改配置檔案,就要讓 SystemD 重新載入配置檔案,然後重新啟動,否則修改不會生效。

5.3 配置檔案的格式

配置檔案就是普通的文字檔案,可以用文字編輯器開啟。

systemctl cat命令可以檢視配置檔案的內容。

從上面的輸出可以看到,配置檔案分成幾個區塊。每個區塊的第一行,是用方括號表示的區別名,比如[Unit]。注意,配置檔案的區塊名和欄位名,都是大小寫敏感的。

每個區塊內部是一些等號連線的鍵值對。

注意,鍵值對的等號兩側不能有空格。

5.4 配置檔案的區塊

[Unit]區塊通常是配置檔案的第一個區塊,用來定義 Unit 的後設資料,以及配置與其他 Unit 的關係。它的主要欄位如下。

  • Description:簡短描述
  • Documentation:文件地址
  • Requires:當前 Unit 依賴的其他 Unit,如果它們沒有執行,當前 Unit 會啟動失敗
  • Wants:與當前 Unit 配合的其他 Unit,如果它們沒有執行,當前 Unit 不會啟動失敗
  • BindsTo:與Requires類似,它指定的 Unit 如果退出,會導致當前 Unit 停止執行
  • Before:如果該欄位指定的 Unit 也要啟動,那麼必須在當前 Unit 之後啟動
  • After:如果該欄位指定的 Unit 也要啟動,那麼必須在當前 Unit 之前啟動
  • Conflicts:這裡指定的 Unit 不能與當前 Unit 同時執行
  • Condition...:當前 Unit 執行必須滿足的條件,否則不會執行
  • Assert...:當前 Unit 執行必須滿足的條件,否則會報啟動失敗

[Install]通常是配置檔案的最後一個區塊,用來定義如何啟動,以及是否開機啟動。它的主要欄位如下。

  • WantedBy:它的值是一個或多個 Target,當前 Unit 啟用時(enable)符號連結會放入/etc/systemd/system目錄下面以 Target 名 + .wants字尾構成的子目錄中
  • RequiredBy:它的值是一個或多個 Target,當前 Unit 啟用時,符號連結會放入/etc/systemd/system目錄下面以 Target 名 + .required字尾構成的子目錄中
  • Alias:當前 Unit 可用於啟動的別名
  • Also:當前 Unit 啟用(enable)時,會被同時啟用的其他 Unit

[Service]區塊用來 Service 的配置,只有 Service 型別的 Unit 才有這個區塊。它的主要欄位如下。

  • 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-successon-failureon-abnormalon-aborton-watchdog
  • TimeoutSec:定義 Systemd 停止當前服務之前等待的秒數
  • Environment:指定環境變數

Unit 配置檔案的完整欄位清單,請參考官方文件。

六、Target

啟動計算機的時候,需要啟動大量的 Unit。如果每一次啟動,都要一一寫明本次啟動需要哪些 Unit,顯然非常不方便。Systemd 的解決方案就是 Target。

簡單說,Target 就是一個 Unit 組,包含許多相關的 Unit 。啟動某個 Target 的時候,Systemd 就會啟動裡面所有的 Unit。從這個意義上說,Target 這個概念類似於”狀態點”,啟動某個 Target 就好比啟動到某種狀態。

傳統的init啟動模式裡面,有 RunLevel 的概念,跟 Target 的作用很類似。不同的是,RunLevel 是互斥的,不可能多個 RunLevel 同時啟動,但是多個 Target 可以同時啟動。

Target 與 傳統 RunLevel 的對應關係如下。

它與init程式的主要差別如下。

(1)預設的 RunLevel(在/etc/inittab檔案設定)現在被預設的 Target 取代,位置是/etc/systemd/system/default.target,通常符號連結到graphical.target(圖形介面)或者multi-user.target(多使用者命令列)。

(2)啟動指令碼的位置,以前是/etc/init.d目錄,符號連結到不同的 RunLevel 目錄 (比如/etc/rc3.d/etc/rc5.d等),現在則存放在/lib/systemd/system/etc/systemd/system目錄。

(3)配置檔案的位置,以前init程式的配置檔案是/etc/inittab,各種服務的配置檔案存放在/etc/sysconfig目錄。現在的配置檔案主要存放在/lib/systemd目錄,在/etc/systemd目錄裡面的修改可以覆蓋原始設定。

七、日誌管理

Systemd 統一管理所有 Unit 的啟動日誌。帶來的好處就是,可以只用journalctl一個命令,檢視所有日誌(核心日誌和應用日誌)。日誌的配置檔案是/etc/systemd/journald.conf

journalctl功能強大,用法非常多。

相關文章