systemd服务分析
systemd 是 Linux 系統(tǒng)工具,用來啟動守護進程,已成為大多數(shù)發(fā)行版的標準配置。
systemd 的優(yōu)點是功能強大,使用方便,缺點是體系龐大,非常復(fù)雜;systemd執(zhí)行服務(wù)是并行的,如果沒有人為的干預(yù)附加啟動依賴,同級服務(wù)啟動順序是亂序的,這個在后續(xù)會體現(xiàn)出來。
systemd囊括的功能板塊很多,內(nèi)容更傾向運維工作,目前因項目需求,就服務(wù)板塊進行分析。
systemd不是簡單的一個命令,而是非常復(fù)雜一組命令,涵蓋系統(tǒng)管理的方方面面。
一、systemctl
systemctl是systemd的主要命令,用于整體管理系統(tǒng)各項服務(wù)等。
在systemctl眼里,最小的功能單位就是單元,也是單個進程的描述,一個個小的單元互相調(diào)用和依賴,組成一個龐大的任務(wù)管理系統(tǒng),這就是 Systemd 的基本思想。
通過systemctl list-unit-files可以查看當(dāng)前系統(tǒng)中所有的單元,如下:
每個單元都有一個描述單元的文件,用于規(guī)范單元的功能和執(zhí)行的機制,分別存放在三個不同的目錄:
1.1 查看單元
像上述的查看系統(tǒng)中所有的單元文件的命令如下:
/lib/systemd/system /etc/systemd/system /usr/lib/systemd/system- /lib/systemd/system:主要存放的是系統(tǒng)默認的單元文件;
- /etc/systemd/system:用戶安裝的軟件的單元文件;
- /usr/lib/systemd/system:用戶自定義的單元文件;
1.2 單元的管理
明白了單元存在的含義,那么需要管理呀,怎么管理單元的動作,具體如下:
systemctl start [UnitName] systemctl stop [UnitName] systemctl restart [UnitName] systemctl kill [UnitName] systemctl status [UnitName] systemctl enable [UnitName] systemctl disable [UnitName]顧名思義,通過systemctl控制對單元的開啟、停止、重啟等操作,這里著重說明的是:
- systemctl enable [UnitName]:用來開啟單元的開機自啟動,這步動作會生成一個符號鏈接,鏈接到你設(shè)計的單元指定的target下面,后續(xù)展開說明;
- systemctl disable [UnitName]:用來取消單元開機自啟動;
- 該服務(wù)需要慎用,對于某些服務(wù)來說,取消單元開機自啟動時,會導(dǎo)致該單元某些文件的缺失,親測!!
- 在取消lightdm.service單元服務(wù)時,即使使用systemctl enable lightdm.service恢復(fù)開機自啟動都無濟于事,需要通過sudo apt-get install --reinstall lightdm進行重裝。
- systemctl status [UnitName]:查看單元當(dāng)前狀態(tài),具體如下:
通過查看status可以查看服務(wù)具體啟動的信息,這個后續(xù)講解自啟動服務(wù)的時候會仔細分析到。
二、systemd-analyze
簡單分析完systemctl的部分功能之后,systemd還提供了一個可以查看所有啟動的總耗時的工具,systemd-analyze;
systemd-analyze systemd-analyze blame systemd-analyze plot > filename.svg systemd-analyze critical-chain systemd-analyze critical-chain atd.service- systemd-analyze:直接查看服務(wù)單元啟動時間,如下
- 這里不是簡單的展開系統(tǒng)開機時間,而是包括了內(nèi)核啟動時間和用戶啟動時間,在兩個不同的硬件上,可以看到,前者是虛擬機中執(zhí)行的結(jié)果,后者直接搭載在板子上的linux系統(tǒng)甚至可以看到固件執(zhí)行時間、加載時間、內(nèi)核啟動時間、以及用戶啟動時間,具體的含義有待后續(xù)進一步確認;
- systemd-analyze blame:查看每個服務(wù)的啟動耗時,該命令直接將不同服務(wù)單元的啟動用時打印出來,如下:
-
不難看出plymouth-quit-wait.service單元服務(wù)執(zhí)行用時11.832秒,但是這個順序并不代表執(zhí)行順序,而是以耗時長短排序,需要得到啟動順序,執(zhí)行后面的命令;
- systemd-analyze plot > filename.svg:通過執(zhí)行該命令,可以在執(zhí)行目錄下生成一個filename.svg的文件,該文件建議使用瀏覽器打開:
- 文件中可以清楚的看到服務(wù)單元的啟動順序,如果你多啟動幾次電腦,多生成幾個文件進行服務(wù)啟動順序?qū)Ρ?#xff0c;你可以清晰的理解文章開頭強調(diào)的systemd啟動服務(wù)是亂序并行的說法。
- systemd-analyze critical-chain:顯示瀑布狀的啟動過程流,這個命令可以看個大概;
- 在“@”字符之后打印單位處于活動狀態(tài)或啟動后的時間。
- 在“+”字符之后,在“+”字符之后打印單位開始的時間。
- systemd-analyze critical-chain atd.service:顯示指定服務(wù)的啟動流,具體看哪個服務(wù)就寫哪個服務(wù)。
三、定制服務(wù)
前面介紹這么多都是紙上談兵而已,需要真正使用上systemd的各種功能,首先要學(xué)會怎么讀服務(wù)文件;
3.1 讀懂服務(wù)文件
我們找一個.service文件去讀,可以通過systemctl cat命令查看服務(wù)的配置文件,也可以直接到前面說的三個目錄下去直接打開,這里打開rc-local.service來講解:
# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version.# This unit gets pulled automatically into multi-user.target by # systemd-rc-local-generator if /etc/rc.local is executable. [Unit] Description=/etc/rc.local Compatibility ConditionFileIsExecutable=/etc/rc.local After=network.target[Service] Type=forking ExecStart=/etc/rc.local start TimeoutSec=0 RemainAfterExit=yes一個服務(wù)怎么啟動、什么時候啟動、啟動什么東西都是由他的配置文件決定的,如上所示,rc-local.service服務(wù)主要是執(zhí)行/etc/rc.local的內(nèi)容,這個關(guān)聯(lián)到linux啟動項的內(nèi)容,這里不展開說明,后續(xù)會補充。
rc-local.service服務(wù)的結(jié)構(gòu)分為兩個板塊,有[Unit]和[Service],其實還有另外一個[Install],后續(xù)會分別進行說明:
3.1.1 [Uint]:啟動順序和依賴關(guān)系
- Unit區(qū)塊的Description字段給出當(dāng)前服務(wù)的簡單描述,Documentation字段給出文檔位置;
- After字段:表示如果network.target或sshd-keygen.service需要啟動,那么sshd.service應(yīng)該在它們之后啟動;
- Before字段,定義sshd.service應(yīng)該在哪些服務(wù)之前啟動;
- After和Before字段只涉及啟動順序,不涉及依賴關(guān)系;
- Wants字段:表示sshd.service與sshd-keygen.service之間存在"弱依賴"關(guān)系,即如果"sshd-keygen.service"啟動失敗或停止運行,不影響sshd.service繼續(xù)執(zhí)行;
- Requires字段則表示"強依賴"關(guān)系,即如果該服務(wù)啟動失敗或異常退出,那么sshd.service也必須退出;
- Wants字段與Requires字段只涉及依賴關(guān)系,與啟動順序無關(guān),默認情況下是同時啟動的。
- ConditionFileIsExecutable=/etc/rc.local指定執(zhí)行文件;
3.1.2 [Service]:啟動行為,定義如何啟動當(dāng)前服務(wù)
- EnvironmentFile字段:指定當(dāng)前服務(wù)的環(huán)境參數(shù)文件。該文件內(nèi)部的key=value鍵值對,可以用$key的形式,在當(dāng)前配置文件中獲取;
- ExecStart字段:定義啟動進程時執(zhí)行的命令;
- ExecReload字段:重啟服務(wù)時執(zhí)行的命令;
- ExecStop字段:停止服務(wù)時執(zhí)行的命令;
- ExecStartPre字段:啟動服務(wù)之前執(zhí)行的命令;
- ExecStartPost字段:啟動服務(wù)之后執(zhí)行的命令;
- ExecStopPost字段:停止服務(wù)之后執(zhí)行的命令;
- Type字段定義啟動類型。它可以設(shè)置的值如下;
- simple(默認值):ExecStart字段啟動的進程為主進程;
- forking:ExecStart字段將以fork()方式啟動,此時父進程將會退出,子進程將成為主進程;
- oneshot:類似于simple,但只執(zhí)行一次,Systemd 會等它執(zhí)行完,才啟動其他服務(wù);
- dbus:類似于simple,但會等待 D-Bus 信號后啟動;
- notify:類似于simple,啟動結(jié)束后會發(fā)出通知信號,然后 Systemd 再啟動其他服務(wù);
- idle:類似于simple,但是要等到其他任務(wù)都執(zhí)行完,才會啟動該服務(wù)。一種使用場合是為讓該服務(wù)的輸出,不與其他服務(wù)的輸出相混合;
- KillMode字段:定義Systemd如何停止sshd服務(wù);
- control-group(默認值):當(dāng)前控制組里面的所有子進程,都會被殺掉;
- process:只殺主進程;
- mixed:主進程將收到SIGTERM信號,子進程收到SIGKILL信號;
- none:沒有進程會被殺掉,只是執(zhí)行服務(wù)的stop命令;
- Restart字段:定義了sshd退出后,Systemd的重啟方式;
- no(默認值):退出后不會重啟;
- on-success:只有正常退出時(退出狀態(tài)碼為0),才會重啟;
- on-failure:非正常退出時(退出狀態(tài)碼非0),包括被信號終止和超時,才會重啟;
- on-abnormal:只有被信號終止和超時,才會重啟;
- on-abort:只有在收到?jīng)]有捕捉到的信號終止時,才會重啟;
- on-watchdog:超時退出,才會重啟;
- always:不管是什么退出原因,總是重啟;
- RestartSec字段:表示 Systemd 重啟服務(wù)之前,需要等待的秒數(shù)。上面的例子設(shè)為等待42秒;
3.1.3 [Install]:定義如何安裝這個配置文件,即怎樣做到開機啟動
- WantedBy字段:表示該服務(wù)所在的 Target;Target的含義是服務(wù)組,表示一組服務(wù)。WantedBy=multi-user.target指的是,sshd 所在的 Target 是multi-user.target;
這個設(shè)置非常重要,因為執(zhí)行systemctl enable sshd.service命令時,sshd.service的一個符號鏈接,就會放在/etc/systemd/system目錄下面的multi-user.target.wants子目錄之中。
分析完之后,回到[rc-local.service源碼]( 3.1 讀懂服務(wù)文件),我們可以清楚的解析出來,該服務(wù)指定的執(zhí)行文件為/etc/rc.local,規(guī)定該服務(wù)在network.target服務(wù)執(zhí)行完成之后再執(zhí)行,并且該服務(wù)類型為forking,該服務(wù)啟動時執(zhí)行的命令為/etc/rc.local start
3.2 target 服務(wù)組
在查看/etc/systemd/system和/lib/systemd/system下面的服務(wù)文件時,仔細的話可以看到分別有.service和.target以及.wants三種不同后綴的文件及文件夾。
像[3.1.3 [Install]]( 3.1.3 [Install]:定義如何安裝這個配置文件,即怎樣做到開機啟動)中描述的WantedBy字段:表示該服務(wù)所在的 target;該target指的就是.target,每個.target指的都是一個獨立的服務(wù)組,表示一組服務(wù)。
我們打開ssh.service可以看到WantedBy=multi-user.target,指定了ssh.service所在的服務(wù)組為multi-user.target多用戶服務(wù)組。
[Unit] Description=OpenBSD Secure Shell server After=network.target auditd.service ConditionPathExists=!/etc/ssh/sshd_not_to_be_run[Service] EnvironmentFile=-/etc/default/ssh ExecStartPre=/usr/sbin/sshd -t ExecStart=/usr/sbin/sshd -D $SSHD_OPTS ExecReload=/usr/sbin/sshd -t ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure RestartPreventExitStatus=255 Type=notify[Install] WantedBy=multi-user.target Alias=sshd.service當(dāng)我們執(zhí)行systemctl enable sshd.service命令時,sshd.service的一個符號鏈接,就會放在/etc/systemd/system目錄下面的multi-user.target.wants子目錄之中;這里講解了(1.2 單元的管理)中的疑點。
我們可以通過執(zhí)行systemctl list-dependencies multi-user.target來查看當(dāng)前multi-user.target服務(wù)組下的服務(wù),
systemd的target
| runlevel0.target, poweroff.target | 中斷系統(tǒng)(halt) |
| runlevel1.target, rescue.target | 單用戶模式 |
| runlevel2.target, runlevel4.target, multi-user.target | 用戶自定義啟動級別,通常識別為級別3。 |
| runlevel3.target, multi-user.target | 多用戶,無圖形界面。用戶可以通過終端或網(wǎng)絡(luò)登錄。 |
| runlevel5.target, graphical.target | 多用戶,圖形界面。繼承級別3的服務(wù),并啟動圖形界面服務(wù)。 |
| runlevel6.target, reboot.target | 重啟 |
| emergency.target | 急救模式(Emergency shell) |
Systemd默認的啟動Target為multi-user.target,我們也可以通過指令去查看當(dāng)前啟動的target
$systemctl get-default multi-user.target一般來說,常用的 Target 有兩個:一個是multi-user.target,表示多用戶命令行狀態(tài);另一個是graphical.target,表示圖形用戶狀態(tài),它依賴于multi-user.target;
3.2.1 target 的配置文件
打開multi-user.target文件,如下:
# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version.[Unit] Description=Multi-User System Documentation=man:systemd.special(7) Requires=basic.target Conflicts=rescue.service rescue.target After=basic.target rescue.service rescue.target AllowIsolate=yes可以看到target 配置文件里面沒有啟動命令,主要字段如下:
- Requires字段:要求basic.target一起運行。
- Conflicts字段:沖突字段。如果rescue.service或rescue.target正在運行,multi-user.target就不能運行,反之亦然。
- After:表示multi-user.target在basic.target 、 rescue.service、 rescue.target之后啟動,如果它們有啟動的話。
- AllowIsolate:允許使用systemctl isolate命令切換到multi-user.target。
修改配置文件以后,需要重新加載配置文件,然后重新啟動相關(guān)服務(wù)。
# 重新加載配置文件 $ sudo systemctl daemon-reload# 重啟相關(guān)服務(wù) $ sudo systemctl restart foobar參考 > 阮一峰Systemd 入門教程
總結(jié)
以上是生活随笔為你收集整理的systemd服务分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: systemd 简介
- 下一篇: doodoo.js发布1.1.0 --