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