systemx
没错,systemd就是强大的服务管理器,是初始化程序(init)和 SystemV 初始化脚本的现代替代者。此外,它还有更多功能。
systemd真的有那么好用吗,让我们深入讨论一下。
Linux操作系统
系统启动过程
BIOS(Basic Input/Output System):
- 计算机的基本
输入/输出系统
,也被称为固件(firmware)
- BIOS提供了与硬件交互的底层软件接口,使操作系统能够与计算机的硬件设备进行通信和控制。
MBR(Master Boot Record):
- 存在于计算机硬盘的特殊扇区,用于存储引导加载程序和磁盘分区表。它位于硬盘的第一个扇区(扇区编号为0),大小为512字节。
MBR还包含了磁盘分区表,记录了硬盘上的分区布局和位置信息。
以下是关于MBR的一些重要信息:
功能:
-
- 启动时加载的引导加载程序(bootloader)的代码。
-
- 引导加载程序负责在计算机启动时从指定的设备(如硬盘、光盘或USB驱动器)读取操作系统的引导扇区。
备注:
- 引导加载程序负责在计算机启动时从指定的设备(如硬盘、光盘或USB驱动器)读取操作系统的引导扇区。
如果想分析该512个字节的内容,可通过以下内容查看信息
dd if=/dev/sda of=mbr.bin bs=512 count=1
od -xa mbr.bin
Sysvinit
/etc/inittab
文件格式:
id:runlevels:action:process
-
id: 登记项标识符,最多为4个字符.用于惟一地标识/etc/inittab文件中的每一个登记项
-
runlevels: 系统运行级别, 用于确定系统进入的预定的运行模式。一般来说,通常会有8种运行模式,即运行模式0~6,S或者s。
- 0:表示关机
- 1:表示单用户模式,在这个模式中,用户登录不需要密码,默认网卡驱动不被加载,一些服务受限
- 2:表示多用户模式,NFS服务不开启
- 3:表示命令行模式
- 4:保留
- 5:表示图形用户模式
- 6:表示重启系统
- S/s:一般用于系统故障后的排错和恢复
-
action: 动作关键字,用于指定init命令或者进程对相应进程(即process域所定义的命令)所实施的动作。
- boot:只有在引导过程中,才执行该进程,但不等待该进程的结束;当该进程死亡时,也不重新启动该进程.
- bootwait:只有在引导过程中,才执行该进程,并等待进程的结束:当该进程死亡时,也不重新启动该进程.实际上,只有在系统被引导后,并从单用户方式进入多用户方式时,这些登记项才被处理;如果系统的默认运行级设置为2(即多用户方式),那么这些登记项在系统引导后将马上被处理.
- initdefault:指定系统的默认运行级.系统启动时,init将首先查找该登记项.如果存在init将据此决定系统最初要进入的运行级.具体来说,init将指定登记项“run_level"字段中的最大数字(即最高运行级)为当前系统的默认运行级;如果该字段为空,那么将其解释为“0123456”,并以“6”作为默认运行级.如果不存在该登记项,那么init将要求用户在系统启动时指定一个最初的运行级.
- off:如果相应的进程正在运行,那么就发出一个警告信号,等待20秒后,再通过杀死信号强行终止该进程.如果相应的进程并不存在那么就忽略该登记项.
- once:启动相应的进程,但不等待该进程结束便继续处理/etc/inittab文件中的下一个登记项;当该进程死亡时,init也不重新启动该进程.注意:在从一个运行级进入另一个运行级时,如果相应的进程仍然在运行,那么init就不重新启动该进程.
- ondemand:与“respawn”的功能完全相同,但只用于运行级为a、b或c的登记项.
- powerfail:只在init接收到电源失败信号时执行相应的进程,但不等待该进程结束.
- powerwait:只在init接收到电源失败信号时执行相应的进程,并在继续对/etc/inittab文件进行任何处理前等待该进程结束.
- respawn:如果相应的进程还不存在,那么init就启动该进程,同时不等待该进程的结束就继续扫描/etc/inittab文件;当该进程死亡时,init将重新启动该进程.如果相应的进程已经存在,那么init将忽略该登记项并继续扫描/etc/inittab文件.
- sysinit:只有在启动或重新启动系统并首先进入单用户时,init才执行这些登记项.而在系统从运行级1-6进入单用户方式时,init并不执行这些登记项."action”字段为“sysinit”的登记项在“run_level”字段不指定任何运行级.
wait:启动进程并等待其结束,然后再处理/etc/inittab文件中的下一个登记项.
Systemd的背景与原因
systemd是目前Linux系统上主要的系统守护进程管理工具
- 背景:
-
串行阻塞的问题:由于init一方面对于进程的管理是串行化的,容易出现阻塞情况,
-
服务的相依性问题: 服务是可能会有相依性的,例如,你要启动网络服务,但是系统没 有网络, 那怎么可能可以唤醒网络服务呢?如果你需要连线到外部取得认证服务器的连 线,但该连线需要另一个A服务的需求,问题是,A服务没有启动, 因此,你的认证服务 就不可能会成功启动的!这就是所谓的服务相依性问题。
init 在管理员自己手动处理这些 服务时,是没有办法协助相依服务的唤醒的!
-
Systemd
Systemd的概念与优势
优势:
- 平行处理所有服务,加速开机流程:on-demand 1启动方式:
旧的 init 启动脚本是串行启动,不相依的服务也是得要等待。但目前我们的硬件主机系统与操作系 统几乎都支持多核心
架构了, 没道理未相依的服务不能同时启动啊!因此引入systemd ,所有服务同时启动,加快系统启动速度!
- 服务相依性的自我检查:
systemd服务相依性的检查,如果 B 服务是 架构在 A 服务上面启动的,系统会自动先启动A 服务
概念
daemon 功能分类
- 服务单元:systemd 旗下管理的服务非常多,systemd 将服务单位 (unit) 区分为 service, socket, target, path,snapshot, timer 等多种不同的类型(type)
- 服务群组
如同 systemV 的 init 里头有个 runlevel 的特色, systemd 亦将许多的功能集合成为一个所谓的 target 项目,这个项目主要在设计操作环 境的创建, 所以是集合了许多的 daemons,亦即是执行某个 target 就是执行好多个 daemon 的意思!
systemd 的配置文件放置目录
- /lib/systemd/system 每个服务最主要的启动脚本设置
- /etc/systemd/system 管理员依据主机系统的需求所创建的执行脚本
注:
执行/etc/systemd/system下的服务优先级高于/lib/systemd/system,但是/etc/systemd/system的服务就是一大堆链接文件,其实都放在/lib/systemd/system,因此如需修改服务,应在/lib/systemd/system下修改
systemd 的 unit 类型分类说明
扩展名 | 类型 |
---|---|
.service | 一般服务类型 (service unit):主要是系统服务,包括服务器本身所需要 的本机服务以及网络服务都是!比较经常被使用到的服务大多是这种类 型! 所以,这也是最常见的类型了! |
.socket | 这种 类型的服务通常在监控讯息传递的插槽档,当有通过此插槽档传递讯息来 说要链接服务时,就依据当时的状态将该用户的要求传送到对应的 daemon,例如创建一个套接字服务,监听连接 |
.target | 执行环境类型 (target unit):其实是一群 unit 的集合,multi-user.target 就是执行一堆其他 .service 或/及 .socket 之类的服务 |
.mount .automount | 文件系统挂载相关的服务 (automount unit / mount unit):例如来自网络 .automount 的自动挂载、NFS 文件系统挂载等与文件系统相关性较高的程序管理。 |
.path | 侦测特定文件或目录类型,如文件路径发生改变,会执行相应的操作 |
.timer | 循环执行的服务 (timer unit):这个东西有点类似 anacrontab 喔!不过 是由 systemd 主动提供的,比 anacrontab 更加有弹性! |
systemctl 管理服务
systemctl [command] [unit]
command 主要有:
- start :立刻启动后面接的 unit
- stop :立刻关闭后面接的 unit
- restart :立刻关闭后启动后面接的 unit,亦即执行 stop 再 start 的意思
- reload :不关闭后面接的 unit 的情况下,重新载入配置文件,让设置生效
- enable :设置下次开机时,后面接的 unit 会被启动
- disable :设置下次开机时,后面接的 unit 不会被启动
- status :目前后面接的这个 unit 的状态,会列出有没有正在执行、开机默认执行否、登录等信息等!
- is-active :目前有没有正在运行中
- is-enable :开机时有没有默认要启用这个 unit
范例一:systemctl status cups.service
● cups.service - CUPS Scheduler
Loaded: loaded (/lib/systemd/system/cups.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2023-07-25 00:00:00 CST; 17h ago
TriggeredBy: ● cups.path
● cups.socket
Docs: man:cupsd(8)
Main PID: 229239 (cupsd)
Tasks: 1 (limit: 9243)
Memory: 1.8M
CGroup: /system.slice/cups.service
└─229239 /usr/sbin/cupsd -l
# 重点在第二、三行喔~
# Loaded:这行在说明,开机的时候这个 unit 会不会启动,enabled 为开机启动,disabled 开机不会启动
# Active:现在这个 unit 的状态是正在执行 (running) 或没有执行 (dead)
# 后面几行则是说明这个 unit 程序的 PID 状态以及最后一行显示这个服务的登录文件信息!
# 登录文件信息格式为:“时间” “讯息发送主机” “哪一个服务的讯息” “实际讯息内容”
# 所以上面的显示讯息是:这个 atd 默认开机就启动,而且现在正在运行的意思!
范例二:systemctl disable cups.service
范例二非常特别!竟然一口气取消掉三个链接文件!也就是说,这三个文件可能是有相依性的问题喔!
范例三: systemctl enable cups.service
范例三可以对比范例二,同时创建三个链接文件,同时可以关注一点,/lib/systemd/system/的的服务会软链接到/etc/systemd/system/,换一句话说,如果想自启动,可以手动软连接。
范例三: systemctl mask cups.service
喔耶~其实这个 mask 注销的动作,只是让启动的脚本变成空的设备而已!
systemctl 观察系统上所有的服务
[root@study ~]# systemctl [command] [--type=TYPE] [--all]
command:
list-units :依据 unit 列出目前有启动的 unit。若加上 --all 才会列出没启动的。
list-unit-files :依据 /usr/lib/systemd/system/ 内的文件,将所有文件列表说明。
--type=TYPE:就是之前提到的 unit type,主要有 service, socket, target 等
范例一:列出系统上面有启动的 unit
systemctrl 或者是 systemctrl list-units -all
范例二:列出系统某种类型的unit
systemctl list-unit-files --type=service
systemctl 管理不同的操作环境 (target unit)
systemctl list-unit-files --type=target
而跟操作界面相关性比 较高的 target 主要有下面几个:
- graphical.target:就是文字加上图形界面,这个项目已经包含了下面的 multi-user.target 项目!
- multi-user.target:纯文本模式!
- rescue.target:在无法使用 root 登陆的情况下,systemd 在开机时会多加一个额外的暂 时系统,与你原本的系统无关。这时你可以取得 root 的权限来维护你的系统。 但是这是 额外系统,因此可能需要动到 chroot 的方式来取得你原有的系统喔!再后续的章节我们 再来谈!
- emergency.target:紧急处理系统的错误,还是需要使用 root 登陆的情况,在无法使用 rescue.target 时,可以尝试使用这种模式!
- shutdown.target:就是关机的流程。
- getty.target:可以设置你需要几个 tty 之类的,如果想要降低 tty 的项目,可以修改这个 东西的配置文件!
范例一:纯文本界面切换到文字加上图形界面
systemctl isolate graphical.target
范例二:文字加上图形界面切换到纯文本界面
systemctl isolate multi-user.target
systemctl 分析各服务之间的相依性
查看服务的依赖例子
systemctl list-dependencies cups.service
systemctl 针对 service 类型的配置文件
下面先看一个例子
分析以上配置文件,可将文件分为三个部分
[Unit]
: unit 本身的说明,以及与其他相依 daemon 的设置,包括在什么服务之后才启动 此 unit 之类的设置值;[Service], [Socket], [Timer], [Mount], [Path]
…:不同的 unit type 就得要使用相对应的设置 项目。我们拿的是 sshd.service 来当范本,所以这边就使用 [Service] 来设置。 这个项目 内主要在规范服务启动的脚本、环境配置文件文件名、重新启动的方式等等。[Install]
:这个项目就是将此 unit 安装到哪个 target 里面去的意思!
每个部份里面还有很多的设置细项,我们使用一个简单的表格来说明每个项目好了!
[Unit]
设置参数 | 参数意义说明 |
---|---|
Description | 输出的此服务的说明 |
Documentation | 提供更新该服务的信息 例如: Documentation=file:/etc/ssh/sshd_config |
After | 说明此 unit 是在哪个 daemon 启动之后才启动的意思 基本上仅是说明服务启动的顺序而已 并没有强制要求里头的服务一定要启动后此 unit 才能启动 |
Before | 与 After 的意义相反,是在什么服务启动前最好启动这个服务的意思,并非强制要求的意思。 |
Requires | 明确的定义此 unit 需要在哪个 daemon 启动后才能够启动!就是设置 相依服务啦!如果在此项设置的前导服务没有启动,那么此 unit 就不 会被启动! |
Wants | 规范的是这个 unit 之后最好还要启动什么服务比较好的意思! 因此,这个 Wants 后面接的服务如 果没有启动,其实不会影响到这个 unit 本身! |
Description | 输出的此服务的说明 |
[Service]
设置参数 | 参数意义说明 |
---|---|
Type | 说明这个 daemon 启动的方式 |
EnvironmentFile | 可以指定启动脚本的环境配置文件! 例如 sshd.service 的配置文件写 入到 /etc/sysconfig/sshd 当中! 你也可以使用 Environment= 后面接 多个不同的 Shell 变量来给予设置! |
ExecStart | 实际执行此 daemon 的指令或脚本程序。 你也可以使用 ExecStartPre (之前) 以及 ExecStartPost (之后) 两个设置项目 来在实际启动服务前,进行额外的指令行为。 但是你得要特别注意的 是,指令串仅接受“指令 参数 参数…”的格式, 不能接受 <, >, >>, & 等特殊字符 ,很多的 bash 语法也不支持喔! 要使用这些特殊 的字符时,最好直接写入到指令脚本里面去!不过,上述的语法也不 是完全不能用,亦即,若要支持比较完整的 bash 语法,那你得要使 用 Type=oneshot 才行喔! 其他的 Type 才不能支持这些字符。 |
ExecStop | 与 systemctl stop 的执行有关,关闭此服务时所进行的指令。 |
ExecReload | 与 systemctl reload 有关的指令行为 |
Restart | 当设置 Restart=1 时,则当此 daemon 服务终止后,会再次的启动此 服务 |
RemainAfterExit | 当设置为 RemainAfterExit=1 时,则当这个 daemon 所属的所有程序 都终止之后,此服务会再尝试启动。这对于 Type=oneshot 的服务很 有帮助! |
TimeoutSec | 若这个服务在启动或者是关闭时,因为某些缘故导致无法顺利“正常 启动或正常结束”的情况下,则我们要等多久才进入“强制结束”的状 态! |
KillMode | 可以是 process, control-group, none 的其中一种,如果是 process 则 daemon 终止时,只会终止主要的程序 (ExecStart 接的后面那串 指令),如果是 control-group 时, 则由此 daemon 所产生的其他 control-group 的程序,也都会被关闭。如果是 none 的话,则没有程 序会被关闭喔! |
RestartSec | 与 Restart 有点相关性,如果这个服务被关闭,然后需要重新启动 时,大概要 sleep 多少时间再重新启动的意思。默认是 100ms (毫 秒)。 |
[Install]
设置参数 | 参数意义说明 |
---|---|
WantedBy | 这个设置后面接的大部分是 *.target unit !意思是,这个 unit 本身是附挂在 哪一个 target unit 下面的!一般来说,大多的服务性质的 unit 都是附挂在 multi-user.target 下面! |
Also | 当目前这个 unit 本身被 enable 时,Also 后面接的 unit 也请 enable 的意 思!也就是具有相依性的服务可以写在这里呢! |
Alias | 进行一个链接的别名的意思!当 systemctl enable 相关的服务时,则此服 务会进行链接文件的创建!以 multi-user.target 为例,这个家伙是用来作为 默认操作环境 default.target 的规划, 因此当你设置用成 default.target 时,这个 /etc/systemd/system/default.target 就会链接到 /usr/lib/systemd/system/multi-user.target 啰! |
systemctl 针对 timer 的配置文件
[Timer]
设置参数 | 参数意义说明 |
---|---|
OnActiveSec | 当 timers.target 启动多久之后才执行这只 unit |
OnBootSec | 当开机完成后多久之后才执行 |
OnStartupSec | 当 systemd 第一次启动之后过多久才执行it |
OnUnitActiveSec | 这个 timer 配置文件所管理的那个 unit 服务在最后一次启动后,隔 多久后再执行一次的意思 |
OnUnitInactiveSec | 这个 timer 配置文件所管理的那个 unit 服务在最后一次停止后,隔 多久再执行一次的意思。 |
OnCalendar | 使用实际时间 (非循环时间) 的方式来启动服务的意思!至于时 间的格式后续再来谈。 |
Unit | 一般来说不太需要设置,因此如同上面刚刚提到的,基本上我们设 置都是 sname.server + sname.timer,那如果你的 sname 并不相 同时,那在 .timer 的文件中, 就得要指定是哪一个 service unit 啰! |
Persistent | 当使用 OnCalendar 的设置时,指定该功能要不要持续进行的意 思。通常是设置为 yes ,比较能够满足类似 anacron 的功能喔! |
下面先看一个例子
- service文件
- timer文件
systemctl start mytest.timer
测试结果
总结:
上图可发现,timer服务配置了10s,可定时启动mytest.service
on-demand:用于描述根据需要提供服务或资源的概念。它指的是按需、随时可用的形式,根据用户的请求或需求,即时提供所需的内容、服务或资源。 ↩︎