systemd入门上手教程

1.简介

systemd即为system daemon,是linux下的一种init软件,由Lennart Poettering带头开发,并在LGPL 2.1及其后续版本许可证下开源发布,开发目标是提供更优秀的框架以表示系统服务间的依赖关系,并依此实现系统初始化时服务的并行启动,同时达到降低Shell的系统开销的效果,最终代替现在常用的System V与BSD风格init程序。

systemd为什么能诞生

采用init进程但是init有两个缺点:

1、串性启动,启动时间长。Init进程是串行启动,只有前一个进程启动完,才会启动下一个进程。(这也是CentOS5的主要特征)

2、启动脚本复杂。Init进程只是执行启动脚本,不管其他事情。脚本需要自己处理各种情况,这使得脚本变得很长而且复杂。

Init:
Centos 5 Sys init 是启动速度最慢的,串行启动过程,无论进程相互之间有无依赖关系。
Centos6 Upstart init 相对启动速度快一点有所改进。有依赖的进程之间依次启动而其他与之没有依赖关系的则并行同步启动。

Centos7 Systemd 与以上都不同。所有进程无论有无依赖关系则都是并行启动(当然很多时候进程没有真正启动而是只有一个信号或者说是标记而已,在真正利用的时候才会真正启动。)

systemd能解决什么?

Systemd为了解决上文的问题而诞生。它的目标是,为系统的启动和管理提供一套完整的解决方案。

根据linux惯例,字母d是守护进程(daemon) 的缩写。Systemd名字的含义就是 守护整个系统。

Centos 7里systemd代替了init,成为了系统的第一个进程。PID为1.其他所有的进程都是它的子进程。

systemd架构图

systemd的结构

Systemd 的优点是功能强大,使用方便,缺点是体系庞大,非常复杂。事实上,现在还有很多人反对使用 Systemd,理由就是它过于复杂,与操作系统的其他部分强耦合,违反的Unix的kiss哲学。

kiss哲学是什么?

(“简单原则”—-尽量用简单的方法解决问题—-是”Unix哲学”的根本原则。这也就是著名的KISS(keep it simple, stupid),意思是”保持简单和笨拙”。)

2.Unit 单元

什么是Unit?

Systemd 可以管理所有系统资源。不同的资源统称为 Unit(单位)

举个例子

系统初始化需要做的事情非常多。需要启动后台服务,比如启动 SSHD 服务;需要做配置工作,比如挂载文件系统。这个过程中的每一步都被 systemd 抽象为一个配置单元,即 unit。可以认为一个服务是一个配置单元;一个挂载点是一个配置单元;一个交换分区的配置是一个配置单元……简单说,单元就是 Systemd 的最小功能单位,是单个进程的描述。一个个小的单元互相调用和依赖,组成一个庞大的任务管理系统,这就是 Systemd 的基本思想。

unit种类

由于 Systemd 要做的事情太多,导致单元有很多不同的种类,大概一共有12种。举例来说,Service 单元负责后台服务,Timer 单元负责定时器,Slice 单元负责资源的分配。


Service unit:系统服务
Target unit:多个 Unit 构成的一个组
Device Unit:硬件设备
Mount Unit:文件系统的挂载点
Automount Unit:自动挂载点
Path Unit:文件或路径
Scope Unit:不是由 Systemd 启动的外部进程
Slice Unit:进程组
Snapshot Unit:Systemd 快照,可以切回某个快照
Socket Unit:进程间通信的 socket
Swap Unit:swap 文件
Timer Unit:定时器

unit依赖

场景1:挂载必须等待挂载点在文件系统中被创建;挂载也必须等待相应的物理设备就绪。

为了解决这类依赖问题,systemd 的配置单元之间可以彼此定义依赖关系,Systemd 用配置单元定义文件中的关键字来描述配置单元之间的依赖关系。比如:unit A 依赖 unit B,可以在 unit B 的定义中用”require A”来表示。这样 systemd 就会保证先启动 A 再启动 B。

场景2: A依赖B,B依赖C,C依赖A, 存在循环依赖。

systemd 将无法启动任意一个服务。此时 systemd 将会尝试解决这个问题,因为配置单元之间的依赖关系有两种:required 是强依赖;want 则是弱依赖,systemd 将去掉 wants 关键字指定的依赖看看是否能打破循环。如果无法修复,systemd 会报错。

unit 的位置 :
Systemd 默认从目录/etc/systemd/system/读取配置文件。但是,里面存放的大部分文件都是符号链接,指向目录/usr/lib/systemd/system/,真正的配置文件存放在那个目录。

unit常用单元管理命令

““

启动单元

$ systemctl start [UnitName]

关闭单元

$ systemctl stop [UnitName]

重启单元

$ systemctl restart [UnitName]

杀死单元进程

$ systemctl kill [UnitName]

查看单元状态

$ systemctl status [UnitName]

开机自动执行该单元

$ systemctl enable [UnitName]

关闭开机自动执行

$ systemctl disable [UnitName]

重新加载一个服务的配置文件

$ systemctl reload [UnitName]

重载所有修改过的配置文件

$ systemctl daemon-reload

显示某个 Unit 的所有底层参数

$ systemctl show [UnitName]

显示某个 Unit 的指定属性的值

$ systemctl show -p CPUShares [UnitName]

设置某个 Unit 的指定属性

$ systemctl set-property [UnitName] CPUShares=500
““

3.Target

什么是target?

在systemd中有一个叫做target的单元,也叫作目标单元。这个单元没有专用的配置选项,它只是以.target结尾的文件,它本身没有具体功能,你可以理解为类别,它的作用就是将一些单元汇聚在一起。

Target 就是一个 Unit 组,包含许多相关的 Unit 。启动某个 Target 的时候,Systemd 就会启动里面所有的 Unit。
并发启动原理(https://www.ibm.com/developerworks/cn/linux/1407_liuming_init3/index.html

target常用管理命令

““

查看当前系统的所有 Target

$ systemctl list-unit-files –type=target

查看一个 Target 包含的所有 Unit

$ systemctl list-dependencies multi-user.target

查看启动时的默认 Target

$ systemctl get-default

设置启动时的默认 Target

$ systemctl set-default multi-user.target

““

runlevel和target

systemd 用目标(target)替代了运行级别的概念,提供了更大的灵活性,如您可以继承一个已有的目标,并添加其它服务,来创建自己的目标。下表列举了 systemd 下的目标和常见 runlevel 的对应关系:。

““
Traditional runlevel New target name Symbolically linked to…

Runlevel 0 | runlevel0.target -> poweroff.target
Runlevel 1 | runlevel1.target -> rescue.target
Runlevel 2 | runlevel2.target -> multi-user.target
Runlevel 3 | runlevel3.target -> multi-user.target
Runlevel 4 | runlevel4.target -> multi-user.target
Runlevel 5 | runlevel5.target -> graphical.target
Runlevel 6 | runlevel6.target -> reboot.target

““
RunLevel 和 /etc/inittab 区别

(1)默认的 RunLevel(在/etc/inittab文件设置)现在被默认的 Target 取代,位置是/etc/systemd/system/default.target,通常符号链接到graphical.target(图形界面)或者multi-user.target(多用户命令行)。

(2)启动脚本的位置,以前是/etc/init.d目录,符号链接到不同的 RunLevel 目录 (比如/etc/rc3.d、/etc/rc5.d等),现在则存放在/lib/systemd/system和/etc/systemd/system目录。

(3)配置文件的位置,以前init进程的配置文件是/etc/inittab,各种服务的配置文件存放在/etc/sysconfig目录。现在的配置文件主要存放在/lib/systemd目录,在/etc/systemd目录里面的修改可以覆盖原始设置。

服务配置单元(service)

什么是服务配置单元

以 .service 为后缀的单元文件, 封装了一个被 systemd 监视与控制的进程。

进程就像旧社会给地主干活的长工,.service就是监控长工干活的周扒皮

谁该干什么活儿,谁干活偷懒了,谁欠钱干不了活,活儿需要他儿子来干,谁干活之前需要洗手(心细的地主)他都记下来

那么unit的配置文件就是他的账本,他看着账本监督长工干活的过程就是service的过程

配置文件的组成

这个文件由三个部分组成:Unit\Service\Install

[Unit]区块通常是配置文件的第一个区块,用来定义 Unit 的元数据,以及配置与其他 Unit 的关系。它的主要字段如下。


Description:简短描述
Documentation:文档地址
Requires:当前 Unit 依赖的其他 Unit,如果它们没有运行,当前 Unit 会启动失败(强依赖)
Wants:与当前 Unit 配合的其他 Unit,如果它们没有运行,当前 Unit 不会启动失败(弱依赖)
BindsTo:与Requires类似,它指定的 Unit 如果退出,会导致当前 Unit 停止运行
Before:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之后启动
After:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之前启动
Conflicts:这里指定的 Unit 不能与当前 Unit 同时运行
Condition...:当前 Unit 运行必须满足的条件,否则不会运行
Assert...:当前 Unit 运行必须满足的条件,否则会报启动失败

[Install]通常是配置文件的最后一个区块,用来定义如何启动,以及是否开机启动。它的主要字段如下。


WantedBy:它的值是一个或多个 Target,当前 Unit 激活时(enable)符号链接会放入/etc/systemd/system目录下面以 Target 名 + .wants后缀构成的子目录中
RequiredBy:它的值是一个或多个 Target,当前 Unit 激活时,符号链接会放入/etc/systemd/system目录下面以 Target 名 + .required后缀构成的子目录中
Alias:当前 Unit 可用于启动的别名
Also:当前 Unit 激活(enable)时,会被同时激活的其他 Unit

[Service]区块用来 Service 的配置,只有 Service 类型的 Unit 才有这个区块。它的主要字段如下。

““
Type:定义启动时的进程行为。它有以下几种值。
Type=simple:默认值,执行ExecStart指定的命令,启动主进程
Type=forking:以 fork 方式从父进程创建子进程,创建后父进程会立即退出
Type=oneshot:一次性进程,Systemd 会等当前服务退出,再继续往下执行
Type=dbus:当前服务通过D-Bus启动
Type=notify:当前服务启动完毕,会通知Systemd,再继续往下执行
Type=idle:若有其他任务执行完毕,当前服务才会运行

ExecStart:启动当前服务的命令
ExecStartPre:启动当前服务之前执行的命令
ExecStartPost:启动当前服务之后执行的命令
ExecReload:重启当前服务时执行的命令
ExecStop:停止当前服务时执行的命令
ExecStopPost:停止当其服务之后执行的命令
RestartSec:自动重启当前服务间隔的秒数
TimeoutSec:定义 Systemd 停止当前服务之前等待的秒数
Environment:指定环境变量
Restart:定义何种情况 Systemd 会自动重启当前服务,可能的值包括always(总是重启)、on-success(只有正常退出时)、on-failure(非正常退出时)、on-abnormal(有被信号终止和超时)、on-abort(收到没有捕捉到的信号终止)、on-watchdog(超时退出)
““

Restart= 的设置分别对应于哪些退出原因

拉起进程的条件

让我们来动手操作下吧

1./usr/lib/systemd/system 目录下添加配置

““
[Unit]
Description=php test script
After=php-fpm.service

[Service]
ExecStart=/usr/local/matrix/bin/php /home/test/test.php
KillMode=process
Restart=always
RestartSec=3s

[Install]
WantedBy=multi-user.target graphic.target
““

2./home/test/user_php_test.service 添加PHP测试代码


<php
while(true) {
$i++;
$t = $i."\n";
file_put_contents('/home/test/output.txt', $t, FILE_APPEND);
usleep(500000);
if ($i == 30) {
Exit(255);
}
}

3.systemd restart user_php_test.service
来观察下 output.txt吧。

添加开机启动和关机启动

““
[root@wjf system]# systemctl enable user_php_test.service
Created symlink from /etc/systemd/system/multi-user.target.wants/user_php_test.service to /usr/lib/systemd/system/user_php_test.service.
Created symlink from /etc/systemd/system/graphic.target.wants/user_php_test.service to /usr/lib/systemd/system/user_php_test.service.

[root@wjf system]# systemctl disable user_php_test.service
Removed symlink /etc/systemd/system/multi-user.target.wants/user_php_test.service.
Removed symlink /etc/systemd/system/graphic.target.wants/user_php_test.service.
““

文件类型说明

enabled:已建立启动链接
disabled:没建立启动链接
static:该配置文件没有[Install]部分(无法执行),只能作为其他配置文件的依赖
masked:该配置文件被禁止建立启动链接

4.TIMER

TIMER是什么?

以 “.timer” 为后缀的单元文件, 封装了一个由 systemd 管理的定时器, 以支持基于定时器的启动。
每个定时器单元都必须有一个与其匹配的单元, 用于在特定的时间启动。

周扒皮先生又隆重登场了

**吝啬的周扒皮就是一个活的计时器,永不只疲倦看着你,不止半夜学?叫,时刻都在盯着你,告诉你几点干什么活儿了,
每个人不同时间点起床后,多久开始干活儿**

但他偶会心情好也会让干完活的长工休息下,但是休息多久后,接着干活,是他说了算,霸道の男子

timer可以使用的时间单位:us(微秒), ms(毫秒), s(秒), m(分), h(时), d(天), w(周)

和crontab有区别吧,他能执行更小的时间粒度

timer文件一般包括哪些部分?

unit, Timer, Install ③个部分

示例配置如下:

[Unit]

Description=Runs mytimer every hour

[Timer]

OnUnitActiveSec=1h

Unit=mytimer.service

[Install]

WantedBy=multi-user.target

[Unit] 标签下指定了不依赖于特定类型的通用配置信息,比如例子中两个文件都指定了一个选项Description=表示描述信息。

[Install] 标签下保存了本单元的安装信息,其中WantedBy=表示当使用systemctl enable命令启用该单元时,会在指定的目标的.wants/或.requires/下创建对应的符号链接(如上例)。这么做的结果是:当指定的目标启动时本单元也会被启动。

[Timer]部分定制定时器。Systemd 提供以下一些字段。


OnActiveSec:定时器生效后,多少时间开始执行任务 (相对于该单元自身被启动的时间点)
OnBootSec:系统启动后,多少时间开始执行任务 (相对于机器被启动的时间点)
OnStartupSec:Systemd 进程启动后,多少时间开始执行任务 (相对于 systemd 被首次启动的时间点)
OnUnitActiveSec:该单元上次执行后,等多少时间再次执行 (相对于匹配单元最后一次被启动的时间点)
OnUnitInactiveSec: 定时器上次关闭后多少时间,再次执行 (相对于匹配单元最后一次被停止的时间点)
OnCalendar:基于绝对时间,而不是相对时间执行(定义基于挂钟时间(wallclock)的日历定时器,值是一个日历事件表达式,这是与传统cron任务类似的定时器)
AccuracySec:如果因为各种原因,任务必须推迟执行,推迟的最大秒数,默认是60秒
Unit:真正要执行的任务,默认是同名的带有.service后缀的单元,若未指定,则默认是与该单元名称相同的 .service 单元。
Persistent:此选项仅对 OnCalendar= 指令定义的日历定时器有意义。 若设为"yes",则表示将匹配单元的上次触发时间永久保存在磁盘上。 这样,当定时器单元再次被启动时, 如果匹配单元本应该在定时器单元停止期间至少被启动一次, 那么将立即启动匹配单元。 这样就不会因为关机而错过必须执行的任务。 默认值为 no
WakeSystem:如果系统休眠,是否自动唤醒系统.(此选项仅确保唤醒系统, 而不关心任务执行完成之后是否需要再次休眠系统。)

日历时间

““
所谓”日历事件”是指可以同时表达多个时间戳的一种特殊的表达式, 可以把它想象成一种专用于时间戳的正则表达式。 其语法是基于前述绝对时间戳语法的一种扩展。例如:

Thu,Fri 2012-*-1,5 11:12:13
表示: 2012年任意月份的1号或5号且为周三或周五的日子的11点12分13秒

“星期”部分是可选的。若指定, 则必须使用英文三字母缩写(例如”Wed”)或英文全称(例如”Wednesday”), 大小写无关。可以使用 “,” 依次列出多个日子, 也可以使用 “..” 表示一个范围, 还可以将多个范围( “..” )用 “,” 依次列出。

对于”年-月-日”与”时:分:秒”两部分中的每个子部分, 都可以: 使用 “*” 表示匹配任意值、 使用 “,” 依次列出多个值、 使用 “/整数” 后缀表示以此整数为间隔不断向后重复跳跃(例如在表示分钟的部分”3/10”等价于”3,13,23,33,43,53”)、 使用 “..” 表示一个范围。 最后,还可以用逗号(,)依次列出多个重复(/)与范围(..)。

在日期部分还可以使用 “~” 表示一个月中的”倒数第几天”。 例如 “-02~03” 表示”2月的倒数第3天”, “Mon -05~07/1” 表示”5月的最后一个星期一”。
““

错过了,再见了

如果定时器单元在启动时 已经超过了 OnBootSec= 或 OnStartupSec= 指定的时间, 那么将会立即启动匹配的单元。 但是对于使用其他指令定义的定时器, 超过了就等于错过了,不会尝试去补救。

定时器相关命令

““

启动计时器

$ sudo systemctl start mytimer.timer

计时器状态

$ systemctl status mytimer.timer

计时器列表

$ systemctl list-timers

停止计时器

sudo systemctl stop myscript.timer

开机启动

sudo systemctl enable myscript.timer

取消开机启动

sudo systemctl enable myscript.timer

““

一起动手实现一个计时器吧

5.关于日志

Systemd 统一管理所有 Unit 的启动日志。带来的好处就是,可以只用journalctl一个命令,查看所有日志(内核日志和应用日志)。日志的配置文件是/etc/systemd/journald.conf

““

查看整个日志

$ sudo journalctl

查看 mytimer.timer 的日志

$ sudo journalctl -u mytimer.timer

查看 mytimer.timer 和 mytimer.service 的日志

$ sudo journalctl -u mytimer

从结尾开始查看最新日志

$ sudo journalctl -f

从结尾开始查看 mytimer.timer 的日志

$ journalctl -f -u timer.timer
““

6.systemd的争议

点我

番外 centos 5x

关于init

init进程,是一个由内核启动的用户级进程,内核自行启动后,就通过启动init来完成引导进程。所以,init始终是第一个进程(其进程编号始终为1), /sbin/init。如果内核找不到init,它就会试着运行/bin/sh

运行级别的配置:/etc/inittab
启动目录:/etc/rc.d

runlevel


0 系统停机模式,系统默认运行级别不能设置为0,否则不能正常启动,机器关闭。
1 单用户模式,root权限,用于系统维护,禁止远程登陆,就像Windows下的安全模式登录。
2 多用户模式,没有NFS网络支持。
3 完整的多用户文本模式,有NFS,登陆后进入控制台命令行模式。
4 系统未使用,保留一般不用,在一些特殊情况下可以用它来做一些事情。例如在笔记本电脑的电池用尽时,可以切换到这个模式来做一些设置。
5 图形化模式,登陆后进入图形GUI模式,X Window系统。
6 重启模式,默认运行级别不能设为6,否则不能正常启动。运行init 6机器就会重启。

参考
阮一峰老师的blog

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值