【BASH】回顧與知識點梳理 三十三
- 三十三. 認識系統服務 (daemons)
- 33.1 什么是 daemon 與服務 (service)
- 早期 System V 的 init 管理行為中 daemon 的主要分類 (Optional)
- systemd 使用的 unit 分類
- systemd 的配置文件放置目錄
- systemd 的 unit 類型分類說明
- 33.2 透過 systemctl 管理服務
- 透過 systemctl 管理單一服務 (service unit) 的啟動/開機啟動與觀察狀態
- 服務啟動/關閉與觀察的練習
- 強迫服務注銷 (mask) 的練習
- 透過 systemctl 觀察系統上所有的服務
- 透過 systemctl 管理不同的操作環境 (target unit)
- 透過 systemctl 分析各服務之間的相依性
- 與 systemd 的 daemon 運作過程相關的目錄簡介
- 網絡服務與端口口對應簡介
- 關閉網絡服務
該系列目錄 --> 【BASH】回顧與知識點梳理(目錄)
三十三. 認識系統服務 (daemons)
在 Unix-Like 的系統中,你會常常聽到 daemon 這個字眼!那么什么是傳說中的 daemon 呢?這些 daemon 放在什么地方?他的功能是什么?該如何啟動這些 daemon ?又如何有效的將這些 daemon 管理妥當?此外,要如何視察這些daemon 開了多少個 ports ?又這些 ports 要如何關閉?還有還有,曉得你系統的這些 port 各代表的是什么服務嗎? 這些都是最基礎需要注意的呢!尤其是在架設網站之前,這里的觀念就顯的更重要了。
從 CentOS 7.x 這一版之后,傳統的 init 已經被舍棄,取而代之的是 systemd 這個家伙~這家伙跟之前的 init 有什么差異? 優缺點為何?如何管理不同種類的服務類型?以及如何取代原本的『執行等級』等等,很重要的改變喔!
33.1 什么是 daemon 與服務 (service)
我們曾經談過『服務』這東西! 當時的說明是『常駐在記體體中的程序,且可以提供一些系統或網絡功能,那就是服務
』。而服務一般的英文說法是『service
』。
簡單的說,系統為了某些功能必須要提供一些服務 (不論是系統本身還是網絡方面),這個服務就稱為 service
。 但是 service 的提供總是需要程序的運作吧!否則如何執行呢?所以達成這個 service 的程序我們就稱呼他為 daemon
啰! 舉例來說,達成循環型例行性工作排程服務 (service) 的程序為 crond 這個 daemon 啦!這樣說比較容易理解了吧!
daemon 既然是一只程序執行后的程序,那么 daemon 所處的那個原本的程序通常是如何命名的呢 (daemon 程序的命名方式)。 每一個服務的開發者,當初在開發他們的服務時,都有特別的故事啦!不過,無論如何,這些服務的名稱被建立之后,被掛上 Linux 使用時,通常在服務的名稱之后會加上一個 d ,例如例行性命令的建立的 at, 與 cron 這兩個服務, 他的程序文件名會被取為 atd 與 crond,這個 d 代表的就是daemon 的意思。
早期 System V 的 init 管理行為中 daemon 的主要分類 (Optional)
那個很純種的 Unix 版本~ 在那種年代底下,我們啟動系統服務的管理方式被稱為 SysV 的 init 腳本程序的處理方式!亦即系統核心第一支呼叫的程序是 init , 然后 init 去喚起所有的系統所需要的服務,不論是本地服務還是網絡服務就是了。
基本上 init 的管理機制有幾個特色如下:
-
服務的啟動、關閉與觀察等方式:
所有的服務啟動腳本通通放置于 /etc/init.d/ 底下,基本上都是使用 bash shell script 所寫成的腳本程序,需要啟動、關閉、重新啟動、觀察狀態時, 可以透過如下的方式來處理:- 啟動:/etc/init.d/daemon start
- 關閉:/etc/init.d/daemon stop
- 重新啟動:/etc/init.d/daemon restart
- 狀態觀察:/etc/init.d/daemon status
-
服務啟動的分類:
init 服務的分類中,依據服務是獨立啟動或被一只總管程序管理而分為兩大類:- 獨立啟動模式 (stand alone):服務獨立啟動,該服務直接常駐于內存中,提供本機或用戶的服務行為,反應速度快。
- 總管程序 (super daemon):由特殊的 xinetd 或 inetd 這兩個總管程序提供 socket 對應或 port 對應的管理。當沒有用戶要求某 socket 或 port 時, 所需要的服務是不會被啟動的。若有用戶要求時,xinetd 總管才會去喚醒相對應的服務程序。當該要求結束時,這個服務也會被結束掉~ 因為透過xinetd 所總管,因此這個家伙就被稱為 super daemon。好處是可以透過 super daemon 來進行服務的時程、聯機需求等的控制,缺點是喚醒服務需要一點時間的延遲。
-
服務的相依性問題:
服務是可能會有相依性的~例如,你要啟動網絡服務,但是系統沒有網絡, 那怎么可能可以喚醒網絡服務呢?如果你需要聯機到外部取得認證服務器的聯機,但該聯機需要另一個 A 服務的需求,問題是,A 服務沒有啟動, 因此,你的認證服務就不可能會成功啟動的!這就是所謂的服務相依性問題。init 在管理員自己手動處理這些服務時,是沒有辦法協助相依服務的喚醒的! -
執行等級的分類:
上面說到 init 是開機后核心主動呼叫的, 然后 init 可以根據用戶自定義的執行等級 (runlevel) 來喚醒不同的服務,以進入不同的操作界面。基本上 Linux 提供 7 個執行等級,分別是 0, 1, 2…6 , 比較重要的是- 1)單人維護模式
- 3)純文本模式
- 5)文字加圖形界面
而各個執行等級的啟動腳本是透過
/etc/rc.d/rc[0-6]/SXXdaemon
連結到 /etc/init.d/daemon , 連結檔名 (SXXdaemon) 的功能為: S 為啟動該服務,XX 是數字,為啟動的順序。由于有 SXX 的設定,因此在開機時可以『依序執行
』所有需要的服務,同時也能解決相依服務的問題。這點與管理員自己手動處理不太一樣就是了。 -
制定執行等級默認要啟動的服務:
若要建立如上提到的 SXXdaemon 的話,不需要管理員手動建立連結檔, 透過如下的指令可以來處理默認啟動、預設不啟動、觀察預設啟動否的行為:- 預設要啟動: chkconfig daemon on
- 預設不啟動: chkconfig daemon off
- 觀察預設為啟動否: chkconfig --list daemon
-
執行等級的切換行為:
當你要從純文本界面 (runlevel 3) 切換到圖形界面 (runlevel 5), 不需要手動啟動、關閉該執行等級的相關服務,只要『 init 5 』即可切換,init 這小子會主動去分析 /etc/rc.d/rc[35].d/ 這兩個目錄內的腳本, 然后啟動轉換 runlevel 中需要的服務~就完成整體的 runlevel 切換。
基本上 init 主要的功能都寫在上頭了,重要的指令包括 daemon 本身自己的腳本(/etc/init.d/daemon) 、xinetd 這個特殊的總管程序 (super daemon)、設定預設開機啟動的 chkconfig,以及會影響到執行等級的 init N 等。雖然 CentOS 7 已經不使用 init 來管理服務了,不過因為考慮到某些腳本沒有辦法直接塞入 systemd 的處理,因此這些腳本還是被保留下來, 所以,我們在這里還是稍微介紹了一下。
systemd 使用的 unit 分類
從 CentOS 7.x 以后,Red Hat 系列的 distribution 放棄沿用多年的 System V 開機啟動服務的流程,就是前一小節提到的 init 啟動腳本的方法, 改用 systemd 這個啟動服務管理機制~那么 systemd 有什么好處呢?
- 平行處理所有服務,加速開機流程:
舊的 init 啟動腳本是『一項一項任務依序啟動
』的模式,因此不相依的服務也是得要一個一個的等待。但目前我們的硬件主機系統與操作系統幾乎都支持多核心架構了, 沒道理未相依的服務不能同時啟動啊!systemd 就是可以讓所有的服務同時啟動,因此你會發現到,系統啟動的速度變快了! - 一經要求就響應的 on-demand 啟動方式:
systemd 全部就是僅有一只 systemd 服務搭配 systemctl 指令來處理,無須其他額外的指令來支持。不像systemV 還要 init, chkconfig, service… 等等指令。 此外, systemd 由于常駐內存,因此任何要求(on-demand) 都可以立即處理后續的 daemon 啟動的任務。 - 服務相依性的自我檢查:
由于 systemd 可以自定義服務相依性的檢查,因此如果 B 服務是架構在 A 服務上面啟動的,那當你在沒有啟動 A 服務的情況下僅手動啟動 B 服務時, systemd 會自動幫你啟動 A 服務喔!這樣就可以免去管理員得要一項一項服務去分析的麻煩~(如果讀者不是新手,應該會有印象,當你沒有啟動網絡, 但卻啟動NIS/NFS 時,那個開機時的 timeout 甚至可達到 10~30 分鐘…) - 依 daemon 功能分類:
systemd 旗下管理的服務非常多,包山包海啦~為了厘清所有服務的功能,因此,首先 systemd 先定義所有的服務為一個服務單位 (unit),并將該 unit 歸類到不同的服務類型 (type) 去。 舊的 init 僅分為 stand alone 與 super daemon 實在不夠看,systemd 將服務單位 (unit) 區分為 service, socket, target, path, snapshot, timer 等多種不同的類型(type), 方便管理員的分類與記憶。 - 將多個 daemons 集合成為一個群組:
如同 systemV 的 init 里頭有個 runlevel 的特色,systemd 亦將許多的功能集合成為一個所謂的 target 項目,這個項目主要在設計操作環境的建置, 所以是集合了許多的 daemons,亦即是執行某個 target 就是執行好多個 daemon 的意思! - 向下兼容舊有的 init 服務腳本:
基本上, systemd 是可以兼容于 init 的啟動腳本的,因此,舊的 init 啟動腳本也能夠透過 systemd 來管理,只是更進階的 systemd 功能就沒有辦法支持就是了。
雖然如此,不過 systemd 也是有些地方無法完全取代 init 的!包括:
- 在 runlevel 的對應上,大概僅有 runlevel 1, 3, 5 有對應到 systemd 的某些 target 類型而已,沒有全部對應;
- 全部的 systemd 都用 systemctl 這個管理程序管理,而 systemctl 支持的語法有限制,不像/etc/init.d/daemon 就是純腳本可以自定義參數,systemctl 不可自定義參數。
- 如果某個服務啟動是管理員自己手動執行啟動,而不是使用 systemctl 去啟動的 (例如你自己手動輸入crond 以啟動 crond 服務),那么 systemd 將無法偵測到該服務,而無法進一步管理。
- systemd 啟動過程中,無法與管理員透過 standard input 傳入訊息!因此,自行撰寫 systemd 的啟動設定時,務必要取消互動機制~(連透過啟動時傳進的標準輸入訊息也要避免!)
不過,光是同步啟動服務腳本這個功能就可以節省你很多開機的時間~同時 systemd 還有很多特殊的服務類型 (type) 可以提供更多有趣的功能!確實值得學一學~ 而且 CentOS 7 已經用了 systemd 了!想不學也不行啊~哈哈哈!好~既然要學,首先就得要針對 systemd 管理的 unit 來了解一下。
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 類型分類說明
那 /usr/lib/systemd/system/ 以下的數據如何區分上述所謂的不同的類型 (type) 呢?很簡單!看擴展名!舉例來說,我們來瞧瞧上一章談到的 vsftpd 這個范例的啟動腳本設定, 還有 crond 與純文本模式的 multi-user 設定:
[root@study ~]# 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
# 比較重要的是上頭提供的那三行特殊字體的部份!
所以我們可以知道 vsftpd 與 crond 其實算是系統服務 (service),而 multi-user 要算是執行環境相關的類型 (target type)。根據這些擴展名的類型, 我們大概可以找到幾種比較常見的 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 更加有彈性! |
其中又以 .service 的系統服務類型最常見了!因為我們一堆網絡服務都是透過這種類型來設計的啊!接下來,讓我們來談談如何管理這些服務的啟動與關閉。
33.2 透過 systemctl 管理服務
基本上, systemd 這個啟動服務的機制,主要是透過一只名為 systemctl 的指令來處理的!跟以前systemV 需要 service / chkconfig / setup / init 等指令來協助不同, systemd 就是僅有 systemctl 這個指令來處理而已呦!所以全部的行為都得要使用 systemctl 的意思啦!有沒有很難?其實習慣了之后,鳥哥是覺得 systemctl 還挺好用的!^_^
透過 systemctl 管理單一服務 (service unit) 的啟動/開機啟動與觀察狀態
一般來說,服務的啟動有兩個階段,一個是『開機的時候設定要不要啟動這個服務
』, 以及『你現在要不要啟動這個服務
』,這兩者之間
有很大的差異喔!舉個例子來說,假如我們現在要『立刻取消 atd 這個服務』時,正規的方法 (不要用 kill) 要怎么處理?
[root@study ~]# systemctl [command] [unit]
command 主要有:start :立刻啟動后面接的 unitstop :立刻關閉后面接的 unitrestart :立刻關閉后啟動后面接的 unit,亦即執行 stop 再 start 的意思reload :不關閉后面接的 unit 的情況下,重載配置文件,讓設定生效enable :設定下次開機時,后面接的 unit 會被啟動disable :設定下次開機時,后面接的 unit 不會被啟動status :目前后面接的這個 unit 的狀態,會列出有沒有正在執行、開機預設執行否、登錄等信息等!is-active :目前有沒有正在運作中is-enable :開機時有沒有預設要啟用這個 unit
# 范例一:看看目前 atd 這個服務的狀態為何?
[root@study ~]# systemctl status atd.service
atd.service - Job spooling toolsLoaded: loaded (/usr/lib/systemd/system/atd.service; enabled) #2Active: active (running) since Mon 2015-08-10 19:17:09 CST; 5h 42min ago #3
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 預設開機就啟動,而且現在正在運作的意思!
好!再回到 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)開機不會啟動 2)現在狀況是關閉的情況!
回答:我們直接使用指令的方式來查詢與設定看看:
看得很清楚~其實就是從 /etc/systemd/system 底下刪除一條連結文件而已~[root@node-135 vsftpd]# systemctl disable chronyd Removed symlink /etc/systemd/system/multi-user.target.wants/chronyd.service. [root@node-135 vsftpd]# systemctl stop chronyd
- 因為我根本沒有打印機安裝在服務器上,目前也沒有網絡打印機,因此我想要將 cups 服務整個關閉,是否可以呢?
回答:同樣的,眼見為憑,我們就動手作看看:# 1. 先看看 cups 的服務是開還是關? [root@study ~]# systemctl status cups.service cups.service - CUPS Printing ServiceLoaded: loaded (/usr/lib/systemd/system/cups.service; enabled)Active: inactive (dead) since Tue 2015-08-11 19:19:20 CST; 3h 29min ago # 有趣得很!竟然是 enable 但是卻是 inactive 耶!相當特別!# 2. 那就直接關閉,同時確認沒有啟動喔! [root@study ~]# systemctl stop cups.service [root@study ~]# systemctl disable cups.service rm '/etc/systemd/system/multi-user.target.wants/cups.path' rm '/etc/systemd/system/sockets.target.wants/cups.socket' rm '/etc/systemd/system/printer.target.wants/cups.service' # 也是非常特別!竟然一口氣取消掉三個連結檔!也就是說,這三個文件可能是有相依性的問題喔! [root@study ~]# netstat -tlunp | grep cups # 現在應該不會出現任何數據!因為根本沒有 cups 的任務在執行當中~所以不會有 port 產生# 3. 嘗試啟動 cups.socket 監聽客戶端的需求喔! [root@study ~]# systemctl start cups.socket [root@study ~]# systemctl status cups.service cups.socket cups.path cups.service - CUPS Printing ServiceLoaded: loaded (/usr/lib/systemd/system/cups.service; disabled)Active: inactive (dead) since Tue 2015-08-11 22:57:50 CST; 3min 41s ago cups.socket - CUPS Printing Service SocketsLoaded: loaded (/usr/lib/systemd/system/cups.socket; disabled)Active: active (listening) since Tue 2015-08-11 22:56:14 CST; 5min ago cups.path - CUPS Printer Service SpoolLoaded: loaded (/usr/lib/systemd/system/cups.path; disabled)Active: inactive (dead) # 確定僅有 cups.socket 在啟動,其他的并沒有啟動的狀態!# 4. 嘗試使用 lp 這個指令來打印看看? [root@study ~]# echo "testing" | lp lp: Error - no default destination available. # 實際上就是沒有打印機!所以有錯誤也沒關系! [root@study ~]# systemctl status cups.service cups.service - CUPS Printing ServiceLoaded: loaded (/usr/lib/systemd/system/cups.service; disabled)Active: active (running) since Tue 2015-08-11 23:03:18 CST; 34s ago [root@study ~]# netstat -tlunp | grep cups tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 25881/cupsd tcp6 0 0 ::1:631 :::* LISTEN 25881/cupsd # 見鬼!竟然 cups 自動被啟動了!明明我們都沒有驅動他啊!怎么回事啊?
上面這個范例的練習在讓您了解一下,很多服務彼此之間是有相依性的!cups 是一種打印服務,這個打印服務會啟用 port 631 來提供網絡打印機的打印功能。 但是其實我們無須一直啟動 631 埠口吧?因此,多了一個名為 cups.socket 的服務,這個服務可以在『用戶有需要打印時,才會主動喚醒cups.service 』的意思! 因此,如果你僅是 disable/stop cups.service 而忘記了其他兩個服務的話,那么當有用戶向其他兩個 cups.path, cups.socket 提出要求時, cups.service 就會被喚醒!所以,你關掉也沒用!
強迫服務注銷 (mask) 的練習
比較正規的作法是,要關閉 cups.service 時,連同其他兩個會喚醒 service 的 cups.socket 與cups.path 通通關閉,那就沒事了! 比較不正規的作法是,那就強迫 cups.service 注銷吧!透過 mask 的方式來將這個服務注銷看看!
# 1. 保持剛剛的狀態,關閉 cups.service,啟動 cups.socket,然后注銷 cups.servcie
[root@study ~]# systemctl stop cups.service
[root@study ~]# systemctl mask cups.service
ln -s '/dev/null' '/etc/systemd/system/cups.service'
# 喔耶~其實這個 mask 注銷的動作,只是讓啟動的腳本變成空的裝置而已!
[root@study ~]# systemctl status cups.service
cups.serviceLoaded: masked (/dev/null)Active: inactive (dead) since Tue 2015-08-11 23:14:16 CST; 52s ago
[root@study ~]# systemctl start cups.service
Failed to issue method call: Unit cups.service is masked. # 再也無法喚醒!
上面的范例你可以仔細推敲一下~原來整個啟動的腳本配置文件被連結到 /dev/null 這個空裝置~因此,無論如何你是再也無法啟動這個 cups.service 了! 透過這個 mask 功能,你就可以不必管其他相依服務可能會啟動到這個想要關閉的服務了!雖然是非正規,不過很有效! ^_^
那如何取消注銷呢?當然就是 unmask 即可啊
[root@study ~]# systemctl unmask cups.service
rm '/etc/systemd/system/cups.service'
[root@study ~]# systemctl status cups.service
cups.service - CUPS Printing ServiceLoaded: loaded (/usr/lib/systemd/system/cups.service; disabled)Active: inactive (dead) since Tue 2015-08-11 23:14:16 CST; 4min 35s ago
# 好佳在有恢復正常!
透過 systemctl 觀察系統上所有的服務
系統上面有多少的服務存在呢?這個時候就得要透過 list-units 及 list-unit-files 來觀察了! 細部的用法如下:
[root@study ~]# systemctl [command] [--type=TYPE] [--all]
command:list-units :依據 unit 列出目前有啟動的 unit。若加上 --all 才會列出沒啟動的。list-unit-files :依據 /usr/lib/systemd/system/ 內的文件,將所有文件列表說明。
--type=TYPE:就是之前提到的 unit type,主要有 service, socket, target 等
# 范例一:列出系統上面有啟動的 unit
[root@study ~]# systemctl
UNIT LOAD ACTIVE SUB DESCRIPTION
proc-sys-fs-binfmt_mis... loaded active waiting Arbitrary Executable File Formats File System
sys-devices-pc...:0:1:... loaded active plugged QEMU_HARDDISK
sys-devices-pc...0:1-0... loaded active plugged QEMU_HARDDISK
sys-devices-pc...0:0-1... loaded active plugged QEMU_DVD-ROM
.....(中間省略).....
vsftpd.service loaded active running Vsftpd ftp daemon
.....(中間省略).....
cups.socket loaded failed failed CUPS Printing Service Sockets
.....(中間省略).....
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
141 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
# 列出的項目中,主要的意義是:
# UNIT :項目的名稱,包括各個 unit 的類別 (看擴展名)
# LOAD :開機時是否會被加載,默認 systemctl 顯示的是有加載的項目而已喔!
# ACTIVE :目前的狀態,須與后續的 SUB 搭配!就是我們用 systemctl status 觀察時,active 的項目!
# DESCRIPTION :詳細描述啰
# cups 比較有趣,因為剛剛被我們玩過,所以 ACTIVE 竟然是 failed 的喔!被玩死了! ^_^
# 另外,systemctl 都不加參數,其實預設就是 list-units 的意思!# 范例二:列出所有已經安裝的 unit 有哪些?
[root@study ~]# systemctl list-unit-files
UNIT FILE STATE
proc-sys-fs-binfmt_misc.automount static
dev-hugepages.mount static
dev-mqueue.mount static
proc-fs-nfsd.mount static
.....(中間省略).....
systemd-tmpfiles-clean.timer static
336 unit files listed.
使用 systemctl list-unit-files
會將系統上所有的服務通通列出來~而不像 list-units 僅以 unit 分類作大致的說明。 至于 STATE 狀態就是前兩個小節談到的開機是否會加載的那個狀態項目啰!主要有enabled / disabled / mask / static 等等。
假設我不想要知道這么多的 unit 項目,我只想要知道 service 這種類別的 daemon 而已,而且不論是否已經啟動,通通要列出來! 那該如何是好?
[root@study ~]# systemctl list-units --type=service --all
# 只剩下 *.service 的項目才會出現喔!
# 范例一:查詢系統上是否有以 cpu 為名的服務?
[root@study ~]# systemctl list-units --type=service --all | grep cpu
cpupower.service loaded inactive dead Configure CPU power related settings
# 確實有喔!可以改變 CPU 電源管理機制的服務哩!
透過 systemctl 管理不同的操作環境 (target unit)
透過上個小節我們知道系統上所有的 systemd 的 unit 觀察的方式,那么可否列出跟操作界面比較有關的 target 項目呢? 很簡單啊!就這樣搞一下:
[root@node-135 vsftpd]# systemctl list-units --type=target --allUNIT LOAD ACTIVE SUB DESCRIPTIONbasic.target loaded active active Basic Systemcryptsetup.target loaded active active Local Encrypted Volumesemergency.target loaded inactive dead Emergency Modefinal.target loaded inactive dead Final Stepgetty-pre.target loaded inactive dead Login Prompts (Pre)getty.target loaded active active Login Promptsgraphical.target loaded inactive dead Graphical Interfaceinitrd-fs.target loaded inactive dead Initrd File Systemsinitrd-root-fs.target loaded inactive dead Initrd Root File Systeminitrd-switch-root.target loaded inactive dead Switch Rootinitrd.target loaded inactive dead Initrd Default Targetlocal-fs-pre.target loaded active active Local File Systems (Pre)local-fs.target loaded active active Local File Systemsmulti-user.target loaded active active Multi-User Systemnetwork-online.target loaded active active Network is Onlinenetwork-pre.target loaded inactive dead Network (Pre)network.target loaded active active Networknss-user-lookup.target loaded inactive dead User and Group Name Lookupspaths.target loaded active active Pathsremote-fs-pre.target loaded inactive dead Remote File Systems (Pre)remote-fs.target loaded active active Remote File Systemsrescue.target loaded inactive dead Rescue Modeshutdown.target loaded inactive dead Shutdownslices.target loaded active active Slicessockets.target loaded active active Socketssound.target loaded active active Sound Cardswap.target loaded active active Swapsysinit.target loaded active active System Initialization
● syslog.target not-found inactive dead syslog.targettime-sync.target loaded inactive dead System Time Synchronizedtimers.target loaded active active Timersumount.target loaded inactive dead Unmount All FilesystemsLOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.32 loaded units listed.
To show all installed unit files use 'systemctl list-unit-files'.
喔!在我們的 CentOS 7.9 的預設情況下,就有 32 個 target unit 耶!而跟操作界面相關性比較高的target 主要有底下幾個:
- graphical.target:就是文字加上圖形界面,這個項目已經包含了底下的 multi-user.target 項目!
- multi-user.target:純文本模式!
- rescue.target:在無法使用 root 登入的情況下,systemd 在開機時會多加一個額外的暫時系統,與你原本的系統無關。這時你可以取得 root 的權限來維護你的系統。但是這是額外系統,因此可能需要動到 chroot 的方式來取得你原有的系統喔!再后續的章節我們再來談!
- emergency.target:緊急處理系統的錯誤,還是需要使用 root 登入的情況,在無法使用 rescue.target 時,可以嘗試使用這種模式!
- shutdown.target:就是關機的流程。
- getty.target:可以設定你需要幾個 tty 之類的,如果想要降低 tty 的項目,可以修改這個東西的配置文件!
正常的模式是 multi-user.target 以及 graphical.target 兩個,救援方面的模式主要是 rescue.target 以及更嚴重的 emergency.target。 如果要修改可提供登入的 tty 數量,則修改 getty.target 項目。基本上,我們最常使用的當然就是 multi-user 以及 graphical 啰! 那么我如何知道目前的模式是哪一種?又得要如何修改呢?底下來玩一玩吧!
[root@study ~]# systemctl [command] [unit.target]
選項與參數:
command:get-default :取得目前的 targetset-default :設定后面接的 target 成為默認的操作模式isolate :切換到后面接的模式
# 范例一:我們的測試機器默認是圖形界面,先觀察是否真為圖形模式,再將默認模式轉為文字界面
[root@study ~]# systemctl get-default
graphical.target # 果然是圖形界面喔!
[root@study ~]# systemctl set-default multi-user.target
[root@study ~]# systemctl get-default
multi-user.target# 范例二:在不重新啟動的情況下,將目前的操作環境改為純文本模式,關掉圖形界面
[root@study ~]# systemctl isolate multi-user.target# 范例三:若需要重新取得圖形界面呢?
[root@study ~]# systemctl isolate graphical.target
在正常的切換情況下,使用上述 isolate 的方式即可。不過為了方便起見, systemd 也提供了數個簡單的指令給我們切換操作模式之用喔! 大致上如下所示:
[root@study ~]# systemctl poweroff 系統關機
[root@study ~]# systemctl reboot 重新啟動
[root@study ~]# systemctl suspend 進入暫停模式
[root@study ~]# systemctl hibernate 進入休眠模式
[root@study ~]# systemctl rescue 強制進入救援模式
[root@study ~]# systemctl emergency 強制進入緊急救援模式
關機、重新啟動、救援與緊急模式這沒啥問題,那么什么是暫停與休眠模式呢?
- suspend:暫停模式會將系統的狀態數據保存到內存中,然后關閉掉大部分的系統硬件,當然,并沒有實際關機喔! 當用戶按下喚醒機器的按鈕,系統數據會重內存中回復,然后重新驅動被大部分關閉的硬件,就開始正常運作!喚醒的速度較快。
- hibernate:休眠模式則是將系統狀態保存到硬盤當中,保存完畢后,將計算機關機。當用戶嘗試喚醒系統時,系統會開始正常運作, 然后將保存在硬盤中的系統狀態恢復回來。因為數據是由硬盤讀出,因此喚醒的效能與你的硬盤速度有關。
透過 systemctl 分析各服務之間的相依性
我們在本章一開始談到 systemd 的時候就有談到相依性的問題克服,那么,如何追蹤某一個 unit 的相依性呢? 舉例來說好了,我們怎么知道 graphical.target 會用到 multi-user.target 呢?那graphical.target 底下還有哪些東西呢? 底下我們就來談一談:
[root@study ~]# systemctl list-dependencies [unit] [--reverse]
選項與參數:
--reverse :反向追蹤誰使用這個 unit 的意思!
# 范例一:列出目前的 target 環境下,用到什么特別的 unit
[root@study ~]# systemctl get-default
multi-user.target
[root@study ~]# systemctl list-dependencies
default.target
├─abrt-ccpp.service
├─abrt-oops.service
├─vsftpd.service
├─basic.target
│ ├─alsa-restore.service
│ ├─alsa-state.service
.....(中間省略).....
│ ├─sockets.target
│ │ ├─avahi-daemon.socket
│ │ ├─dbus.socket
.....(中間省略).....
│ ├─sysinit.target
│ │ ├─dev-hugepages.mount
│ │ ├─dev-mqueue.mount
.....(中間省略).....
│ └─timers.target
│ └─systemd-tmpfiles-clean.timer
├─getty.target
│ └─getty@tty1.service
└─remote-fs.target
根據線條聯機的流程,我們也能夠知道, multi-user.target 其實還會用到 basic.target + getty.target + remote-fs.target 三大項目, 而
basic.target 又用到了 sockets.target + sysinit.target + timers.target… 等一堆~所以啰,從這邊就能夠清楚的查詢到每種 target 模式底下還有的相依模式。 那么如果要查出誰會用到 multi-user.target 呢?就這么作!
[root@study ~]# systemctl list-dependencies --reverse
default.target
└─graphical.target
reverse 本來就是反向的意思,所以加上這個選項,代表『誰還會用到我的服務
』的意思~所以看得出來, multi-user.target 主要是被 graphical.target 所使用喔! 好~那再來,graphical.target 又使用了多少的服務呢?可以這樣看:
[root@study ~]# systemctl list-dependencies graphical.target
graphical.target
├─accounts-daemon.service
├─gdm.service
├─network.service
├─rtkit-daemon.service
├─systemd-update-utmp-runlevel.service
└─multi-user.target├─abrt-ccpp.service├─abrt-oops.service
.....(底下省略).....
所以可以看得出來,graphical.target 就是在 multi-user.target 底下再加上 accounts-daemon, gdm, network, rtkit-deamon, systemd-update-utmp-runlevel 等服務而已! 這樣會看了嗎?了解 daemon 之間的相關性也是很重要的喔!出問題時,可以找到正確的服務相依流程!
與 systemd 的 daemon 運作過程相關的目錄簡介
我們在前幾小節曾經談過比較重要的 systemd 啟動腳本配置文件在 /usr/lib/systemd/system/, /etc/systemd/system/ 目錄下,那還有哪些目錄跟系統的 daemon 運作有關呢? 基本上是這樣的:
- /usr/lib/systemd/system/:
使用 CentOS 官方提供的軟件安裝后,默認的啟動腳本配置文件都放在這里,這里的數據盡量不要修改~要修改時,請到 /etc/systemd/system 底下修改較佳! - /run/systemd/system/:
系統執行過程中所產生的服務腳本,這些腳本的優先序要比 /usr/lib/systemd/system/ 高! - /etc/systemd/system/:
管理員依據主機系統的需求所建立的執行腳本,其實這個目錄有點像以前 /etc/rc.d/rc5.d/Sxx 之類的功能!執行優先序又比 /run/systemd/system/ 高喔! - /etc/sysconfig/*:
幾乎所有的服務都會將初始化的一些選項設定寫入到這個目錄下,舉例來說,mandb 所要更新的 man page 索引中,需要加入的參數就寫入到此目錄下的 man-db 當中喔!而網絡的設定則寫在/etc/sysconfig/network-scripts/ 這個目錄內。所以,這個目錄內的文件也是挺重要的; - /var/lib/:
一些會產生數據的服務都會將他的數據寫入到 /var/lib/ 目錄中。舉例來說,數據庫管理系統 Mariadb 的數據庫默認就是寫入 /var/lib/mysql/ 這個目錄下啦! - /run/:
放置了好多 daemon 的暫存檔,包括 lock file 以及 PID file 等等。
我們知道 systemd 里頭有很多的本機會用到的 socket 服務,里頭可能會產生很多的 socket file ~那你怎么知道這些 socket file 放置在哪里呢? 很簡單!還是透過 systemctl 來管理!
[root@node-135 vsftpd]# systemctl list-sockets
LISTEN UNIT ACTIVATES
/dev/log systemd-journald.socket systemd-journald.service
/run/dbus/system_bus_socket dbus.socket dbus.service
/run/dmeventd-client dm-event.socket dm-event.service
/run/dmeventd-server dm-event.socket dm-event.service
/run/lvm/lvmetad.socket lvm2-lvmetad.socket lvm2-lvmetad.service
/run/lvm/lvmpolld.socket lvm2-lvmpolld.socket lvm2-lvmpolld.service
/run/systemd/initctl/fifo systemd-initctl.socket systemd-initctl.service
/run/systemd/journal/socket systemd-journald.socket systemd-journald.service
/run/systemd/journal/stdout systemd-journald.socket systemd-journald.service
/run/systemd/shutdownd systemd-shutdownd.socket systemd-shutdownd.service
/run/udev/control systemd-udevd-control.socket systemd-udevd.service
kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service12 sockets listed.
Pass --all to see loaded but inactive sockets, too.
這樣很清楚的就能夠知道正在監聽本地服務需求的 socket file 所在的文件名位置啰!
網絡服務與端口口對應簡介
系統所有的功能都是某些程序所提供的,而程序則是透過觸發程序而產生的。同樣的,系統提供的網絡服務當然也是這樣的! 只是由于網絡牽涉到 TCP/IP 的概念,所以顯的比較復雜一些就是了。
當客戶端聯機過來我們的主機時, 我們主機是如何分辨不同的服務要求呢?那就是透過埠號 (端口號,port number) 啦!系統上面有沒有什么設定可以讓服務與埠號對應在一起呢?那就是 /etc/services 啦!
[root@study ~]# cat /etc/services
....(前面省略)....
ftp 21/tcp
ftp 21/udp fsp fspd
ssh 22/tcp # The Secure Shell (SSH) Protocol
ssh 22/udp # The Secure Shell (SSH) Protocol
....(中間省略)....
http 80/tcp www www-http # WorldWideWeb HTTP
http 80/udp www www-http # HyperText Transfer Protocol
....(底下省略)....
# 這個文件的內容是以底下的方式來編排的:
# <daemon name> <port/封包協議> <該服務的說明>
請特別注意!雖然有的時候你可以藉由修改 /etc/services 來更改一個服務的埠號,不過并不建議如此做, 因為很有可能會造成一些協議的錯誤情況!這里特此說明一番呦!(除非你要架設一個地下網站,否則的話,使用 /etc/services 原先的設定就好啦!)
關閉網絡服務
除了本地服務之外,其實你一定要觀察的,反而是網絡服務喔!雖然網絡服務默認有 SELinux 管理,不過,在鳥哥的立場上, 我還是建議非必要的網絡服務就關閉他!那么什么是網絡服務呢?基本上,會產生一個網絡監聽端口口 (port) 的程序,你就可以稱他是個網絡服務了! 那么如何觀察網絡端口口?就這樣追蹤啊!
[root@study ~]# netstat -tlunp
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1340/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 2387/master
tcp6 0 0 :::555 :::* LISTEN 29113/vsftpd
tcp6 0 0 :::22 :::* LISTEN 1340/sshd
tcp6 0 0 ::1:25 :::* LISTEN 2387/master
udp 0 0 0.0.0.0:5353 0.0.0.0:* 750/avahi-daemon: r
udp 0 0 0.0.0.0:36540 0.0.0.0:* 750/avahi-daemon: r
如上表所示,我們的系統上至少開了 22, 25, 555, 5353, 36540 這幾個埠口~而其中 5353, 36540 是由avahi-daemon 這個東西所啟動的!接下來我們使用 systemctl 去觀察一下,到底有沒有 avahi-daemon 為開頭的服務呢?
[root@study ~]# systemctl list-units --all | grep avahi-daemon
avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack
avahi-daemon.socket loaded active running Avahi mDNS/DNS-SD Stack Activation Socket
透過追查,知道這個 avahi-daemon 的目的是在局域網絡進行類似網芳的搜尋,因此這個服務可以協助你在區網內隨時了解即插即用的裝置! 包括筆記本電腦等,只要連上你的區網,你就能夠知道誰進來了。問題是,你可能不要這個協議啊!所以,那就關閉他吧!
[root@study ~]# systemctl stop avahi-daemon.service
[root@study ~]# systemctl stop avahi-daemon.socket
[root@study ~]# systemctl disable avahi-daemon.service avahi-daemon.socket
[root@study ~]# netstat -tlunp
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1340/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 2387/master
tcp6 0 0 :::555 :::* LISTEN 29113/vsftpd
tcp6 0 0 :::22 :::* LISTEN 1340/sshd
tcp6 0 0 ::1:25 :::* LISTEN 2387/master
一般來說,你的本地服務器至少需要 25 號埠口,而 22 號埠口則最好加上防火墻來管理遠程聯機登入比較妥當~因此,上面的埠口中, 除了 555 是我們上一章因為測試而產生的之外,這樣的系統能夠被爬墻的機會已經少很多了! ^_^!OK!現在如果你的系統里面有一堆網絡端口口在監聽, 而你根本不知道那是干麻用的,鳥哥建議你,現在就透過上面的方式,關閉他吧!
該系列目錄 --> 【BASH】回顧與知識點梳理(目錄)