CentOS 7 使用 Systemd 替換了SysV
Ubuntu 從 15.04 開始使用 Systemd
Systemd 是 Linux 系統(tǒng)工具,用來啟動守護(hù)進(jìn)程,已成為大多數(shù)發(fā)行版的標(biāo)準(zhǔn)配置
優(yōu)點(diǎn):
按需啟動進(jìn)程,減少系統(tǒng)資源消耗
并行啟動進(jìn)程,提高系統(tǒng)啟動速度
在 SysV-init 時(shí)代,將每個(gè)服務(wù)項(xiàng)目編號,依次執(zhí)行啟動腳本。Ubuntu 的 Upstart 解決了沒有直接依賴的啟動之間的并行啟動。而 Systemd 通過 Socket 緩存、DBus 緩存和建立臨時(shí)掛載點(diǎn)等方法進(jìn)一步解決了啟動進(jìn)程之間的依賴,做到了所有系統(tǒng)服務(wù)并發(fā)啟動。對于用戶自定義的服務(wù),Systemd 允許配置其啟動依賴項(xiàng)目,從而確保服務(wù)按必要的順序運(yùn)行。
SystemV Upstart 參考上一篇博文:Linux 初始化系統(tǒng) SystemV Upstart
使用 CGroup 監(jiān)視和管理進(jìn)程的生命周期
CGroup 提供了類似文件系統(tǒng)的接口,當(dāng)進(jìn)程創(chuàng)建子進(jìn)程時(shí),子進(jìn)程會繼承父進(jìn)程的 CGroup。因此無論服務(wù)如何啟動新的子進(jìn)程,所有的這些相關(guān)進(jìn)程都會屬于同一個(gè) CGroup
在 Systemd 之前的主流應(yīng)用管理服務(wù)都是使用 進(jìn)程樹 來跟蹤應(yīng)用的繼承關(guān)系的,而進(jìn)程的父子關(guān)系很容易通過 兩次 fork 的方法脫離。
而 Systemd 則提供通過 CGroup 跟蹤進(jìn)程關(guān)系,引補(bǔ)了這個(gè)缺漏。通過 CGroup 不僅能夠?qū)崿F(xiàn)服務(wù)之間訪問隔離,限制特定應(yīng)用程序?qū)ο到y(tǒng)資源的訪問配額,還能更精確地管理服務(wù)的生命周期
統(tǒng)一管理服務(wù)日志
支持快照和系統(tǒng)恢復(fù)
缺點(diǎn):
Systemd 可以管理所有系統(tǒng)資源:
例如,MySQL服務(wù)被 Systemd 視為一個(gè) Unit,使用一個(gè) mysql.service 作為啟動配置文件
單元文件中包含該單元的描述、屬性、啟動命令等
Systemd 將系統(tǒng)資源劃分為12類,對應(yīng)12種類型的單元文件
系統(tǒng)資源類型 | 單元文件擴(kuò)展名 | 單元文件描述 |
---|---|---|
Service | .service | 封裝守護(hù)進(jìn)程的啟動、停止、重啟和重載操作,是最常見的一種 Unit 文件 |
Target | .target | 定義 target 信息及依賴關(guān)系,一般僅包含 Unit 段 |
Device | .device | 對于 /dev 目錄下的硬件設(shè)備,主要用于定義設(shè)備之間的依賴關(guān)系 |
Mount | .mount | 定義文件系統(tǒng)的掛載點(diǎn),可以替代過去的 /etc/fstab 配置文件 |
Automount | .automount | 用于控制自動掛載文件系統(tǒng),相當(dāng)于 SysV-init 的 autofs 服務(wù) |
Path | .path | 用于監(jiān)控指定目錄或文件的變化,并觸發(fā)其它 Unit 運(yùn)行 |
Scope | .scope | 這種 Unit 文件不是用戶創(chuàng)建的,而是 Systemd 運(yùn)行時(shí)產(chǎn)生的,描述一些系統(tǒng)服務(wù)的分組信息 |
Slice | .slice | 用于表示一個(gè) CGroup 的樹 |
Snapshot | .snapshot | 用于表示一個(gè)由 systemctl snapshot 命令創(chuàng)建的 Systemd Units 運(yùn)行狀態(tài)快照,可以切回某個(gè)快照 |
Socket | .socket | 監(jiān)控來自于系統(tǒng)或網(wǎng)絡(luò)的數(shù)據(jù)消息 |
Swap | .swap | 定義一個(gè)用戶做虛擬內(nèi)存的交換分區(qū) |
Timer | .timer | 用于配置在特定時(shí)間觸發(fā)的任務(wù),替代了 Crontab 的功能 |
對于操作單元文件的命令,如果缺省擴(kuò)展名,則默認(rèn)
.service
擴(kuò)展名而操作 target 的命令,例如 isolate,則默認(rèn)
.target
擴(kuò)展名
單元文件的語法來源于 XDG桌面入口配置文件.desktop
文件
Unit 文件可以分為三個(gè)配置區(qū)段:
單元文件中的區(qū)段名和字段名大小寫敏感
每個(gè)區(qū)段內(nèi)都是一些等號連接的鍵值對(鍵值對的等號兩側(cè)不能有空格)
主要字段如下:
Description
:當(dāng)前服務(wù)的簡單描述
Documentation
:文檔地址,可以是一個(gè)或多個(gè)文檔的 URL 路徑
【依賴關(guān)系】
Requires
:與其它 Unit 的強(qiáng)依賴關(guān)系,如果其中任意一個(gè) Unit 啟動失敗或異常退出,當(dāng)前 Unit 也會被退出
Wants
:與其它 Unit 的弱依賴關(guān)系,如果其中任意一個(gè) Unit 啟動失敗或異常退出,不影響當(dāng)前 Unit 繼續(xù)執(zhí)行
只涉及依賴關(guān)系,默認(rèn)情況下 兩個(gè) Unit 同時(shí)啟動
【啟動順序】
After
:該字段指定的 Unit 全部啟動完成以后,才會啟動當(dāng)前 Unit
Before
:該字段指定的 Unit 必須在當(dāng)前 Unit 啟動完成之后再啟動
只涉及啟動順序,不影響啟動結(jié)果和運(yùn)行情況
Binds To
:與 Requires 相似,該字段指定的 Unit 如果退出,會導(dǎo)致當(dāng)前 Unit 停止運(yùn)行
Part Of
:一個(gè) Bind To 作用的子集,僅在列出的 Unit 失敗或重啟時(shí),終止或重啟當(dāng)前 Unit,而不會隨列出Unit 的啟動而啟動
http://manpages.ubuntu.com/manpages/bionic/en/man5/systemd.unit.5.html
主要字段如下:
WantedBy
:它的值是一個(gè)或多個(gè) target,執(zhí)行enable命令時(shí),符號鏈接會放入/etc/systemd/system
目錄下以 target 名 + .wants
后綴構(gòu)成的子目錄中RequiredBy
:它的值是一個(gè)或多個(gè) target,執(zhí)行enable命令時(shí),符號鏈接會放入/etc/systemd/system
目錄下以 target 名 + .required
后綴構(gòu)成的子目錄中Alias
:當(dāng)前 Unit 可用于啟動的別名Also
:當(dāng)前 Unit 被 enable/disable 時(shí),會被同時(shí)操作的其他 Unithttp://manpages.ubuntu.com/manpages/bionic/en/man5/systemd.unit.5.html
主要字段如下:
【啟動類型】
Type
:定義啟動時(shí)的進(jìn)程行為。它有以下幾種值。Type=simple
:默認(rèn)值,ExecStart
字段啟動的進(jìn)程為主進(jìn)程Type=forking
:ExecStart
字段將以fork()
方式從父進(jìn)程創(chuàng)建子進(jìn)程啟動,創(chuàng)建后父進(jìn)程會立即退出,子進(jìn)程成為主進(jìn)程。PIDFile
字段,以便 Systemd 能夠跟蹤服務(wù)的主進(jìn)程Type=oneshot
:只執(zhí)行一次,Systemd 會等當(dāng)前服務(wù)退出,再繼續(xù)往下執(zhí)行RemainAfterExit=yes
字段,使得 Systemd 在服務(wù)進(jìn)程退出之后仍然認(rèn)為服務(wù)處于激活狀態(tài)Type=dbus
:當(dāng)前服務(wù)通過 D-Bus 信號啟動。當(dāng)指定的 BusName 出現(xiàn)在 DBus 系統(tǒng)總線上時(shí),Systemd認(rèn)為服務(wù)就緒Type=notify
:當(dāng)前服務(wù)啟動完畢會發(fā)出通知信號,通知 Systemd,然后 Systemd 再啟動其他服務(wù)Type=idle
:Systemd 會等到其他任務(wù)都執(zhí)行完,才會啟動該服務(wù)。【啟動行為】
ExecStart
:啟動當(dāng)前服務(wù)的命令
ExecStart=/bin/echo execstart1ExecStart=ExecStart=/bin/echo execstart2
順序執(zhí)行設(shè)定的命令,把字段置空,表示清除之前的值
ExecStartPre
:啟動當(dāng)前服務(wù)之前執(zhí)行的命令
ExecStartPost
:啟動當(dāng)前服務(wù)之后執(zhí)行的命令
ExecReload
:重啟當(dāng)前服務(wù)時(shí)執(zhí)行的命令
ExecStop
:停止當(dāng)前服務(wù)時(shí)執(zhí)行的命令
ExecStopPost
:停止當(dāng)前服務(wù)之后執(zhí)行的命令
RemainAfterExit
:當(dāng)前服務(wù)的所有進(jìn)程都退出的時(shí)候,Systemd 仍認(rèn)為該服務(wù)是激活狀態(tài)
TimeoutSec
:定義 Systemd 停止當(dāng)前服務(wù)之前等待的秒數(shù)
注:所有的啟動設(shè)置之前,都可以加上一個(gè)連詞號(
-
),表示"抑制錯(cuò)誤",即發(fā)生錯(cuò)誤的時(shí)候,不影響其他命令的執(zhí)行。比如,EnvironmentFile=-/etc/sysconfig/sshd
(注意等號后面的那個(gè)連詞號),就表示即使/etc/sysconfig/sshd
文件不存在,也不會拋出錯(cuò)誤。
【重啟行為】
RestartSec
:Systemd 重啟當(dāng)前服務(wù)間隔的秒數(shù)KillMode
:定義 Systemd 如何停止服務(wù),可能的值包括:Restart
:定義何種情況 Systemd 會自動重啟當(dāng)前服務(wù),可能的值包括:【上下文】
PIDFile
:指向當(dāng)前服務(wù) PID file 的絕對路徑。
User
:指定運(yùn)行服務(wù)的用戶
Group
:指定運(yùn)行服務(wù)的用戶組
EnvironmentFile
:指定當(dāng)前服務(wù)的環(huán)境參數(shù)文件。該文件內(nèi)部的key=value
鍵值對,可以用$key
的形式,在當(dāng)前配置文件中獲取
啟動
sshd
,執(zhí)行的命令是/usr/sbin/sshd -D $OPTIONS
,其中的變量$OPTIONS
就來自EnvironmentFile
字段指定的環(huán)境參數(shù)文件。
http://manpages.ubuntu.com/manpages/bionic/en/man5/systemd.service.5.html
在 Unit 文件中,有時(shí)會需要使用到一些與運(yùn)行環(huán)境有關(guān)的信息,例如節(jié)點(diǎn) ID、運(yùn)行服務(wù)的用戶等。這些信息可以使用占位符來表示,然后在實(shí)際運(yùn)行中動態(tài)地替換為實(shí)際的值。
詳細(xì)了解見 https://cloud.tencent.com/developer/article/1516125
在現(xiàn)實(shí)中,往往有一些應(yīng)用需要被復(fù)制多份運(yùn)行,就會用到模板文件
模板文件的寫法與普通單元文件基本相同,只是模板文件名是以 @ 符號結(jié)尾。例如:apache@.service
通過模板文件啟動服務(wù)實(shí)例時(shí),需要在其文件名的 @ 字符后面附加一個(gè)用于區(qū)分服務(wù)實(shí)例的參數(shù)字符串,通常這個(gè)參數(shù)是用于監(jiān)控的端口號或控制臺 TTY 編譯號
systemctl start apache@8080.service
Systemd 在運(yùn)行服務(wù)時(shí),首先尋找跟單元名完全匹配的單元文件,如果沒有找到,才會嘗試選擇匹配模板
例如上面的命令,System 首先會在約定的目錄下尋找名為 apache@8080.service 的單元文件,如果沒有找到,而文件名中包含 @ 字符,它就會嘗試去掉后綴參數(shù)匹配模板文件。對于 apache@8080.service,Systemd 會找到 apache@.service 模板文件,并通過這個(gè)模板文件將服務(wù)實(shí)例化。
詳細(xì)了解見 https://cloud.tencent.com/developer/article/1516125
systemctl list-unit-files
將會列出文件的 state,包括 static, enabled, disabled, masked, indirect
masked
service軟鏈接到/dev/null
該單元文件被禁止建立啟動鏈接
static
該單元文件沒有[Install]
部分(無法執(zhí)行),只能作為其他配置文件的依賴
enabled
已建立啟動鏈接
disabled
沒建立啟動鏈接
關(guān)掉觸摸板配置文件
Unit]Description=Switch-off Touchpad[Service]Type=oneshotExecStart=/usr/bin/touchpad-off startExecStop=/usr/bin/touchpad-off stopRemainAfterExit=yes[Install]WantedBy=multi-user.target
RemainAfterExit
字段設(shè)為yes
,表示進(jìn)程退出以后,服務(wù)仍然保持執(zhí)行。這樣的話,一旦使用systemctl stop
命令停止服務(wù),ExecStop
指定的命令就會執(zhí)行,從而重新開啟觸摸板systemd-analyze
Analyze and debug system manager, If no command is passed, Systemd-analyze time is implied
https://www.freedesktop.org/software/systemd/man/systemd-analyze.html
systemd-analyze time
查看初始化耗時(shí)
systemd-analyze blame
打印所有運(yùn)行單元,按它們初始化的時(shí)間排序。此信息可用于優(yōu)化啟動時(shí)間。注意,輸出可能具有誤導(dǎo)性,因?yàn)橐粋€(gè)服務(wù)的初始化可能非常緩慢,因?yàn)樗却硪粋€(gè)服務(wù)的初始化完成
systemd-run
將一個(gè)指定的服務(wù)變成后臺服務(wù)
未測試
參考 https://www.freedesktop.org/software/systemd/man/systemd-run.html
systemctl
是 Systemd 的主命令,用于管理系統(tǒng)
動作 | SysV Init 指令 | Systemd 指令 |
---|---|---|
啟動某服務(wù) | service httpd start | systemctl start httpd |
停止某服務(wù) | service httpd stop | systemctl stop httpd |
重啟某服務(wù) | service httpd restart | systemctl restart httpd |
檢查服務(wù)狀態(tài) | service httpd status | systemctl status httpd |
刪除某服務(wù) | chkconfig --del httpd | 停掉應(yīng)用,刪除其配置文件 |
使服務(wù)開機(jī)自啟動 | chkconfig --level 5 httpd on | systemctl enable httpd |
使服務(wù)開機(jī)不自啟動 | chkconfig --level 5 httpd off | systemctl disable httpd |
查詢服務(wù)是否開機(jī)自啟 | chkconfig --list | grep httpd | systemctl is-enabled httpd |
加入自定義服務(wù) | chkconfig --add test | systemctl load test |
顯示所有已啟動的服務(wù) | chkconfig --list | systemctl list-unit-files | grep enabled |
--all
顯示加載到內(nèi)存的所有單元
--type
-t
--type=
顯示指定類型(12種類型)的單元
--state
--state=
顯示指定狀態(tài)的單元或單元文件
單元狀態(tài)
輸入
systemctl list-units --state
按Tab
鍵,顯示所有可用的值單元文件狀態(tài)
另外還可以用 enabled static disabled 等
systemctl list-unit-files
顯示的狀態(tài)
--failed
--state=failed
顯示加載失敗的單元
systemctl --failed
--version
打印 Systemd 版本
lfp@legion:/lib/systemd/system$ systemctl --versionSystemd 237+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD -IDN2 +IDN -PCRE2 default-hierarchy=hybrid
我的理解
- systemd 對單元的管理,不涉及單元文件自身屬性和內(nèi)容
list-units
相當(dāng)于systemctl
列出當(dāng)前已加載的單元(內(nèi)存)
默認(rèn)情況下僅顯示處于激活狀態(tài)(正在運(yùn)行)的單元
UNIT 單元名
LOAD 加載狀態(tài)
ACTIVE SUB 執(zhí)行狀態(tài)(大狀態(tài) 子狀態(tài))
DESCRIPTION 描述
start
啟動單元
systemctl start mysql.service
stop
停止單元
systemctl stop mysql.service
kill
殺掉單元進(jìn)程
systemctl kill mysql.service
reload
不終止單元,重新加載 針對該單元的 運(yùn)行配置文件,而不是 針對 systemd的 該單元的啟動配置文件
例如啟動 MySQL 服務(wù),reload 可以在不停止服務(wù)的情況下重載 MySQL 的配置文件
my.cnf
restart
重啟單元
該單元在重啟之前擁有的資源不會被完全清空,比如文件描述符存儲設(shè)施
systemctl reload mysql.service
status
status [unit | PID]
顯示單元或進(jìn)程所屬單元的運(yùn)行信息
systemctl status mysql.service
Loaded
行:配置文件的位置,是否設(shè)為開機(jī)啟動
Active
行:表示正在運(yùn)行
Main PID
行:主進(jìn)程ID
CGroup
塊:應(yīng)用的所有子進(jìn)程日志塊:應(yīng)用的日志
is-active
判斷指定的單元是否處于激活狀態(tài)
# 默認(rèn)會打印當(dāng)前單元的狀態(tài),可以通過 --quiet 參數(shù)取消打印lfp@legion:~$ systemctl is-active mysqlactive
is-failed
判斷指定的單元是否處于啟動失敗狀態(tài)
lfp@legion:~$ systemctl is-failed mysqlactive
list-dependencies
查看單元之間的依賴關(guān)系
systemctl list-dependencies graphical.target systemctl list-dependencies mysql.service
show
show --property= Unit
?=> show -p Unit
顯示單元所有底層參數(shù)
lfp@legion:~$ systemctl show -p MainPID mysqlMainPID=1061
set-property
在單元啟動的時(shí)候設(shè)置運(yùn)行時(shí)的某個(gè)屬性,立即生效,并保存在磁盤中作為啟動配置
如果添加了--runtime
則重啟后失效
并非所有的屬性都可以設(shè)置,只是 systemd.resource-control 包含的屬性
isolate
切換到某個(gè) target(系統(tǒng)狀態(tài)),立即停止該 target 未包含的單元進(jìn)程。也可以理解為切換 runlevel
如果沒有指定擴(kuò)展名,則默認(rèn).target
只有當(dāng).target單元文件中的AllowIsolate=yes
時(shí),才能使用 isolate 切換;也可以用IgnoreOnIsolate=yes
字段來拒絕使用 isolate 切換
systemctl isolate multi-user.target
cat
顯示單元配置文件的備份文件,包括插入式配置drop-ins
,可以完整的看到單元服務(wù)的配置。注意這里打印的依據(jù)是磁盤的上內(nèi)容,如果用戶修改了配置文件(磁盤已修改)但是未執(zhí)行daemon-reload
命令(內(nèi)存中未更新),那么該命令顯示的配置和實(shí)際執(zhí)行情況有出入
lfp@legion:~$ systemctl cat mysql.service # /lib/systemd/system/mysql.service# MySQL Systemd service file[Unit]Description=MySQL Community Server...[Install]WantedBy=multi-user.target[Service]Type=forking...# 這段就顯示的是 插入式配置 drop-in 的內(nèi)容# /etc/systemd/system/mysql.service.d/mysql.conf# MySQL Systemd service file[Unit]# Description=MySQL Community Server conf[Service]# ExecStartPost=/home/lfp/bin/espeak.sh
我的理解
- systemd 對單元文件自身屬性和內(nèi)容的管理
list-unit-files
列出所有已安裝的單元文件和它們的啟用狀態(tài)
和
list-units
的區(qū)別是
- list-units 僅顯示當(dāng)前已加載到內(nèi)存中的單元
- list-unit-files 會讀取單元文件內(nèi)容,列出所有單元,包括存在于硬盤未加載進(jìn)內(nèi)存的單元
實(shí)際測試結(jié)果:
systemctl list-unit-files 顯示“348 Unit files listed”
systemctl list-units --all 顯示“405 loaded units listed”
systemctl list-units 顯示 “232 loaded units listed”
enable
使某個(gè)單元開機(jī)自啟動
這會根據(jù)單元文件內(nèi)容中的[Install]
指定的 target 組,創(chuàng)建一個(gè)軟鏈接
lfp@legion:/etc/systemd/system$ vim v2rayL.service# 文件內(nèi)容 [Install] 段......[Install]WantedBy=multi-user.target......lfp@legion:/etc/systemd/system$ systemctl is-enabled v2rayL.service disabledlfp@legion:/etc/systemd/system$ systemctl enable v2rayL.service # 根據(jù) [Install] 段指定的組,添加軟鏈接Created symlink /etc/systemd/system/multi-user.target.wants/v2rayL.service → /etc/systemd/system/v2rayL.service.lfp@legion:/etc/systemd/system$ systemctl is-enabled v2rayL.service enabled
disable
取消某個(gè)單元開機(jī)自啟動設(shè)置,刪除軟鏈接
這會刪除所有指向該單元文件的軟鏈接,不僅僅是 enable 操作創(chuàng)建的
reenable
disable 和 enable 的結(jié)合,根據(jù)單元文件內(nèi)容中的 [Install] 段,重置軟鏈接
is-enabled
檢查某個(gè)單元是否是開機(jī)自啟動的(建立的啟動鏈接)
lfp@legion:~$ systemctl is-enabled mysqlenabled
get-default
獲取默認(rèn)啟動 target,default-target 是指向該 target 的軟鏈接
set-default
設(shè)置默認(rèn)啟動 target,同時(shí)修改 default-target 指向設(shè)定的 target
systemctl set-default multi-user.target
daemon-reload
重新加載所有的單元文件和依賴關(guān)系
對單元文件有修改的時(shí)候,需要執(zhí)行該命令重新加載文件內(nèi)容
reboot
systemctl reboot
重啟系統(tǒng)(異步操作)
it will return after the reboot operation is enqueued, without waiting for it to complete
poweroff
關(guān)閉系統(tǒng),切斷電源(異步操作)
halt
僅CPU停止工作,其他硬件仍處于開機(jī)狀態(tài)(異步操作)
suspend
暫停系統(tǒng)(異步操作)
將觸發(fā)執(zhí)行suspend.target
hibernate
讓系統(tǒng)進(jìn)入冬眠狀態(tài)(異步操作)
將觸發(fā)執(zhí)行hibernate.target
/run/systemd/system/
單元(服務(wù))運(yùn)行時(shí)生成的配置文件所在目錄/etc/systemd/system/
系統(tǒng)或用戶自定義的配置文件,初始化過程中Systemd
只執(zhí)行/etc/systemd/system
目錄里面的配置文件
/lib/systemd/system/
軟件安裝時(shí)添加的配置文件,類似于 /etc/init.d/
對于支持 Systemd 的程序,安裝的時(shí)候,會自動的在 /lib/systemd/system
目錄添加一個(gè)配置文件
其他目錄都是軟鏈接
/etc/systemd/system/default.target
Systemd 執(zhí)行的第一個(gè)單元文件,符號鏈接到默認(rèn)啟動 target 對應(yīng)的 .target
單元文件
SysV 的啟動腳本放在/etc/init.d
目錄下
Systemd 的單元文件放在/etc/systemd/system
和 /lib/systemd/system
目錄下
當(dāng)一個(gè)程序在3個(gè)目錄下都存在啟動方式時(shí),優(yōu)先級是/etc/systemd/system --> /lib/systemd/system --> /etc/init.d
lfp@legion:/etc/init.d$ ll-rwxr-xr-x 1 root root 5650 5月 19 22:09 mysql*lfp@legion:/etc/systemd/system$ ll-rw-r--r-- 1 root root 511 5月 20 01:42 mysql.servicelfp@legion:/lib/systemd/system$ ll-rw-r--r-- 1 root root 499 5月 20 01:20 mysql.service
/etc/systemd/system
里面的同名service會覆蓋/lib/systemd/system
里面的
注意查看文件信息,該同名文件不能是指向 /lib/systemd/system 的軟鏈接
軟鏈接不會覆蓋而會同步
如果某個(gè)程序不存在Systemd 單元文件,那么會執(zhí)行/etc/init.d
里面的啟動腳本
根據(jù)啟動過程,
/etc/systemd/system/multi-user.target.wants/
目錄下是很多指向/lib/systemd/system/
目錄的軟鏈接,所以兩個(gè)目錄下的單元文件會互相同步。如果
/etc/systemd/system/
和/etc/systemd/system/multi-user.target.wants/
同時(shí)存在單元文件,測試發(fā)現(xiàn),不管是手動啟動還是開機(jī)自啟動,使用的都是/etc/systemd/system/
目錄下的service單元文件
/etc/init.d
目錄下的腳本mysql 修改 mysql.service
為mysql.service.bak
然后通過service mysql restart
啟動/etc/init.d/mysql
腳本
下面是啟動后的一些信息
注:在恢復(fù)
mysql.service
之前,需要先通過service mysql stop
利用/etc/init.d/mysql
腳本中的stop
結(jié)束上面的進(jìn)程,否則一旦恢復(fù),service mysql stop
執(zhí)行的操作就不是/etc/init.d/mysql
腳本中的stop
,無法結(jié)束上面的進(jìn)程,出現(xiàn)命令無法正常執(zhí)行的情況
結(jié)束上面的進(jìn)程,恢復(fù)mysql.service
,重新啟動
/etc/systemd/system
覆蓋測試未修改前,查看MySQL的狀態(tài)
lfp@legion:~$ service mysql status● mysql.service - MySQL Community Server# 可以發(fā)現(xiàn)這里的 mysql.service 是在 /lib/systemd/system 下面 Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: en Active: active (running) since Sat 2020-04-25 18:34:30 CST; 5h 33min ago Main PID: 988 (mysqld) Tasks: 28 (limit: 4915) CGroup: /system.slice/mysql.service └─988 /usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid4月 25 18:34:30 legion Systemd[1]: Starting MySQL Community Server...4月 25 18:34:30 legion Systemd[1]: Started MySQL Community Server.
將 /lib/systemd/system 下面的文件復(fù)制到 /etc/systemd/system/
下面
sudo cp /lib/systemd/system/mysql.service /etc/systemd/system/
修改 mysql.service
sudo vim /etc/systemd/system/mysql.service
?
重啟 mysql.service ,系統(tǒng)提示需要重新加載
lfp@legion:~$ systemctl restart mysql.service Warning: The Unit file, source configuration file or drop-ins of mysql.service changed on disk. Run 'systemctl daemon-reload' to reload units.lfp@legion:~$ systemctl daemon-reload# 重新加載lfp@legion:~$ systemctl restart mysql.service # 重啟lfp@legion:~$ systemctl status mysql.service ● mysql.service - MySQL Community Server hahahaha# 發(fā)現(xiàn)這里是修改之后的,覆蓋了 /lib/systemd/lib 中的# 這里也可以看到加載路徑 Loaded: loaded (/etc/systemd/system/mysql.service; enabled; vendor preset: en Active: active (running) since Sun 【2020-04-26】 00:47:02 CST; 5s ago Process: 21590 ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/m Process: 21581 ExecStartPre=/usr/share/mysql/mysql-Systemd-start pre (code=exi Main PID: 21592 (mysqld) Tasks: 27 (limit: 4915) CGroup: /system.slice/mysql.service └─21592 /usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pi4月 26 00:47:02 legion Systemd[1]: Starting MySQL Community Server hahahaha...4月 26 00:47:02 legion Systemd[1
兩個(gè)含義
系統(tǒng)的某個(gè)狀態(tài)稱為一個(gè) target(類似于"狀態(tài)點(diǎn)")
達(dá)到某個(gè)系統(tǒng)狀態(tài),所需的一個(gè)或多個(gè)資源(Unit)稱為一個(gè) target(一個(gè) Unit 組)
target是一個(gè)抽象的系統(tǒng)資源,不像MySQL有實(shí)體
如果一個(gè)target只包含一個(gè)Unit,那么該 target,沒有對應(yīng)的目錄,指的就是這個(gè) Unit
例如
hibernate.target
只包含systemd-hibernate.service
一個(gè)Unit如果一個(gè)target包含多個(gè)Unit,那么該target,有對應(yīng)的 xxx.target.wants 目錄,指的是目錄里面所有的Unit
例如
multi-user.target
包含位于/etc/systemd/system/multi-user.target.wants
目錄下的多個(gè) Unit
target也是一個(gè) Target 類型的系統(tǒng)資源,有對應(yīng)的單元文件 xxx.target
Systemd 使用 target 來劃分和管理資源(Unit),啟動(激活)某個(gè) xxx.target 單元文件,通過執(zhí)行該 target 包含的 Unit,使系統(tǒng)達(dá)到某種狀態(tài)
對于狀態(tài)點(diǎn)的理解:
例如,執(zhí)行
systemd suspend
命令讓系統(tǒng)暫停,會觸發(fā)啟動suspend.target
,然后執(zhí)行里面的systemd-suspend.service
Unit,使系統(tǒng)達(dá)到一個(gè)暫停的狀態(tài)
傳統(tǒng)的init
啟動模式里面,有 RunLevel 的概念,跟 Target 的作用很類似。不同的是,RunLevel 是互斥的,不可能多個(gè) RunLevel 同時(shí)啟動,但是多個(gè) Target 可以同時(shí)啟動
runlevel是 SysV init 初始化系統(tǒng)中的概念,在Systemd初始化系統(tǒng)中使用的是 Target,他們之間的映射關(guān)系是
Runlevel | Target | 說明 |
---|---|---|
0 | poweroff.target | 關(guān)閉系統(tǒng) |
1 | rescue.target | 維護(hù)模式 |
2,3,4 | multi-user.target | 多用戶,無圖形系統(tǒng)(命令行界面) |
5 | graphical.target | 多用戶,圖形化系統(tǒng)(圖形用戶界面) |
6 | reboot.target | 重啟系統(tǒng) |
讀入 /boot
目錄下的內(nèi)核文件
內(nèi)核文件加載完之后,開始執(zhí)行第一個(gè)程序/sbin/init
初始化進(jìn)程,由 Systemd 初始化系統(tǒng)引導(dǎo),完成相關(guān)的初始化工作
Systemd 執(zhí)行default.target
,獲知設(shè)定的啟動 target
實(shí)際上
default.target
是指向設(shè)定的啟動 target 的軟鏈接
Systemd 執(zhí)行啟動 target 對應(yīng)的單元文件。根據(jù)單元文件中定義的依賴關(guān)系,傳遞控制權(quán),依次執(zhí)行其他 target 單元文件,同時(shí)啟動每個(gè) target 包含的單元
對于圖形化界面,默認(rèn) target 是 graphical,Systemd 執(zhí)行位于
/lib/systemd/system/
目錄下的 graphical.target 單元文件,根據(jù) target 單元文件中定義的依賴關(guān)系,依次啟動其他 target 單元文件以及各個(gè) target 包含的位于/etc/systemd/system/
目錄下的單元例如: graphical.target 的依賴關(guān)系是
[Unit]Description=Graphical InterfaceDocumentation=man:systemd.special(7)Requires=multi-user.target #Wants=display-manager.service #Conflicts=rescue.service rescue.targetAfter=multi-user.target rescue.service rescue.target display-manager.service #AllowIsolate=yes
因此,依次啟動 multi-user.target --> basic.target --> sysinit.target --> local-fs.target -->local-fs-pre.target --> ...
同時(shí)啟動每個(gè) target 包含的位于
/etc/systemd/system/
目錄下的UnitSysV對應(yīng)的 rc5.d --> /etc/init.d 目錄下的指定的腳本就不會在開機(jī)的時(shí)候執(zhí)行了
systemctl get-default
lfp@legion:~$ runlevelN 5lfp@legion:~$ systemctl get-defaultgraphical.target
systemctl set-default [xxx.target]
# Ubuntu18.04# 圖形用戶界面 切換 命令行界面sudo systemctl set-default multi-user.target# 命令行界面 切換 圖形用戶界面 systemctl set-default graphical.target reboot # 命令行界面 想進(jìn)入 圖形用戶界面(僅進(jìn)入一次,重啟系統(tǒng)后仍然會進(jìn)入命令行模式) sudo systemctl start lightdm
直接修改/lib/systemd/system
目錄下的單元文件
如果軟件包更新,修改會被丟棄
將/lib/systemd/system
中的單元文件復(fù)制到/etc/systemd/system/
如果軟件包更新,不會同步更新
在/etc/systemd/system/
中添加配置(推薦)
步驟:
/etc/systemd/system/
目錄下新建<單元名>.d
目錄<單元名>.d
目錄下,新建<單元名>.conf
文件<單元名>.conf
文件中修改配置測試:
創(chuàng)建目錄及文件
# /mysql.service.dlfp@legion:/etc/systemd/system/mysql.service.d$ lsmysql.conf
修改配置
# MySQL Systemd service config file# 不需要所有的組,僅添加需要修改的組及選項(xiàng)[Unit]Description=MySQL Community Server config test[Service]ExecStartPost=/home/lfp/bin/espeak.sh
重啟測試
lfp@legion:/etc/systemd/system/mysql.service.d$ systemctl daemon-reloadlfp@legion:/etc/systemd/system/mysql.service.d$ systemctl restart mysql.servicelfp@legion:/etc/systemd/system/mysql.service.d$ systemctl status mysql.servicelfp@legion:/etc/systemd/system/mysql.service.d$ systemctl status mysql.service# 描述已經(jīng)被修改● mysql.service - MySQL Community Server config test Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled)# 加入了配置文件 Drop-In: /etc/systemd/system/mysql.service.d └─mysql.conf Active: active (running) since Thu 2020-05-21 20:18:02 CST; 12min ago# 新增的動作執(zhí)行成功 Process: 4703 ExecStartPost=/home/lfp/bin/espeak.sh (code=exited, status=0/SUCCESS) Process: 4672 ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid (code=exited, status=0/SUCCESS) Process: 4663 ExecStartPre=/usr/share/mysql/mysql-Systemd-start pre (code=exited, status=0/SUCCESS) Main PID: 4674 (mysqld) Tasks: 27 (limit: 4915) CGroup: /system.slice/mysql.service └─4674 /usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid5月 21 20:18:02 legion espeak.sh[4703]: ALSA lib pcm_route.c:867:(find_matching_chmap) Found no matching channel map
rc.local
文件/lib/systemd/rc.local.service
# 如果存在,就自動添加到 multi-user.target# 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 CompatibilityDocumentation=man:systemd-rc-local-generator(8)ConditionFileIsExecutable=/etc/rc.localAfter=network.target[Service]Type=forkingExecStart=/etc/rc.local startTimeoutSec=0RemainAfterExit=yesGuessMainPID=no
創(chuàng)建 rc.local 文件,賦予可執(zhí)行權(quán)限,即可添加啟動命令
sudo touch /etc/rc.localchmod 755 /etc/rc.locallfp@legion:/etc$ vim rc.local#!/bin/sh -eecho "test rc.local" > /usr/local/rclocal.logecho "rc.local `date +%Y-%m-%d-%H:%M:%S`" >/home/lfp/log/rclocal.logexit 0
hostnamectl status
Show current system hostname and related information
lfp@legion:/lib/systemd/system$ hostnamectl status Static hostname: legion Icon name: computer-laptop Chassis: laptop Machine ID: b28xxxxxxxx2ecafa29e Boot ID: 21xxxxxxxxxxxx1d3a47504d Operating System: Ubuntu 18.04.4 LTS Kernel: Linux 5.3.0-51-generic Architecture: x86-64
Systemd 統(tǒng)一管理所有 Unit 的啟動日志。帶來的好處就是,可以只用journalctl
一個(gè)命令,查看所有日志(內(nèi)核日志和應(yīng)用日志)。
配置文件
/etc/systemd/journald.conf
日志保存目錄
/var/log/journal/
默認(rèn)日志最大限制為所在文件系統(tǒng)容量的 10%,可通過 /etc/systemd/journald.conf
中的 SystemMaxUse 字段來指定
該目錄是 systemd 軟件包的一部分。若被刪除,systemd 不會自動創(chuàng)建它,直到下次升級軟件包時(shí)重建該目錄。如果該目錄缺失,systemd 會將日志記錄寫入 /run/systemd/journal。這意味著,系統(tǒng)重啟后日志將丟失。
journalctl -u [服務(wù)名]
查看指定單元的日志
journalctl -b
http://manpages.ubuntu.com/manpages/bionic/en/man1/systemctl.1.html
http://manpages.ubuntu.com/manpages/bionic/en/man5/systemd.unit.5.html
https://www.cnblogs.com/yingsong/p/6012180.html
https://www.cnblogs.com/sparkdev/p/8472711.html
http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html
http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-part-two.html
https://linoxide.com/linux-how-to/systemd-boot-process/
https://cloud.tencent.com/developer/article/1516125
https://www.cnblogs.com/sparkdev/p/8472711.html
https://www.ibm.com/developerworks/cn/linux/1407_liuming_init3/index.html?ca=drs-