第 10 章:認識系統服務 Daemons
systemd 使用的 unit 分類
- 平行處理所有服務,加速開機流程
- 一經要求就回應的 on-demand 啟動方式
- 服務相依性的自我檢查
- 依 daemon 功能分類
- 將多個 daemons 集合成為一個群組
- 向下相容舊有的 init 服務腳本
systemd 的設定檔放置目錄
systemd 將過去所謂的 daemon 執行腳本通通稱為一個服務單位 (unit),而每種服務單位依據功能來區分時,就分類為不同的類型 (type)。 基本的類型有包括系統服務、資料監聽與交換的插槽檔服務 (socket)、儲存系統狀態的快照類型、提供不同類似執行等級分類的操作環境 (target) 等等。 因為設定檔都放置在底下的目錄中
/usr/lib/systemd/system/
:每個服務最主要的啟動腳本設定,有點類似以前的 /etc/init.d 底下的檔案;/run/systemd/system/
:系統執行過程中所產生的服務腳本,這些腳本的優先序要比/usr/lib/systemd/system/
高!/etc/systemd/system/
:管理員依據主機系統的需求所建立的執行腳本,其實這個目錄有點像以前/etc/rc.d/rc5.d/Sxx
之類的功能!執行優先序又比/run/systemd/system/
高喔!
也就是說,到底系統開機會不會執行某些服務其實是看 /etc/systemd/system/
底下的設定,所以該目錄底下就是一大堆連結檔。而實際執行的 systemd 啟動腳本設定檔, 其實都是放置在 /usr/lib/systemd/system/
底下的喔!因此如果你想要修改 某個服務啟動的設定,應該要去 /usr/lib/systemd/system/
底下修改才對! /etc/systemd/system/
僅是連結到正確的執行腳本設定檔而已。所以想要看執行腳本設定,應該就得要到 /usr/lib/systemd/system/
底下去查閱才對!
systemd 的 unit 類型分類說明
systemd 的 unit 類型分類說明
ll /usr/lib/systemd/system/ | grep -E '(vsftpd|multi|cron)'
-rw-r--r--. 1 root root 284 7月 30 2014 crond.service
-rw-r--r--. 1 root root 567 3月 6 06:51 multipathd.service
-rw-r--r--. 1 root root 524 3月 6 13:48 multi-user.target
drwxr-xr-x. 2 root root 4096 5月 4 17:52 multi-user.target.wants
lrwxrwxrwx. 1 root root 17 5月 4 17:52 runlevel2.target -> multi-user.target
lrwxrwxrwx. 1 root root 17 5月 4 17:52 runlevel3.target -> multi-user.target
lrwxrwxrwx. 1 root root 17 5月 4 17:52 runlevel4.target -> multi-user.target
-rw-r--r--. 1 root root 171 6月 10 2014 vsftpd.service
-rw-r--r--. 1 root root 184 6月 10 2014 vsftpd@.service
-rw-r--r--. 1 root root 89 6月 10 2014 vsftpd.target
# 比較重要的是上頭提供的那三行特殊字體的部份!
常見的 systemd 的服務類型
副檔名 | 主要服務功能 |
---|---|
.service | 一般服務類型 (service unit):主要是系統服務,包括伺服器本身所需要的本機服務以及網路服務都是!比較經常被使用到的服務大多是這種類型! 所以,這也是最常見的類型了! |
.socket | 內部程序資料交換的插槽服務 (socket unit):主要是 IPC (Inter-process communication) 的傳輸訊息插槽檔 (socket file) 功能。 這種類型的服務通常在監控訊息傳遞的插槽檔,當有透過此插槽檔傳遞訊息來說要連結服務時,就依據當時的狀態將該用戶的要求傳送到對應的 daemon, 若 daemon 尚未啟動,則啟動該 daemon 後再傳送用戶的要求。 |
使用 socket 類型的服務一般是比較不會被用到的服務,因此在開機時通常會稍微延遲啟動的時間 (因為比較沒有這麼常用嘛!)。一般用於本機服務比較多,例如我們的圖形界面很多的軟體都是透過 socket 來進行本機程序資料交換的行為。 (這與早期的 xinetd 這個 super daemon 有部份的相似喔!) | |
.target | 執行環境類型 (target unit):其實是一群 unit 的集合,例如上面表格中談到的 multi-user.target 其實就是一堆服務的集合~也就是說, 選擇執行 multi-user.target 就是執行一堆其他 .service 或/及 .socket 之類的服務就是了! |
.mount.automount | 檔案系統掛載相關的服務 (automount unit / mount unit):例如來自網路的自動掛載、NFS 檔案系統掛載等與檔案系統相關性較高的程序管理。 |
.path | 偵測特定檔案或目錄類型 (path unit):某些服務需要偵測某些特定的目錄來提供佇列服務,例如最常見的列印服務,就是透過偵測列印佇列目錄來啟動列印功能! 這時就得要 .path 的服務類型支援了! |
.timer | 循環執行的服務 (timer unit):這個東西有點類似 anacrontab 喔!不過是由 systemd 主動提供的,比 anacrontab 更加有彈性! |
透過 systemctl 管理服務
基本上, systemd 這個啟動服務的機制,主要是透過一隻名為 systemctl 的指令來處理的!跟以前 systemV 需要 service / chkconfig / setup / init 等指令來協助不同, systemd 就是僅有 systemctl 這個指令來處理而已呦!
透過 systemctl 管理單一服務 (service unit) 的啟動/開機啟動與觀察狀態
透過 systemctl 管理單一服務
systemctl [command] [unit]
command 主要有:
start :立刻啟動後面接的 unit
stop :立刻關閉後面接的 unit
restart :立刻關閉後啟動後面接的 unit,亦即執行 stop 再 start 的意思
reload :不關閉後面接的 unit 的情況下,重新載入設定檔,讓設定生效
enable :設定下次開機時,後面接的 unit 會被啟動
disable :設定下次開機時,後面接的 unit 不會被啟動
status :目前後面接的這個 unit 的狀態,會列出有沒有正在執行、開機預設執行否、登錄等資訊等!
is-active :目前有沒有正在運作中
is-enabled:開機時有沒有預設要啟用這個 unit範例一:看看目前 atd 這個服務的狀態為何?
systemctl status atd.service
atd.service - Job spooling tools
Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled)
Active: active (running) since Mon 2015-08-10 19:17:09 CST; 5h 42min ago
Main PID: 1350 (atd)
CGroup: /system.slice/atd.service
└─1350 /usr/sbin/atd -f
Aug 10 19:17:09 study.centos.vbird systemd[1]: Started Job spooling tools.
# 重點在第二、三行喔~
# Loaded:這行在說明,開機的時候這個 unit 會不會啟動,enabled 為開機啟動,disabled 開機不會啟動
# Active:現在這個 unit 的狀態是正在執行 (running) 或沒有執行 (dead)
# 後面幾行則是說明這個 unit 程序的 PID 狀態以及最後一行顯示這個服務的登錄檔資訊!
# 登錄檔資訊格式為:『時間』 『訊息發送主機』 『哪一個服務的訊息』 『實際訊息內容』
# 所以上面的顯示訊息是:這個 atd 預設開機就啟動,而且現在正在運作的意思!範例二:正常關閉這個 atd 服務
systemctl stop atd.service
systemctl status atd.service
atd.service - Job spooling tools
Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled)
Active: inactive (dead) since Tue 2015-08-11 01:04:55 CST; 4s ago
Process: 1350 ExecStart=/usr/sbin/atd -f $OPTS (code=exited, status=0/SUCCESS)
Main PID: 1350 (code=exited, status=0/SUCCESS)
Aug 10 19:17:09 study.centos.vbird systemd[1]: Started Job spooling tools.
Aug 11 01:04:55 study.centos.vbird systemd[1]: Stopping Job spooling tools...
Aug 11 01:04:55 study.centos.vbird systemd[1]: Stopped Job spooling tools.
# 目前這個 unit 下次開機還是會啟動,但是現在是沒在運作的狀態中!同時,
# 最後兩行為新增加的登錄訊息,告訴我們目前的系統狀態喔!
回到 systemctl status atd.service 的第三行,不是有個 Active 的 daemon 現在狀態嗎?除了 running 跟 dead 之外, 有沒有其他的狀態呢?有的~基本上有幾個常見的狀態:
- active (running):正有一隻或多隻程序正在系統中執行的意思,舉例來說,正在執行中的 vsftpd 就是這種模式。
- active (exited):僅執行一次就正常結束的服務,目前並沒有任何程序在系統中執行。 舉例來說,開機或者是掛載時才會進行一次的 quotaon 功能,就是這種模式! quotaon 不須一直執行~只須執行一次之後,就交給檔案系統去自行處理囉!通常用 bash shell 寫的小型服務,大多是屬於這種類型 (無須常駐記憶體)。
- active (waiting):正在執行當中,不過還再等待其他的事件才能繼續處理。舉例來說,列印的佇列相關服務就是這種狀態! 雖然正在啟動中,不過,也需要真的有佇列進來 (列印工作) 這樣他才會繼續喚醒印表機服務來進行下一步列印的功能。
- inactive:這個服務目前沒有運作的意思。
既然 daemon 目前的狀態就有這麼多種了,那麼 daemon 的預設狀態有沒有可能除了 enable/disable 之外,還有其他的情況呢?當然有!
- enabled:這個 daemon 將在開機時被執行
- disabled:這個 daemon 在開機時不會被執行
- static:這個 daemon 不可以自己啟動 (enable 不可),不過可能會被其他的 enabled 的服務來喚醒 (相依屬性的服務)
- mask:這個 daemon 無論如何都無法被啟動!因為已經被強制註銷 (非刪除)。可透過 systemctl unmask 方式改回原本狀態
服務啟動/關閉與觀察的練習
問題:找到系統中名為 chronyd 的服務,觀察此服務的狀態,觀察完畢後,將此服務設定為:
- 開機不會啟動
- 現在狀況是關閉的情況!
回答:
# 1. 觀察一下狀態,確認是否為關閉/未啟動呢?
systemctl status chronyd.service
hronyd.service - NTP client/server
Loaded: loaded (/usr/lib/systemd/system/chronyd.service; enabled)
Active: active (running) since Mon 2015-08-10 19:17:07 CST; 24h ago
.....(底下省略).....
# 2. 由上面知道目前是啟動的,因此立刻將他關閉,同時開機不會啟動才行!
systemctl stop chronyd.service
systemctl disable chronyd.service
rm '/etc/systemd/system/multi-user.target.wants/chronyd.service'
# 看得很清楚~其實就是從 /etc/systemd/system 底下刪除一條連結檔案而已~
systemctl status chronyd.service
chronyd.service - NTP client/server
Loaded: loaded (/usr/lib/systemd/system/chronyd.service; disabled)
Active: inactive (dead)
# 如此則將 chronyd 這個服務完整的關閉了!
強迫服務註銷 (mask) 的練習
比較正規的作法是,要關閉 cups.service 時,連同其他兩個會喚醒 service 的 cups.socket 與 cups.path 通通關閉,那就沒事了! 比較不正規的作法是,那就強迫 cups.service 註銷吧!透過 mask 的方式來將這個服務註銷看看!
強迫服務註銷的練習
# 1. 保持剛剛的狀態,關閉 cups.service,啟動 cups.socket,然後註銷 cups.servcie
systemctl stop cups.service
systemctl mask cups.service
ln -s '/dev/null' '/etc/systemd/system/cups.service'
# 喔耶~其實這個 mask 註銷的動作,只是讓啟動的腳本變成空的裝置而已!
systemctl status cups.service
cups.service
Loaded: masked (/dev/null)
Active: inactive (dead) since Tue 2015-08-11 23:14:16 CST; 52s ago
systemctl start cups.service
Failed to issue method call: Unit cups.service is masked. # 再也無法喚醒!
上面的範例你可以仔細推敲一下~原來整個啟動的腳本設定檔被連結到 `/dev/null 這個空裝置~因此,無論如何你是再也無法啟動這個 cups.service 了! 透過這個 mask 功能,你就可以不必管其他相依服務可能會啟動到這個想要關閉的服務了!雖然是非正規,不過很有效! ^_^
那如何取消註銷呢?當然就是 unmask 即可啊!
systemctl unmask cups.service
rm '/etc/systemd/system/cups.service'
systemctl status cups.service
cups.service - CUPS Printing Service
Loaded: loaded (/usr/lib/systemd/system/cups.service; disabled)
Active: inactive (dead) since Tue 2015-08-11 23:14:16 CST; 4min 35s ago
# 好佳在有恢復正常!