linux的systemctl 命令用法 轉
目錄
-
預熱
-
管理單個 unit
-
檢視系統上的 unit
-
管理不同的操作環境(target unit)
-
檢查 unit 之間的依賴性
-
相關的目錄和檔案
-
systemctl daemon-reload 子命令
-
總結
筆者在前文中概要的介紹了 systemd 的基本概念和主要特點。由於 systemd 相關的絕大多數任務都是通過 systemctl 命令管理的,所以本文將集中的介紹 systemctl 命令的用法。注意,本文以 ubuntu 16.04 進行介紹,文中所有的 demo 都在 ubuntu 16.04 中完成。
systemctl 命令有兩大類功能:
-
控制 systemd 系統
-
管理系統上執行的服務
在介紹這些功能前讓我們先來熱個身,瞭解些 systemctl 命令自身相關的資訊。
預熱
檢查 systemd 的版本
$ systemctl --version
檢視 systemd 和 systemctl 程式相關的目錄
$ whereis systemd$ whereis systemctl
確認 1 號程序
作為 init 系統,systemd 程序作為系統中的 1 號程序應該是毋庸置疑的,讓我們搜尋與 systemd 相關的程序:
結果讓人有點不敢相信自己的眼睛,我們搜到了好幾個與 systemd 相關的程序,但是卻沒有 1 號程序。讓我們看看 1 號程序是誰:
/sbin/init 是什麼?
好吧,/sbin/init 只是到 /lib/systemd/systemd 的連結檔案,系統的 1 號程序的確是 systemd,只不過在 ubuntu 系統中被起了個別名叫 /sbin/init。
管理單個 unit
systemctl 提供了一組子命令來管理單個的 unit,其命令格式為:
systemctl [command] [unit]
command 主要有:
start:立刻啟動後面接的 unit。
stop:立刻關閉後面接的 unit。
restart:立刻關閉後啟動後面接的 unit,亦即執行 stop 再 start 的意思。
reload:不關閉 unit 的情況下,重新載入配置檔案,讓設定生效。
enable:設定下次開機時,後面接的 unit 會被啟動。
disable:設定下次開機時,後面接的 unit 不會被啟動。
status:目前後面接的這個 unit 的狀態,會列出有沒有正在執行、開機時是否啟動等資訊。
is-active:目前有沒有正在執行中。
is-enable:開機時有沒有預設要啟用這個 unit。
kill :不要被 kill 這個名字嚇著了,它其實是向執行 unit 的程序傳送訊號。
show:列出 unit 的配置。
mask:登出 unit,登出後你就無法啟動這個 unit 了。
unmask:取消對 unit 的登出。
我們先通過 prometheus.service 來觀察服務型別 unit 的基本資訊:
輸出內容的第一行是對 unit 的基本描述。
第二行中的 Loaded 描述作業系統啟動時會不會啟動這個服務,enabled 表示開機時啟動,disabled 表示開機時不啟動。而啟動該服務的配置檔案路徑為:/lib/systemd/system/prometheus.service。
第三行 中的 Active 描述服務當前的狀態,active (running) 表示服務正在執行中。如果是 inactive (dead) 則表示服務當前沒有執行。後面則是服務的啟動時間。
第四行的 Docs 提供了線上文件的地址。
下面的 Main PID 表示程序的 ID,接下來是任務的數量,佔用的記憶體和 CPU 資源。
再下面的 Cgroup 描述的是 cgrpup 相關的資訊,筆者會在後續的文章中詳細的介紹。
最後是輸出的日誌資訊。
關於 unit 的啟動狀態,除了 enable 和 disable 之外還有:
static:這個 unit 不可以自己啟動,不過可能會被其它的 enabled 的服務來喚醒。
mask:這個 unit 無論如何都無法被啟動!因為已經被強制登出。可通過 systemctl unmask 改回原來的狀態。
關於 unit 的執行狀態 Active,除了 active 和 inactive 之外還有:
active (exited):僅執行一次就正常結束的服務,目前並沒有任何程式在系統中執行。舉例來說,開機或者是掛載時才會進行一次的 quotaon 功能,就是這種模式! Quotaon 不需要一直執行,只在執行一次之後,就交給檔案系統去自行處理。通常用 bash shell 寫的小型服務,大多是屬於這種型別。
active (waiting):正在執行當中,不過還再等待其他的事件才能繼續處理。舉例來說,列印的相關服務就是這種狀態。
enable 和 disable 操作
比如我們為 prometheus 服務建立了配置檔案 /lib/systemd/system/prometheus.service,然後執行 enable 命令:
$ sudo systemctl enable prometheus.service
所謂的 enable 就是在 multi-user.target.wants 下面建立了一個連結檔案:
至於為什麼會連結到 multi-user.target.wants 目錄下,則是由 prometheus.server 檔案中的配置資訊決定的。
檢視 unit 的配置
使用 show 子命令可以檢視 unit 的詳細配置情況:
$ sudo systemctl show prometheus.service
這裡的輸出非常多,主要是很多的預設設定也都顯示出來了。
登出與反登出 unit
如果我們想暫時的禁用某個 unit,比如 prometheus.service,可以登出這個 unit,登出之後就無法再啟動這個服務了:
$ sudo systemctl mask prometheus.service
從上圖中的輸出我們可以看到,所謂的登出就是把 prometheus.service 檔案連結到 /dev/null 這個空裝置中去了。所以就無法再啟動該服務了。下面我們嘗試執行一次反登出:
$ sudo systemctl unmask prometheus.service
unmask 操作就是刪除掉 mask 操作中建立的連結。
檢視系統上的 unit
systemctl 提供了子命令可以檢視系統上的 unit,命令格式為:
systemctl [command] [--type=TYPE] [--all]
command 有:
list-units:列出當前已經啟動的 unit,如果新增 -all 選項會同時列出沒有啟動的 unit。
list-unit-files:根據 /lib/systemd/system/ 目錄內的檔案列出所有的 unit。
--type=TYPE:可以過濾某個型別的 unit。
不帶任何引數執行 systemctl 命令會列出所有已啟動的 unit:
系統預設啟動的服務是非常多的,上圖只截取了前面幾行。下面是對輸出的介紹:
UNIT:專案的名稱,包括各個 unit 的類別(看副檔名)。
LOAD:開機時 unit 的配置是否被載入。
ACTIVE:目前的狀態,須與後續的 SUB 搭配!就是我們用 systemctl status 觀察時,active的內容。
DESCRIPTION:描述資訊。
注意,systemctl 不加引數,其實等同於 systemctl list-units!
下面我們檢視系統上一共安裝了多少 unit:
$ sudo systemctl list-unit-files
結果也非常的多,我們仍然只擷取一部分結果。這裡的 STATE 就是我們前面介紹的 服務的啟動狀態,有 enable 和 disable、static 和 mask。
只檢視某種型別的 unit
比如我們只想看服務型別的 unit:
$ systemctl list-units --type=service --all
這次只有以 .service 結尾的 unit 才會出現。
如果要看 mount 型別的 unit 指定 --type=mount 就可以了:
檢視載入失敗的 unit
如果發現某個 unit 不工作,可以檢視是否有 unit 載入失敗:
$ systemctl --failed
管理不同的操作環境(target unit)
通過指定 --type=target 就可以用 systemctl list-units 命令檢視系統中預設有多少種 target:
筆者的 ubuntu 16.04 中居然有 27 個 target!我們在此僅介紹幾個常用的 target。
graphical.target:就是文字介面再加上圖形介面,這個 target 已經包含了下面的 multi-user.target。
multi-user.target:純文字模式!
rescue.target:在無法使用 root 登陸的情況下,systemd 在開機時會多加一個額外的臨時系統,與你原本的系統無關。這時你可以取得 root 的許可權來維護你的系統。
emergency.target:緊急處理系統的錯誤,在無法使用 rescue.target 時,可以嘗試使用這種模式!
shutdown.target:就是執行關機。
getty.target:可以設定 tty 的配置。
正常的模式是 multi-user.target 和 graphical.target 兩個,救援方面的模式主要是 rescue.target 以及更嚴重的 emergency.target。如果要修改可提供登陸的 tty 數量,則修改 getty.target。
下面是操作 target unit 命令的格式:
systemctl [command] [unit.target]
command 有:
get-default:取得目前的 target。
set-default:設定後面接的 target 成為預設的操作模式。
isolate:切換到後面接的模式。
檢視和設定預設的 target
$ sudo systemctl get-default
筆者系統的預設 target 為 graphical.target,所以啟動時預設啟動圖形介面。下面我們把它設定為 multi-user.target:
$ sudo systemctl set-default multi-user.target
實際的執行過程是刪除之前的連結檔案,然後建立新的到 /lib/systemd/system/multi-user.target 的連結檔案。這樣下次開機時預設會進入純文字模式。
切換 target
我們還可以在不重新啟動的情況下切換不同的 target,比如從圖形介面切換到純文字的模式:
$ sudo systemctl isolate multi-user.target
在一般情況下,使用上述 isolate 的方式即可完成不同 target 的切換。不過為了方便起見,systemd 也提供了
幾個簡單的指令用來切換操作模式,大致如下所示:
$ sudo systemctl poweroff # 系統關機 $ sudo systemctl reboot # 重新開機 $ sudo systemctl suspend # 進入暫停模式 $ sudo systemctl hibernate # 進入休眠模式 $ sudo systemctl rescue # 強制進入救援模式 $ sudo systemctl emergency # 強制進入緊急救援模式
這裡簡單介紹一下暫停模式與休眠模式的區別
suspend:暫停模式會將系統的狀態儲存到記憶體中,然後關閉掉大部分的系統硬體,當然,並沒有實際關機。當用戶按下喚醒機器的按鈕,系統資料會從記憶體中回覆,然後重新驅動被大部分關閉的硬體,所以喚醒系統的速度比較快。
hibernate:休眠模式則是將系統狀態儲存到硬碟當中,儲存完畢後,將計算機關機。當用戶嘗試喚醒系統時,系統會開始正常執行,然後將儲存在硬碟中的系統狀態恢復回來。因為資料需要從硬碟讀取,因此喚醒的速度比較慢(如果你使用的是 SSD 磁碟,喚醒的速度也是非常快的)。
檢查 unit 之間的依賴性
很多服務之間是有依賴關係的,systemd 的一大亮點就是可以管理 unit 之間的依賴關係。我們可以通過下面的命令來檢視 unit 間的依賴關係:
systemctl list-dependencies [unit] [--reverse] 選項 --reverse 會反向追蹤是誰在使用這個 unit。
下面讓我們看看當前執行的 target 的依賴關係:
我們當前執行在 graphical.target 下,它由一個長長的依賴列表(上圖並未展示所有的專案),其中最重要的依賴專案為 multi-user.target。下面我們使用 --reverse 選項檢視 multi-user.target unit 被誰使用:
$ systemctl list-dependencies multi-user.target --reverse
從上面兩張圖上我們可以確定下面的關係:graphical.target 依賴 multi-user.target。
我們這裡只是通過 target unit 介紹瞭如何檢視 unit 之間的依賴關係,實際使用中更多的是檢查服務 unit 之間的依賴關係。
相關的目錄和檔案
在不同的發行版中與 systemd 相關的檔案路徑可能會不太一樣,強調一下,本文介紹的是 ubuntu 16.04 。
/lib/systemd/system/ 大多數 unit 的配置檔案都放在這個目錄下。
/run/systemd/system/ 系統執行過程中產生的指令碼,比如使用者相關的指令碼和會話相關的指令碼。
/etc/systemd/system/ 這個目錄中主要的檔案都是指向 /lib/systemd/system/ 目錄中的連結檔案。
注意,在我們自己建立 unit 配置檔案時,既可以把配置檔案放在 /lib/systemd/system/ 目錄下,也可以放在 /etc/systemd/system/ 目錄下。
/etc/default/ 這個目錄中放置很多服務預設的配置檔案。
/var/lib/ 一些會產生資料的服務都會將他的資料寫入到 /var/lib/ 目錄中,比如 docker 相關的資料檔案就放在這個目錄下。
/run/ 這個目錄放置了好多服務執行時的臨時資料,比如 lock file 以及 PID file 等等。
我們知道 systemd 裡管理了很多會用到本機 socket 的服務,所以系統中肯定會產生很多的 socket 檔案。那麼,這些 socke 檔案都存放在哪裡呢?我們可以使用 systemctl 進行檢視:
$ systemctl list-sockets
其實,絕大多數的 socket 檔案都存放在 /run 目錄及其子目錄中。
systemctl daemon-reload 子命令
daemon-reload 是一個很容易被誤用的子命令,主要是因為它名字中包含的 daemon 一詞很容易讓它和 reload 子命令混淆。
我們在前文簡略的介紹了 reload 子命令,它的作用是重新載入某個服務程式的配置檔案。這裡的程式指的是服務型別 unit 的配置中指定的程式,也就是我們常說的 daemon(提供某種服務的應用程式)。比如服務型別的 unit prometheus.service,提供服務的 daemon 程式在我的機器上是 /usr/local/share/prometheus/prometheus,所以 reload 子命令重新載入的是 prometheus 的配置檔案。
如果把 daemon-reload 子命令中的 daemon 理解為 systemd 程式,就可以把這個命令解釋為重新載入 systemd 程式的配置檔案。而所有的 unit 配置檔案都是作為 systemd 程式的配置檔案存在的。這樣得出的結論就是:
-
新新增 unit 配置檔案時需要執行 daemon-reload 子命令
-
有 unit 的配置檔案發生變化時也需要執行 daemon-reload 子命令
daemon-reload 命令會做很多的事情,其中之一是重新生成依賴樹(也就是 unit 之間的依賴關係),所以當你修改了 unit 配置檔案中的依賴關係後如果不執行 daemon-reload 命令是不會生效的。
總結
systemctl 提供了管理 systemd 和系統服務的眾多子命令。本文只是走馬觀花的把主要的子命令和一些常見的用法介紹了一下。對於這麼一個龐大的命令集和相信只有在使用中不斷的磨練才能夠真正的掌握它們。