Linux-Systemd
目錄
一、Systemd概述
二、Systemd優(yōu)勢
2.1兼容性
2.2啟動速度
2.3systemd 提供按需啟動能力
2.4采用 linux 的 cgroups 跟蹤和管理進程的生命周期
2.5啟動掛載點和自動掛載的管理
2.6實現(xiàn)事務性依賴關系管理
2.7日志服務
2.8 依賴關系
2.9systemd 事務
三、unit(單元)
四、systemd和systemctl
一、Systemd概述
? ? ? ?關于 systemd 的起源,首先要從 Linux 的 init 程序說起。Linux 系統(tǒng)在啟動過程中,內(nèi)核完成初始化以后,由內(nèi)核第一個啟動的程序便是 init 程序,路徑為 /sbin/init(為一個軟連接,鏈接到真實的 init 進程),其 PID 為1,它為系統(tǒng)里所有進程的“祖先”,Linux 中所有的進程都由 init 進程直接或間接進行創(chuàng)建并運行,init 進程以守護進程的方式存在,負責組織與運行系統(tǒng)的相關初始化工作,讓系統(tǒng)進入定義好的運行模式,如命令行模式或圖形界面模式。
init 程序的發(fā)展,大體上可分為三個階段:sysvinit->upstart->systemd,根據(jù) init 進程的發(fā)展特性,可以簡單理解為如下:
sysvinit:init 系統(tǒng)通過 shell 腳本以串行的方式啟動系統(tǒng)服務,下一個進程必須等待上一個進程啟動完成后才能開始啟動,因此系統(tǒng)啟動的過程比較慢。
upstart:在 sysvinit 的基礎上,把一些沒有關聯(lián)的程序并行啟動,以提高啟動的速度,但是存在依賴關系的程序仍然為串行啟動。
systemd:通過套接字激活的機制,讓所有無論有無依賴關系的程序全部并行啟動,并且僅按照系統(tǒng)啟動的需要啟動相應的服務,最大化提高開機啟動速度。
? ? ? ? systemd 是 linux 系統(tǒng)中最新的初始化系統(tǒng)(init),它主要的設計目標是克服 sysvinit 固有的缺點,提高系統(tǒng)的啟動速度。systemd 和 ubuntu 的 upstart 是競爭對手,但是時至今日 ubuntu 也采用了 systemd,所以 systemd 在競爭中勝出,大有一統(tǒng)天下的趨勢。目前主流的系統(tǒng)中,systemd 的守護進程主要分為系統(tǒng)態(tài)(system)與用戶態(tài)(user),可以在 ps -ef 中看到 systemd 的守護進程,如下:
? ? ?PID 為1的進程/sbin/init 即是 system 態(tài)的 systemd,它為一個軟鏈接,指向真實的 systemd 路徑,在操作系統(tǒng)中一般放在/usr/lib/systemd/目錄:
? ? ? ?systemd 為進程服務集合的總稱,它包含許多的進程,負責控制、管理系統(tǒng)的資源,其中包括 systemd-login,負責用戶登錄相關信息的創(chuàng)建、修改與刪除;systemd-sleep 控制系統(tǒng)的休眠、睡眠狀態(tài)切換等等。在優(yōu)麒麟操作系統(tǒng)下,它們主要集中在/usr/lib/systemd/文件目錄
二、Systemd優(yōu)勢
2.1兼容性
systemd 提供了和 sysvinit 兼容的特性。系統(tǒng)中已經(jīng)存在的服務和進程無需修改。這降低了系統(tǒng)向 systemd 遷移的成本,使得 systemd 替換現(xiàn)有初始化系統(tǒng)成為可能。
2.2啟動速度
systemd 提供了比 upstart 更激進的并行啟動能力,采用了 socket / D-Bus activation 等技術啟動服務。一個顯而易見的結(jié)果就是:更快的啟動速度。為了減少系統(tǒng)啟動時間,systemd 的目標是:
- 盡可能啟動更少的進程
- 盡可能將更多進程并行啟動
2.3systemd 提供按需啟動能力
當 sysvinit 系統(tǒng)初始化的時候,它會將所有可能用到的后臺服務進程全部啟動運行。并且系統(tǒng)必須等待所有的服務都啟動就緒之后,才允許用戶登錄。這種做法有兩個缺點:首先是啟動時間過長,其次是系統(tǒng)資源浪費。
某些服務很可能在很長一段時間內(nèi),甚至整個服務器運行期間都沒有被使用過。比如 CUPS,打印服務在多數(shù)服務器上很少被真正使用到。您可能沒有想到,在很多服務器上 SSHD 也是很少被真正訪問到的。花費在啟動這些服務上的時間是不必要的;同樣,花費在這些服務上的系統(tǒng)資源也是一種浪費。
systemd 可以提供按需啟動的能力,只有在某個服務被真正請求的時候才啟動它。當該服務結(jié)束,systemd 可以關閉它,等待下次需要時再次啟動它。
這有點類似于以前系統(tǒng)中的 inetd,并且有很多文章介紹如何把過去 inetd 管理的服務遷移到 systemd。
2.4采用 linux 的 cgroups 跟蹤和管理進程的生命周期
systemd 利用了 Linux 內(nèi)核的特性即 cgroups 來完成跟蹤的任務。當停止服務時,通過查詢 cgroups ,systemd 可以確保找到所有的相關進程,從而干凈地停止服務。
cgroups 已經(jīng)出現(xiàn)了很久,它主要用來實現(xiàn)系統(tǒng)資源配額管理。cgroups 提供了類似文件系統(tǒng)的接口,使用方便。當進程創(chuàng)建子進程時,子進程會繼承父進程的 cgroups 。因此無論服務如何啟動新的子進程,所有的這些相關進程都會屬于同一個 cgroups ,systemd 只需要簡單地遍歷指定的 cgroups 即可正確地找到所有的相關進程,將它們一一停止即可。
2.5啟動掛載點和自動掛載的管理
傳統(tǒng)的 linux 系統(tǒng)中,用戶可以用 /etc/fstab 文件來維護固定的文件系統(tǒng)掛載點。這些掛載點在系統(tǒng)啟動過程中被自動掛載,一旦啟動過程結(jié)束,這些掛載點就會確保存在。這些掛載點都是對系統(tǒng)運行至關重要的文件系統(tǒng),比如 HOME 目錄。和 sysvinit 一樣,Systemd 管理這些掛載點,以便能夠在系統(tǒng)啟動時自動掛載它們。systemd 還兼容 /etc/fstab 文件,您可以繼續(xù)使用該文件管理掛載點。
有時候用戶還需要動態(tài)掛載點,比如打算訪問 DVD 或者 NFS 共享的內(nèi)容時,才臨時執(zhí)行掛載以便訪問其中的內(nèi)容,而不訪問光盤時該掛載點被取消(umount),以便節(jié)約資源。傳統(tǒng)地,人們依賴 autofs 服務來實現(xiàn)這種功能。
systemd 內(nèi)建了自動掛載服務,無需另外安裝 autofs 服務,可以直接使用 systemd 提供的自動掛載管理能力來實現(xiàn) autofs 的功能。
2.6實現(xiàn)事務性依賴關系管理
系統(tǒng)啟動過程是由很多的獨立工作共同組成的,這些工作之間可能存在依賴關系,比如掛載一個 NFS 文件系統(tǒng)必須依賴網(wǎng)絡能夠正常工作。systemd 雖然能夠最大限度地并發(fā)執(zhí)行很多有依賴關系的工作,但是類似"掛載 NFS"和"啟動網(wǎng)絡"這樣的工作還是存在天生的先后依賴關系,無法并發(fā)執(zhí)行。對于這些任務,systemd 維護一個"事務一致性"的概念,保證所有相關的服務都可以正常啟動而不會出現(xiàn)互相依賴,以至于死鎖的情況。
2.7日志服務
systemd 自帶日志服務 journald,該日志服務的設計初衷是克服現(xiàn)有的 syslog 服務的缺點。比如:
- syslog 不安全,消息的內(nèi)容無法驗證。每一個本地進程都可以聲稱自己是 Apache PID 4711,而 syslog 也就相信并保存到磁盤上。
- 數(shù)據(jù)沒有嚴格的格式,非常隨意。自動化的日志分析器需要分析人類語言字符串來識別消息。一方面此類分析困難低效;此外日志格式的變化會導致分析代碼需要更新甚至重寫。
systemd journal 用二進制格式保存所有日志信息,用戶使用 journalctl 命令來查看日志信息。無需自己編寫復雜脆弱的字符串分析處理程序。
systemd journal 的優(yōu)點如下:
簡單性:代碼少,依賴少,抽象開銷最小。
零維護:日志是除錯和監(jiān)控系統(tǒng)的核心功能,因此它自己不能再產(chǎn)生問題。舉例說,自動管理磁盤空間,避免由于日志的不斷產(chǎn)生而將磁盤空間耗盡。
移植性:日志文件應該在所有類型的 Linux 系統(tǒng)上可用,無論它使用的何種 CPU 或者字節(jié)序。
性能:添加和瀏覽日志非常快。
最小資源占用:日志數(shù)據(jù)文件需要較小。
統(tǒng)一化:各種不同的日志存儲技術應該統(tǒng)一起來,將所有的可記錄事件保存在同一個數(shù)據(jù)存儲中。所以日志內(nèi)容的全局上下文都會被保存并且可供日后查詢。例如一條固件記錄后通常會跟隨一條內(nèi)核記錄,最終還會有一條用戶態(tài)記錄。重要的是當保存到硬盤上時這三者之間的關系不會丟失。syslog 將不同的信息保存到不同的文件中,分析的時候很難確定哪些條目是相關的。
擴展性:日志的適用范圍很廣,從嵌入式設備到超級計算機集群都可以滿足需求。
安全性:日志文件是可以驗證的,讓無法檢測的修改不再可能。
在了解了 systemd 的種種優(yōu)勢之后讓我們開始認識它的一些基本概念。
2.8 依賴關系
雖然 systemd 將大量的啟動工作解除了依賴,使得它們可以并發(fā)啟動。但還是存在有些任務,它們之間存在天生的依賴,不能用"套接字激活"(socket activation)、D-Bus activation 和 autofs 三大方法來解除依賴。比如:掛載必須等待掛載點在文件系統(tǒng)中被創(chuàng)建;掛載也必須等待相應的物理設備就緒。為了解決這類依賴問題,systemd 的配置單元之間可以彼此定義依賴關系。Systemd 用配置單元定義文件中的關鍵字來描述配置單元之間的依賴關系。比如:unit A 依賴 unit B,可以在 unit B 的定義中用"require A"來表示。這樣 systemd 就會保證先啟動 A 再啟動 B。
2.9systemd 事務
systemd 能保證事務完整性。Systemd 的事務概念和數(shù)據(jù)庫中的有所不同,主要是為了保證多個依賴的配置單元之間沒有環(huán)形引用。比如存在 unit A、B、C,假如它們的依賴關系如下(此圖來自互聯(lián)網(wǎng)):
存在循環(huán)依賴,那么 systemd 將無法啟動任意一個服務。此時 systemd 將會嘗試解決這個問題,因為配置單元之間的依賴關系有兩種:required 是強依賴;want 則是弱依賴,systemd 將去掉 wants 關鍵字指定的依賴看看是否能打破循環(huán)。如果無法修復,systemd 會報錯。systemd 能夠自動檢測和修復這類配置錯誤,從而極大地減輕了管理員的排錯負擔。
三、unit(單元)
系統(tǒng)初始化需要做的事情非常多。需要啟動后臺服務,比如啟動 ssh 服務;需要做配置工作,比如掛載文件系統(tǒng)。這個過程中的每一步都被 systemd 抽象為一個配置單元,即 unit。可以認為一個服務是一個配置單元,一個掛載點是一個配置單元,一個交換分區(qū)的配置是一個配置單元等等。systemd 將配置單元歸納為以下一些不同的類型。然而,systemd 正在快速發(fā)展,新功能不斷增加。所以配置單元類型可能在不久的將來繼續(xù)增加。下面是一些常見的 unit 類型:
? ? ? ?service :代表一個后臺服務進程,比如 MySQLd。這是最常用的一類。
? ? ? ?socket :此類配置單元封裝系統(tǒng)和互聯(lián)網(wǎng)中的一個套接字 。當下,systemd 支持流式、數(shù)據(jù)報和 連續(xù)包的 AF_INET、AF_INET6、AF_UNIX socket 。每一個套接字配置單元都有一個相應的服務配置單元 。相應的服務在第一個"連接"進入套接字時就會啟動(例如:nscd.socket 在有新連接后便啟動 nscd.service)。
? ? ? ?device :此類配置單元封裝一個存在于 Linux 設備樹中的設備。每一個使用 udev 規(guī)則標記的設備都將會在 systemd 中作為一個設備配置單元出現(xiàn)。
? ? ? ?mount :此類配置單元封裝文件系統(tǒng)結(jié)構(gòu)層次中的一個掛載點。Systemd 將對這個掛載點進行監(jiān)控和管理。比如可以在啟動時自動將其掛載;可以在某些條件下自動卸載。Systemd 會將? /etc/fstab 中的條目都轉(zhuǎn)換為掛載點,并在開機時處理。
? ? ? ?automount :此類配置單元封裝系統(tǒng)結(jié)構(gòu)層次中的一個自掛載點。每一個自掛載配置單元對應一個掛載配置單元 ,當該自動掛載點被訪問時,systemd 執(zhí)行掛載點中定義的掛載行為。
? ? ? swap:和掛載配置單元類似,交換配置單元用來管理交換分區(qū)。用戶可以用交換配置單元來定義系統(tǒng)中的交換分區(qū),可以讓這些交換分區(qū)在啟動時被激活。
? ? ? target :此類配置單元為其他配置單元進行邏輯分組。它們本身實際上并不做什么,只是引用其他配置單元而已。這樣便可以對配置單元做一個統(tǒng)一的控制。這樣就可以實現(xiàn)大家都已經(jīng)非常熟悉的運行級別概念。比如想讓系統(tǒng)進入圖形化模式,需要運行許多服務和配置命令,這些操作都由一個個的配置單元表示,將所有這些配置單元組合為一個目標(target),就表示需要將這些配置單元全部執(zhí)行一遍以便進入目標所代表的系統(tǒng)運行狀態(tài)。 (例如:multi-user.target 相當于在傳統(tǒng)使用 SysV 的系統(tǒng)中運行級別 5)
? ? ? ? timer:定時器配置單元用來定時觸發(fā)用戶定義的操作,這類配置單元取代了 atd、crond 等傳統(tǒng)的定時服務。
? ? ? ?snapshot :與 target 配置單元相似,快照是一組配置單元。它保存了系統(tǒng)當前的運行狀態(tài)。
path:文件系統(tǒng)中的一個文件或目錄。
scope:用于 cgroups,表示從 systemd 外部創(chuàng)建的進程。
slice:用于 cgroups,表示一組按層級排列的單位。slice 并不包含進程,但會組建一個層級,并將 scope 和 service 都放置其中。
? ? ? ? 每個配置單元都有一個對應的配置文件,系統(tǒng)管理員的任務就是編寫和維護這些不同的配置文件,比如一個 MySQL 服務對應一個 mysql.service 文件。這種配置文件的語法非常簡單,用戶不需要再編寫和維護復雜的系統(tǒng)腳本了。
下面是 docker.service
[root@k8s-master ~]# cat /usr/lib/systemd/system/docker.service [Unit] Description=Docker Application Container Engine Documentation=https://docs.docker.com BindsTo=containerd.service After=network-online.target firewalld.service containerd.service Wants=network-online.target Requires=docker.socket[Service] Type=notify # the default is not to use systemd for cgroups because the delegate issues still # exists and systemd currently does not support the cgroup feature set required # for containers run by docker ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock ExecReload=/bin/kill -s HUP $MAINPID TimeoutSec=0 RestartSec=2 Restart=always# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229. # Both the old, and new location are accepted by systemd 229 and up, so using the old location # to make them work for either version of systemd. StartLimitBurst=3# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230. # Both the old, and new name are accepted by systemd 230 and up, so using the old name to make # this option work for either version of systemd. StartLimitInterval=60s# Having non-zero Limit*s causes performance problems due to accounting overhead # in the kernel. We recommend using cgroups to do container-local accounting. LimitNOFILE=infinity LimitNPROC=infinity LimitCORE=infinity# Comment TasksMax if your systemd version does not supports it. # Only systemd 226 and above support this option. TasksMax=infinity# set delegate yes so that systemd does not reset the cgroups of docker containers Delegate=yes# kill only the docker process, not all processes in the cgroup KillMode=process[Install] WantedBy=multi-user.target- Unit 段:此部分所有 Unit 文件通用,用來定義 Unit 的元數(shù)據(jù)、配置以及與其他 Unit 的關系,Description 描述 Unit 文件信息,Documentation 表示指定服務的文檔,Condition 表示服務啟動的條件,有些 Unit 還包含 wants、before、after、require 字段,這些表示服務的一個依賴關系。
- Install 段:此部分所有 Unit 文件通用,通常指定運行目標的 target,使得服務在系統(tǒng)啟動時自動運行。Wantedby、RequiredBy 與 Unit 段 Wants 字段類似,表示依賴關系,Alias 字段表示啟動運行時使用的別名。
- service 段:服務(Service)類型的 Unit 文件特有的字段,用于定義服務的具體管理和執(zhí)行動作。其中包括 Type 字段,定義進程的行為,例如使用 fork()啟動,使用 dbus 啟動等等;ExecStart、ExecStartPre、ExecStartPos、ExecReload、ExecStop 分別表示啟動當前服務執(zhí)行的命令、啟動當前服務之前執(zhí)行的命令、啟動當前服務之后啟動的命令、重啟當前服務時執(zhí)行的命令、停止當前服務時執(zhí)行的命令。以上圖為例,啟動藍牙服務所需要執(zhí)行的命令為/usr/lib/bluetooth/bluetoothd。
對于systemd的所有詳細啟動順序情況,我們可以使用systemd本身自帶的systemd-anlyze,它是一個分析啟動性能的工具,
[root@k8s-master1 ~]# systemd-analyze --help systemd-analyze [OPTIONS...] {COMMAND} ...Profile systemd, show unit dependencies, check unit files.-h --help Show this help--version Show package version--no-pager Do not pipe output into a pager--system Operate on system systemd instance-H --host=[USER@]HOST Operate on remote host-M --machine=CONTAINER Operate on local container--order Show only order in the graph--require Show only requirement in the graph--from-pattern=GLOB Show only origins in the graph--to-pattern=GLOB Show only destinations in the graph--fuzz=SECONDS Also print also services which finished SECONDSearlier than the latest in the branch--man[=BOOL] Do [not] check for existence of man pagesCommands:time Print time spent in the kernelblame Print list of running units ordered by time to initcritical-chain Print a tree of the time critical chain of unitsplot Output SVG graphic showing service initializationdot Output dependency graph in dot(1) formatset-log-level LEVEL Set logging threshold for systemddump Output state serialization of service managerverify FILE... Check unit files for correctness系統(tǒng)啟動時間
[root@k8s-master ~]# systemd-analyze Startup finished in 3.099s (kernel) + 3.536s (initrd) + 18.010s (userspace) = 24.646s [root@k8s-master ~]#打印上次開機時的所有服務,并顯示服務耗時
給出的樹形關鍵路徑就是該unit的最長耗時路徑.
?systemd-analyze plot > boot.svg
詳細的systemd啟動流程,直到graphical.target. 將boot.svg拖入瀏覽器顯示如下
?
四、systemd和systemctl
? ? ? ?提到systemctl就一定需要知道systemd,因為Linux 服務管理有兩種方式service和systemctl。而systemd是Linux系統(tǒng)最新的初始化系統(tǒng)(init),作用是提高系統(tǒng)的啟動速度,盡可能啟動較少的進程,盡可能更多進程并發(fā)啟動,systemd對應的進程管理命令就是systemctl。值得一提的是,systemctl命令兼容了service哦。
這里咱們梳理一下systemd這個啟動服務管理機制有哪些好處(也就是使用systemctl相關命令的好處啦)。
? ? ? ? 平行處理所有服務,加速開機流程:舊的init啟動腳本(System V的那個)是“一項一項任務依序啟動”的模式,因此不相依的服務也是得要一個一個的等待。而systemd可以讓所有的服務同時啟動,畢竟目前我們的硬件主機系統(tǒng)與操作系統(tǒng)幾乎都支持多核心架構(gòu),因此你會發(fā)現(xiàn)到,系統(tǒng)啟動的速度變快了;
? ? ? ?一經(jīng)請求就響應的on-demand啟動方式:systemd僅有一只systemd服務搭配systemctl指令進行處理,無須其他額外的指令來支持。不像systemV還要init,chkconfig,service...等等指令。此外,systemd由于常駐內(nèi)存,因此任何請求(on-demand)都可以立即處理后續(xù)的daemon啟動的任務;
? ? ? 服務關聯(lián)性的自我檢查:由于systemd可以自行進行服務關聯(lián)性的檢查,因此如果B服務的啟動前提是A服務,那當你在沒有啟動A服務的情況下僅手動啟動B服務時,systemd會自動幫你啟動A服務;
? ? ? ?根據(jù)daemon功能分類:systemd旗下管理的服務非常多,為了理清所有服務的功能,因此,首先systemd先定義所有的服務為一個服務單位(這里單位叫“unit”,挺重要的,后面詳細說),并將該unit分類到不同的服務類型(type)中。systemd將服務單位(unit)區(qū)分為service,socket,target,path,snapshot,timer等多種不同的類型(type);
? ? ? 將多個daemons集合成為一個群組:systemd將許多的功能集合成為一個所謂的target項目,這個項目主要用于設計操作環(huán)境的創(chuàng)建,所以集合了許多的daemons(執(zhí)行某個target就是執(zhí)行多個daemon);
? ? ? ?向下兼容容舊有的init服務腳本:基本上,systemd是可以兼容init的啟動腳本,因此,舊的init啟動腳本也能夠通過systemd來管理,當然了,這里僅限于不使用systemd的某些高級功能;
————————————————
reference:
干貨分享 | Systemd 技術原理&實踐(上) - 知乎
關于 systemd 的初步理解_Linux教程_Linux公社-Linux系統(tǒng)門戶網(wǎng)站???????
?
總結(jié)
以上是生活随笔為你收集整理的Linux-Systemd的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 批量修改图片的后缀名以及删除相同的符号
- 下一篇: 死亡直播间