首頁 >系統教程 >Linux >深入解析CentOS 7下的systemd管理系統

深入解析CentOS 7下的systemd管理系統

PHPz
PHPz轉載
2024-01-06 08:53:42697瀏覽

CentOS系統啟動流程:

POST --> Boot Sequence --> Bootloader --> kernel initramfs(initrd) --> rootfs --> /sbin/init

innit程式:

CentOS 5:SysV init

CetnOS 6:  Upstart

#CentOS 7 : Systemd

Systemd新功能:

系統Sys V init和LSB init scripts相容

系統引導時實現服務並行啟動;

採用socket / D-Bus activation等技術啟動服務;為了減少系統啟動時間,systemd的目標是:盡可能啟動更少的進程;盡可能將更多的進程並行啟動;

按需啟動進程;

Systemd可以提供按需啟動的能力,只有在某個服務被真正要求的時候才啟動它。當服務結束,systemd可以關閉它,等待下次需要時再次啟動它。

能夠對系統進行快照和復原;

啟動掛載點和自動掛載點的管理:

#Systemd自助管理系統上的掛載點,以便能夠在系統啟動時自動掛載它們。且相容/etc/fstab檔;

實作事務依賴關係管理:

systemd 維護一個"交易一致性"的概念,確保所有相關的服務都可以正常啟動而不會出現互相依賴,以至於死鎖的情況。

基於內生依賴關係定義服務控制邏輯;

#system利用Linux核心的特性即CGroup來完成進程追蹤的任務。當停止服務時,透過查詢CGroup,systemd可以確保找到所有的相關進程,以便乾淨地停止服務;

日誌服務:

systemd自帶日誌服務journald,此日誌服務的設計初衷是克服現有的syslog服務的缺點。

System的基本概念

單元的概念:

#系統初始化需要做的事情非常多。需要啟動後台服務,例如啟動 SSHD 服務;需要做設定工作,例如掛載檔案系統。這個過程中的每一步都被 systemd 抽象化為一個配置單元,即 unit。可以認為一個服務是一個配置單元;一個掛載點是一個配置單元;一個交換分區的配置是一個配置單元;等等。 systemd 將配置單元歸納為以下一些不同的類型。然而,systemd 正在快速發展,新功能不斷增加。所以配置單元類型可能在不久的將來繼續增加。

service:代表一個後台服務進程,例如mysqld。這是常用的一類;

socket:此類設定單元封裝系統和網際網路中的一個套接字。當下,systemd支援流式、資料包和連續包的AF_INET、AF_INET6、AF_UNIX socket。每一個套接字配置單元都有一個對應的服務配置單元 。對應的服務在第一個"連接"進入套接字時就會啟動(例如:nscd.socket 在有新連線後便啟動 nscd.service)。

device :此類組態單元封裝一個存在於 Linux 裝置樹中的裝置。每一個使用 udev 規則標記的裝置都會在 systemd 中作為一個裝置配置單元出現。

mount :此類設定單元封裝檔案系統結構層次中的一個掛載點。 Systemd 將對這個掛載點進行監控與管理。例如可以在啟動時自動將其掛載;可以在某些條件下自動卸載。 Systemd 會將/etc/fstab 中的條目都轉換為掛載點,並在開機時處理。

automount :此類組態單元封裝系統結構層次中的一個自掛載點。每一個自掛載配置單元對應一個掛載配置單元 ,當該自動掛載點被存取時,systemd 執行掛載點中定義的掛​​載行為。

swap: 和掛載設定單元類似,交換設定單元用來管理交換分割區。使用者可以用交換配置單元來定義系統中的交換分區,可以讓這些交換分區在啟動時被啟動。

target :此類組態單元為其他組態單元進行邏輯分組。它們本身其實並不做什麼,只是引用其他組態單元而已。這樣便可以對配置單元做一個統一的控制。這樣就可以實現大家都已經非常熟悉的運行等級概念。例如想讓系統進入圖形化模式,需要執行許多服務和設定指令,這些操作都由一個個的組態單元表示,將所有這些組態單元組合為一個目標(target),就表示需要將這些組態單元全部執行一遍以便進入目標所代表的系統運作狀態。 (例如:multi-user.target 相當於在傳統使用 SysV 的系統中運作等級 3)

timer:定時器組態單元用來定時觸發使用者定義的操作,這類組態單元取代了 atd、crond 等傳統的定時服務。

snapshot :與 target 配置單元相似,快照是一組組態單元。它保存了系統目前的運作狀態。

依賴關係:

####

雖然 systemd 將大量的啟動工作解除了依賴,使得它們可以並發啟動。但還是有一些任務,它們之間有天生的依賴,不能用"套接字啟動"(socket activation)、D-Bus activation 和 autofs 三大方法來解除依賴(三大方法詳情見後續描述)。例如:掛載必須等待掛載點在檔案系統中被建立;掛載也必須等待對應的實體設備就緒。為了解決這類依賴問題,systemd 的配置單元之間可以彼此定義依賴關係。

Systemd 用設定單元定義檔中的關鍵字來描述設定單元之間的依賴關係。例如:unit A 依賴 unit B,可以在 unit B 的定義中用"require A"來表示。這樣 systemd 就會保證先啟動 A 再啟動 B。

Systemd交易:

Systemd 能保證事務完整性。 Systemd 的事務概念和資料庫中的有所不同,主要是為了確保多個依賴的組態單元之間沒有環形引用。 存在循環依賴,那麼 systemd 將無法啟動任意一個服務。此時systemd 將會嘗試解決這個問題,因為配置單元之間的依賴關係有兩種:required是強依賴;want 則是弱依賴,systemd 將去掉 wants 關鍵字指定的依賴看看是否能打破循環。如果無法修復,systemd會報錯。

Systemd 能夠自動偵測並修復這類設定錯誤,大幅減輕了管理員的排錯負擔。

Target和運行等級:

systemd 用目標(target)取代了運行等級的概念,提供了更大的靈活性,如您可以繼承一個現有的目標,並添加其它服務,來創建自己的目標。下表列舉了 systemd 下的目標和常見 runlevel 的對應關係:

CentOS 7下systemd管理的详解

#Systemd 的並發啟動原則

如前所述,在 Systemd 中,所有的服務都並發啟動,例如Avahi、D-Bus、livirtd、X11、HAL 可以同時啟動。乍看,這似乎有點問題,例如 Avahi 需要syslog 的服務,Avahi 和syslog 同時啟動,假設 Avahi 的啟動比較快,所以syslog 還沒準備好,可是 Avahi 又需要記錄日誌,這豈不是會出現問題?

Systemd 的開發人員仔細研究了服務之間相互依賴的本質問題,發現所謂依賴可以分為三個具體的類型,而每一個類型實際上都可以透過相應的技術解除依賴關係。

並發啟動原理之一:解決 socket #依賴

絕大多數的服務依賴是套接字依賴。例如服務A 透過一個套接字連接埠S1 提供自己的服務,其他的服務如果需要服務A,則需要連接S1。因此如果服務A 尚未啟動,S1就不存在,其他的服務就會啟動錯誤。所以傳統地,人們需要先啟動服務A,等待它進入就緒狀態,再啟動其他需要它的服務。 Systemd認為,只要我們預先把S1 建立好,那麼其他所有的服務就可以同時啟動而無需等待服務A 來創建S1 了。如果服務A 尚未啟動,那麼其他進程向S1 發送的服務請求實際上會被Linux 作業系統緩存,其他進程會在這個請求的地方等待。一旦服務A 啟動就緒,就可以立即處理快取的請求,一切都開始正常運作。

那麼服務如何使用 init 程序所建立的套接字呢?

Linux 作業系統有一個特性,當一個行程呼叫fork 或exec 來建立子程序之後,所有在父行程中被開啟的檔案句柄(file descriptor) 都被程序所繼承。套接字也是一種檔案句柄,進程A 可以建立一個套接字,此後當進程A 呼叫 exec啟動一個新的子進程時,只要確保該套接字的close_on_exec 標誌位元被清空,那麼新的子進程就可以繼承這個套接字。子進程看到的套接字和父進程創建的套接字是同一個系統套接字,就彷彿這個套接字是子進程自己創建的一樣,沒有任何區別。

這個特性以前被一個叫做 inetd 的系統服務所利用。 Inetd 進程會負責監控一些常用套接字端口,例如Telnet,當該端口有連接請求時,inetd才啟動 telnetd 進程,並將有連接的套接字傳遞給新的telnetd 進程進行處理。這樣,當系統沒有telnet 客戶端連線時,就不需要啟動telnetd 進程。 Inetd可以代理很多的網路服務,這樣就可以節約很多的系統負載和記憶體資源,只有當有真正的連線請求時才啟動對應服務,並把套接字傳遞給對應的服務程序。

和 inetd 類似,systemd 是所有其他進程的父進程,它可以先建立所有需要的套接字,然後在呼叫exec 的時候將該套接字傳遞給新的服務進程,而新進程直接使用該套接字進行服務即可。

並發啟動原理之二:解決 D-Bus 

##D-Bus 是 desktop-bus 的簡稱,是低延遲、低開銷、高可用性的進程間通訊機制。它越來越多地用於應用程式之間通信,也用於應用程式和作業系統核心之間的通信。許多現代的服務流程都使用D-Bus取代套接字作為進程間通訊機制,對外提供服務。例如簡化Linux 網路設定的NetworkManager 服務就使用D-Bus 和其他的應用程式或服務進行互動:郵件用戶端軟體evolution 可以透過D-Bus 從NetworkManager 服務取得網路狀態的改變,以便做出對應的處理。

D-Bus 支援所謂"busactivation"功能。如果服務A 需要使用服務 B 的 D-Bus 服務,而服務 B 並沒有運行,則 D-Bus 可以在服務 A 請求服務 B 的 D-Bus 時自動啟動服務 B。而服務 A 發出的請求會被 D-Bus 緩存,服務 A 則等待服務 B 啟動就緒。利用這個特性,依賴D-Bus 的服務就可以實現並行啟動。

並發啟動原理之三:解決檔案系統依賴

#系統啟動過程中,檔案系統相關的活動是最耗時的,例如掛載檔案系統,對檔案系統進行磁碟檢查(fsck),磁碟配額檢查等都是非常耗時的操作。在等待這些工作完成的同時,系統處於空閒狀態。那些想使用檔案系統的服務似乎必須等待檔案系統初始化完成才可以啟動。但是systemd 發現這種依賴也是可以避免的。

Systemd 參考了 autofs 的設計思路,​​使得依賴檔案系統的服務和檔案系統本身初始化兩者可以並發工作。 autofs可以監測到某個檔案系統掛載點真正被存取到的時候才觸發掛載操作,這是透過內核automounter 模組的支援而實現的。例如一個open()系統呼叫作用在"/misc/cd/file1"的時候,/misc/cd 尚未執行掛載操作,此時 open()呼叫被掛起等待,Linux 核心通知 autofs,autofs 執行掛載。這時候,控制權返回給open()系統調用,並正常打開檔案。

Systemd 整合了 autofs 的實現,對於系統中的掛載點,例如/home,當系統啟動的時候,systemd 為其建立一個臨時的自動掛載點。在這個時刻/home真正的掛載設備尚未啟動好,真正的掛載操作還沒有執行,檔案系統偵測也還沒完成。可是那些依賴該目錄的程序已經可以並發啟動,他們的open()操作被內建在systemd 中的autofs 捕獲,將該open()調用掛起(可中斷睡眠狀態)。然後等待真正的掛載操作完成,檔案系統偵測也完成後,systemd將該自動掛載點替換為真正的掛載點,並讓open()呼叫返回。由此,實現了那些依賴檔案系統的服務和檔案系統本身同時並發啟動。

當然對於"/"根目錄的依賴實際上一定還是要串行執行,因為systemd 自己也存放在/之下,必須等待系統根目錄掛載檢查好。

不過對於類似/home 等掛載點,這種並發可以提高系統的啟動速度,尤其是當/home是遠端的 NFS 節點,或是加密磁碟等,需要耗費較長的時間才可以準備就緒的情況下,因為並發啟動,在這段時間內,系統並不是完全無事可做,而是可以利用這段空餘時間做更多的啟動進程的事情,總的來說就縮短了系統啟動時間。

Systemd 的使用

以下針對技術人員的不同角色來簡單地介紹一下 systemd 的使用。本文只打算給予簡單的描述,讓您對 systemd 的使用有一個大概的理解。具體的細節內容太多,就是無法在一篇短文內寫全。還需要讀者自己去進一步查閱 systemd的文檔。

Unit 檔案的編寫

#開發人員開發了一個新的服務程序,例如httpd,就需要為其編寫一個配置單元檔案以便該服務可以被systemd 管理,類似UpStart 的工作設定檔。在該文件中定義服務啟動的命令列語法,以及和其他服務的依賴關係等。

此外我們之前已經了解到,systemd 的功能繁多,不僅用來管理服務,還可以管理掛載點,定義定時任務等。這些工作都是由編輯對應的設定單元檔案完成的。我在這裡給出幾個配置單元文件的例子。

下面是 SSH 服務的設定單元文件,服務設定單元檔案以.service為檔案名稱後綴。

[root@kalaguiyin system]# cat/usr/lib/systemd/system/sshd.service 

[Unit]

Description=OpenSSH server daemon

After=network.target sshd-keygen.service

Wants=sshd-keygen.service

##[unit]部分,描述訊息

[Service]

EnvironmentFile=/etc/sysconfig/sshd

ExecStart=/usr/sbin/sshd -D $OPTIONS

ExecReload=/bin/kill -HUP $MAINPID

KillMode=process

Restart=on-failure

##RestartSec=42s

#[service]定義,ExecStartPre定義啟動服務之前應該執行的命令;

#ExecStart 定義啟動服務的特定命令列語法。

[Install]

WantedBy=multi-user.target

#[install]部分:WangtedBy顯示這個服務是在多用戶模式下所需要的。

那我們就來看看multi-user.target 吧:

[root@kalaguiyin system]# catmulti-user.target

[Unit]

Description=Multi-User System

Documentation=man:systemd.special(7)

Requires=basic.target

#Conflicts=rescue.service rescue.target

After=basic.target rescue.servicerescue.target

AllowIsolate=yes

# Requires 定義顯示 multi-user.target 啟動的時候 basic.target 也必須啟動;另外 basic.target 停止的時間# 候,multi-user.target 也必須停止。如果您接著查看 basic.target 文件,您會發現它又指定了 sysinit.target 

# 其他的單元必須隨之啟動。同樣 sysinit.target 也會包含其他的單位。採用這樣的層層連結的結構,最終所# 有需要支援多用戶模式的元件服務都會被初始化啟動好。

[Install]

Alias=default.target

##  Alias 定義,即定義本單元的別名,以便在執行 systemctl 的時候就可以使用這個別名來引用本單元。

此外在/etc/systemd/system 目錄下還可以看到諸如*.wants 的目錄,放在該目錄下的配置單元檔案等同於在[Unit]小節中的 wants 關鍵字,即本單元啟動時,還需要啟動這些單元。例如您可以簡單地把您自己寫的 foo.service 檔案放入 multi-user.target.wants 目錄下,這樣每次都會被預設啟動了。

[root@kalaguiyin system]# pwd

##### ###/etc/systemd/system#### ###[root@kalaguiyin system]# ls### ###basic.target.wants                          display-manager.service### ###bluetooth.target.wants                       getty.target.wants### ###dbus-org.bluez.service                       graphical.target.wants### ###printer.target.wants                                

spice-vdagentd.target.wants                          wants                                 

再讓我們來看看sys-kernel-debug.mout文件,這個文件定義了一個文件掛載點:

[root@kalaguiyin system]# cat

##sys-kernel-debug.mount

[Unit]

Description=Debug File System

Documentation=https://www.kernel.org/doc/Documentation/filesystems/debugfs.txt

Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems

DefaultDependencies=no

#ConditionPathExists=/sys/kernel/debug

##Before=sysinit.target

#[Mount]

What=debugfs

Where=/sys/kernel/debug##Type=debugfs

這個設定單元檔案定義了一個掛載點。掛載設定檔檔案有一個[Mount]設定小節,裡面設定了 What,Where 和Type 三個資料項目。這都是掛載指令所必須的,範例中的設定等同於下面這個掛載指令:

mount –t debugfs /sys/kernel/debug debugfs


##Systemd

CentOS 7下systemd管理的详解系統管理:


#systemd 的主要命令列工具是 systemctl。

多數管理者應該都已經非常熟悉系統服務和 init 系統的管理,例如 service、chkconfig以及 telinit 指令的使用。 systemd 也完成同樣的管理任務,只是命令工具systemctl 的語法有所不同而已。

啟動服務CentOS 7下systemd管理的详解

systemctl start httpd.service 如圖1:

#停止服務CentOS 7下systemd管理的详解

systemctl stop httpd.service  如圖2:

#重啟服務

systemctl restarthttpd.service  如圖3:

#重載服務

systemctl reloadhttpd.service

條件式重啟

systemctl condrestarthttpd.service

#狀態查看

systemctl statushttpd.service

#列出可以啟動或停止的服務清單。

systemctl list-unit-files –type=service

#設定服務為開機啟動

chkconfig httpd on

##systemctl enablehttpd.service

##取消服務開機啟動;

systemctl disablehttpd.service

檢查一個服務在目前環境下被配置為啟用還是停用。

systemctl is-enabledhttpd.service;echo $?

輸出在各個運行等級下服務的啟用和停用情況

systemctl list-unit-files –type=service

#列出某服務在哪些運作等級下啟用和停用。

ls /etc/lib/systemd/system/*.wants/httpd.service

改變使用者運行等級:CentOS 7下systemd管理的详解

systemctl isolatemulti-user.target

#multi-user.target   ==  第3運轉等級

graphical.target    ==  第5運轉等級 runlevel3.target 符號鏈接,指向multi-user.target runlevel5.target 符號鏈接,指向graphical.target#改變預設運行等級:

[root@kalaguiyinsystem]# systemctl set-default multi-user.target #### ###rm'/etc/systemd/system/default.target'#### ###ln -s'/usr/lib/systemd/system/multi-user.target''/etc/systemd/system/default.target'### ###上述操作的實質是刪除/usr/lib/systemd/system/default.target,然後將目標層級的target檔案連結至/etc/systemd/system/default.target檔案;### ########## ###systemd 已經不只是一個初始化系統了:### ######systemd ######也負責系統其他的管理配置,例如配置網絡,######Locale ######管理,管理系統核心模組載入等。 ######

Systemd 出色地取代了sysvinit 的所有功能,但它並未就此自滿。因為init 行程是系統所有行程的父行程這樣的特殊性,systemd 非常適合提供曾經由其他服務提供的功能,例如定時任務 (以前由 crond 完成) ;會話管理 (以前由 ConsoleKit/PolKit 等管理) ;會話管理 (以前由 ConsoleKit/PolKit 等管理)  。光從本文皮毛一樣的介紹來看,S​​ystemd已經管得很多了,但它還在不斷發展。它將逐漸成為一個多功能的系統環境,能夠處理非常多的系統管理任務,有人甚至將它視為一個作業系統。這非常有助於標準化 Linux 的管理!

以上是深入解析CentOS 7下的systemd管理系統的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:jb51.net。如有侵權,請聯絡admin@php.cn刪除