systemd的作用

时间:2022-05-06
本文章向大家介绍systemd的作用,主要内容包括一、systemd的诞生:、二、systemd是什么?、2.2 systemctl:、2.3 target文件:、2.4 日志文件:、三、systemd的争议:、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

早上群上讨论了一下systemd的作用,还导致了一个人的直接退群,出于求知心理,搜索了一些systemd,对此也作出了一些相应的整理;

一、systemd的诞生:

学习嵌入式bootloader与kernel衔接的时候,就入门了init进程;init进程也就是系统的第一个进程,PID号为1;

init进程总所周知的问题是从它开始启动,并从下一个程序开始,都是以一个进程启动另一个进程的方式来进行;这样做的显而易见的缺点就是执行速度慢,没有一整套的系统来管理,并且/ect/目录下的随便一个脚本简直长的发指;关机过程差不多是相反的过程,首先init停止所有服务,最后阶段会卸载文件系统。

所以伟大的程序员开始了自己的创作,systemd也就诞生啦。systemd 几乎完全兼容传统的 SysV init 系统: SysV init 脚本可以作为另一种配置文件格式被识别; 提供与 SysV 兼容的 /dev/initctl 接口; 提供各种 SysV 工具的兼容实现; 依然兼容例如 /etc/fstab 或者 utmp之类传统的 Unix 特性。

systemd现在广泛用于Fedora 21、Ubuntu(Ubuntu 15.04以上)、Centos等linux操作系统上;

二、systemd是什么?

开发Systemd的主要目的就是减少系统引导时间和计算开销。

Systemd(系统管理守护进程),最开始以GNU GPL协议授权开发,现在已转为使用GNU LGPL协议,它是如今讨论最热烈的引导和服务管理程序。如果你的Linux系统配置为使用Systemd引导程序,它取替传统的init进程,启动过程将交给systemd处理。Systemd的一个核心功能是它同时支持init进程的后开机启动脚本。

 Systemd引入了并行启动的概念,它会为每个需要启动的守护进程建立一个套接字,这些套接字对于使用它们的进程来说是抽象的,这样它们可以允许不同守护进程之间进行交互。Systemd会创建新进程并为每个进程分配一个控制组(cgroup)。处于不同控制组的进程之间可以通过内核来互相通信。 cgroups 信息由内核负责维护, 并且可以通过 /sys/fs/cgroup/systemd/ 接口进行访问。

当作为系统实例运行时, systemd 将会按照 system.conf 配置文件 以及 system.conf.d 配置目录中的指令工作; 当作为用户实例运行时,systemd 将会按照 user.conf 配置文件 以及 user.conf.d 配置目录中的指令工作。

2.1 单位:

systemd 将各种系统启动和运行相关的对象, 表示为各种不同类型的单元(unit), 并提供了处理不同单元之间依赖关系的能力。 

Systemd 的其中一个目标就是简化这些事物之间的相互作用,因此如果你有程序需要在某个挂载点被创建或某个设备被接入后开始运行,Systemd 可以让这一切正常运作起来变得相当容易。

各种不同的单元类型如下:

  1. service 单元。用于封装一个后台服务进程。 
  2. socket 单元。 用于封装一个系统套接字(UNIX)或互联网套接字(INET/INET6)或FIFO管道。 相应的服务在第一个"连接"进入套接字时才会被启动。
  3. target 单元。 用于将多个单元在逻辑上组合在一起。
  4. device 单元。用于封装一个设备文件,可用于基于设备的启动。 并非每一个设备文件都需要一个 device 单元, 但是每一个被 udev 规则标记的设备都必须作为一个 device 单元出现。
  5. mount 单元。 用于封装一个文件系统挂载点(也向后兼容传统的 /etc/fstab 文件)。
  6. automount 单元。 用于封装一个文件系统自动挂载点,也就是仅在挂载点确实被访问的情况下才进行挂载。 它取代了传统的 autofs 服务。
  7. timer 单元。 用于封装一个基于时间触发的动作。它取代了传统的 atd, crond 等任务计划服务。
  8. swap 单元。 用于封装一个交换分区或者交换文件。 它与 mount 单元非常类似。
  9. path 单元。 用于根据文件系统上特定对象的变化来启动其他服务。
  10. slice 单元。 用于控制特定 CGroup 内(例如一组 service 与 scope 单元)所有进程的总体资源占用。
  11. scope 单元。它与 service 单元类似,但是由 systemd 根据 D-bus 接口接收到的信息自动创建, 可用于管理外部创建的进程。

systemd 能够处理各种类型的依赖关系, 包括依赖与冲突(也就是 Requires= 与 Conflicts= 指令), 以及先后顺序(也就是 After= 与 Before= 指令)。 注意, 上述两种类型的依赖关系(依赖与冲突、先后顺序)之间是相互独立的(无关的)。 举例来说,假定 foo.service 依赖于(Requires) bar.service 但并未指定先后顺序, 那么这两个服务将被同时并行启动。 不过在两个单元之间既存在依赖关系也存在先后顺序的情形也很常见。 另外需要注意的是, 大多数依赖关系都是由 systemd 隐式创建和维护的, 因此没有必要额外手动创建它们。

2.2 systemctl:

systemctrl是systemd的系统管理的指令,相应指令如下:http://man.linuxde.net/systemctl

 1 # 重启系统
 2 $ sudo systemctl reboot
 3 
 4 # 关闭系统,切断电源
 5 $ sudo systemctl poweroff
 6 
 7 # CPU停止工作
 8 $ sudo systemctl halt
 9 
10 # 暂停系统
11 $ sudo systemctl suspend
12 
13 # 让系统进入冬眠状态
14 $ sudo systemctl hibernate
15 
16 # 让系统进入交互式休眠状态
17 $ sudo systemctl hybrid-sleep
18 
19 # 启动进入救援状态(单用户状态)
20 $ sudo systemctl rescue

2.3 target文件:

Systemd使用“target”来处理引导和服务管理过程。这些systemd里的“target”文件被用于分组不同的引导单元以及启动同步进程。

简单说,Target 就是一个 Unit 组,包含许多相关的 Unit 。启动某个 Target 的时候,Systemd 就会启动里面所有的 Unit。从这个意义上说,Target 这个概念类似于"状态点",启动某个 Target 就好比启动到某种状态。

传统的init启动模式里面,有运行级别的概念,跟 Target 的作用很类似。不同的是,运行级别是互斥的,不可能多个运行级别同时启动,但是多个 Target 可以同时启动。

它与init进程的主要差别如下。

(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目录里面的修改可以覆盖原始设置;

2.4 日志文件:

systemd使用journalctl来管理相应的日志文件;

 1 # 查看所有日志(默认情况下 ,只保存本次启动的日志)
 2 $ sudo journalctl
 3 
 4 # 查看内核日志(不显示应用日志)
 5 $ sudo journalctl -k
 6 
 7 # 查看系统本次启动的日志
 8 $ sudo journalctl -b
 9 $ sudo journalctl -b -0
10 
11 # 查看上一次启动的日志(需更改设置)
12 $ sudo journalctl -b -1
13 
14 # 查看指定时间的日志
15 $ sudo journalctl --since="2012-10-30 18:17:16"
16 $ sudo journalctl --since "20 min ago"
17 $ sudo journalctl --since yesterday
18 $ sudo journalctl --since "2015-01-10" --until "2015-01-11 03:00"
19 $ sudo journalctl --since 09:00 --until "1 hour ago"
20 
21 # 显示尾部的最新10行日志
22 $ sudo journalctl -n
23 
24 # 显示尾部指定行数的日志
25 $ sudo journalctl -n 20
26 
27 # 实时滚动显示最新日志
28 $ sudo journalctl -f
29 
30 # 查看指定服务的日志
31 $ sudo journalctl /usr/lib/systemd/systemd
32 
33 # 查看指定进程的日志
34 $ sudo journalctl _PID=1
35 
36 # 查看某个路径的脚本的日志
37 $ sudo journalctl /usr/bin/bash
38 
39 # 查看指定用户的日志
40 $ sudo journalctl _UID=33 --since today
41 
42 # 查看某个 Unit 的日志
43 $ sudo journalctl -u nginx.service
44 $ sudo journalctl -u nginx.service --since today
45 
46 # 实时滚动显示某个 Unit 的最新日志
47 $ sudo journalctl -u nginx.service -f
48 
49 # 合并显示多个 Unit 的日志
50 $ journalctl -u nginx.service -u php-fpm.service --since today
51 
52 # 查看指定优先级(及其以上级别)的日志,共有8级
53 # 0: emerg
54 # 1: alert
55 # 2: crit
56 # 3: err
57 # 4: warning
58 # 5: notice
59 # 6: info
60 # 7: debug
61 $ sudo journalctl -p err -b
62 
63 # 日志默认分页输出,--no-pager 改为正常的标准输出
64 $ sudo journalctl --no-pager
65 
66 # 以 JSON 格式(单行)输出
67 $ sudo journalctl -b -u nginx.service -o json
68 
69 # 以 JSON 格式(多行)输出,可读性更好
70 $ sudo journalctl -b -u nginx.serviceqq
71  -o json-pretty
72 
73 # 显示日志占据的硬盘空间
74 $ sudo journalctl --disk-usage
75 
76 # 指定日志文件占据的最大空间
77 $ sudo journalctl --vacuum-size=1G
78 
79 # 指定日志文件保存多久
80 $ sudo journalctl --vacuum-time=1years

三、systemd的争议:

直接看知乎问题吧:https://www.zhihu.com/question/25873473