Linux systemd 介绍和使用

一、systemd介绍

systemd是一个Linux系统基础组件的集合,提供了一个系统和服务管理器,运行为PID 1并负责启动其它程序。systemd采用并行化任务,可以提高系统的启动速度(SysV-init 采用串行启动)。除此之外,systemd还具有日志进程、控制基础系统配置、维护登陆用户列表以及系统账户、运行时目录和设置等功能。其次,systemd可以运行容器和虚拟机,管理网络配置、网络时间同步、日志转发和名称解析。

systemd的架构如下图:

 二、Systemd VS Sysvinit

systemd相对于sysvinit的优点:

1、启动速度快:Systemd的目标是尽可能启动更少的进程,并将更多进程并行启动,以提高系统的启动速度。

2、按需启动:Systemd提供按需启动能力,可以按需加载服务,而SysVinit在系统初始化时会将所有可能用到的后台服务进程全部启动运行。

3、强大的管理能力:Systemd使用socket和D-Bus来开启服务,提供基于守护进程的按需启动策略,并保留了Linux cgroups的进程追踪功能。这些特性使得Systemd具有更强大的管理能力。

4、并行性能:Systemd支持快照和系统状态恢复,维护挂载和自挂载点,实现了各服务间基于从属关系的一个更为精细的逻辑控制,具有前卫的并行性能。

5、日志管理:Systemd的日志系统使用journalctl命令来查看日志信息,使得日志的检索和查看变得非常容易。Systemd的日志系统将所有可记录的事件保存在同一个数据存储中,从而使得日志内容的全局上下文得以保存并可供日后查询。

常见操作对比:

描述

SysVinit

Systemd

启动服务

service example start

systemctl start example

停止服务

service example stop

systemctl stop example

重新启动服务

service example restart

systemctl restart example

重新加载服务配置文件

service example reload

systemctl reload example

查看服务状态

service example status

systemctl status example

系统启动时启用服务

chkconfig example on

systemctl enable example

系统启动时禁用服务

chkconfig example off

systemctl disable example

打印服务列表

chkconfig --list

systemctl list-unit-files --type=service

systemd和sysvinit 运行级别对比:

Description

SysVInit

Systemd

关机模式

runlevel 0

poweroff.target

单用户root模式

runlevel 1

rescure.target

离线多用户模式

runlevel 2

multi-user.target

标准多用户模式

runlevel 3

multi-user.target

安全模式

runlevel 4

multi-user.target

带图形界面的多用户模式

runlevel 5

graphical.target

重启模式

runlevel 6

reboot.target

如何在yocto中修改systemd的运行模式:

SYSTEMD_DEFAULT_TARGET = "custom.target"

三、systemd命令使用

systemd提供了一些常用的命令,例如:

systemctl:这是systemd的主命令,用于管理系统。可以用来重启系统、关闭系统、停止CPU工作、暂停系统、让系统进入冬眠状态、让系统进入交互式休眠状态、启动进入救援状态(单用户状态)等。
systemd-analyze:这个命令用于查看启动耗时。
systemctl list-unit-files:可以列出所有可用单元(服务)。
systemctl list-units:可以列出所有运行中的单元。
systemctl list-unit-files | grep enable:可以查看自启动的软件。
systemctl daemon-reload:修改了某个单元的配置文件后,可以用这个命令重载配置文件。
systemctl reload mysqld.service:可以用这个命令重载某个单元。
hostnamectl:用于查看当前主机的信息。
localectl:用于查看本地化设置。
timedatectl:用于查看当前时区设置

3.1 systemctl使用

# 重启系统
$ sudo systemctl reboot
# 关闭系统,切断电源
$ sudo systemctl poweroff
# CPU停止工作
$ sudo systemctl halt
# 暂停系统
$ sudo systemctl suspend
# 让系统进入冬眠状态
$ sudo systemctl hibernate
# 让系统进入交互式休眠状态
$ sudo systemctl hybrid-sleep
# 启动进入救援状态(单用户状态)
$ sudo systemctl rescue

3.2 systemd-analyze使用

# 查看启动耗时
$ systemd-analyze                                                                                       
# 查看每个服务的启动耗时
$ systemd-analyze blame
# 显示瀑布状的启动过程流
$ systemd-analyze critical-chain
# 显示指定服务的启动流
$ systemd-analyze critical-chain atd.service

3.3 hostnamectl使用

# 显示当前主机的信息
$ hostnamectl
# 设置主机名。
$ sudo hostnamectl set-hostname rhel7

3.4 localectl使用

# 查看本地化设置
$ localectl
# 设置本地化参数。
$ sudo localectl set-locale LANG=en_GB.utf8
$ sudo localectl set-keymap en_GB

3.5 timedatectl使用

# 查看当前时区设置
$ timedatectl
# 显示所有可用的时区
$ timedatectl list-timezones                                                                                   
# 设置当前时区
$ sudo timedatectl set-timezone America/New_York
$ sudo timedatectl set-time YYYY-MM-DD
$ sudo timedatectl set-time HH:MM:SS

3.6 loginctl使用

# 列出当前session
$ loginctl list-sessions
# 列出当前登录用户
$ loginctl list-users
# 列出显示指定用户的信息
$ loginctl show-user ruanyf

四、systemd Unit文件

systemd 可以管理所有系统资源,不同的资源统称为 unit(单位)。 unit 文件统一了过去各种不同系统资源配置格式,例如服务的启/停、定时任务、设备自动挂载、网络配置、虚拟内存配置等。而 systemd 通过不同的文件后缀来区分这些配置文件。

4.1 systemd unit 文件类型

systemd 支持的 12 种 unit 文件类型如下:

.automount

用于控制自动挂载文件系统,相当于 SysV-init 的 autofs 服务

.device

对于 /dev 目录下的设备,主要用于定义设备之间的依赖关系

.mount

定义系统结构层次中的一个挂载点,可以替代过去的 /etc/fstab 配置文件

.path

用于监控指定目录或文件的变化,并触发其它 Unit 运行

.scope

这种 Unit 文件不是用户创建的,而是 Systemd 运行时产生的,描述一些系统服务的分组信息

.service

封装守护进程的启动、停止、重启和重载操作,是最常见的一种 Unit 文件

.slice

用于表示一个 CGroup 的树,通常用户不会自己创建这样的 Unit 文件

.snapshot

用于表示一个由 systemctl snapshot 命令创建的 Systemd Units 运行状态快照

.socket

监控来自于系统或网络的数据消息,用于实现基于数据自动触发服务启动

.swap

定义一个用户做虚拟内存的交换分区

.target

用于对 Unit 文件进行逻辑分组,引导其它 Unit 的执行。它替代了 SysV-init 运行级别的作用,并提供更灵活的基于特定设备事件的启动方式

.timer

用于配置在特定时间触发的任务,替代了 Crontab 的功能

systemctl list-units命令可以查看当前系统的所有 Unit 。

# 列出正在运行的 Unit
$ systemctl list-units
# 列出所有Unit,包括没有找到配置文件的或者启动失败的
$ systemctl list-units --all
# 列出所有没有运行的 Unit
$ systemctl list-units --all --state=inactive
# 列出所有加载失败的 Unit
$ systemctl list-units --failed
# 列出所有正在运行的、类型为 service 的 Unit
$ systemctl list-units --type=service

4.2 systemd unit 优先级

Unit 文件按照 Systemd 约定,应该被放置指定的三个系统目录之一中。这三个目录是有优先级的,如下所示,越靠上的优先级越高。因此,在三个目录中有同名文件的时候,只有优先级最高的目录里的那个文件会被使用。

/etc/systemd/system:系统或用户自定义的配置文件
/run/systemd/system:软件运行时生成的配置文件
/usr/lib/systemd/system:系统或第三方软件安装时添加的配置文件。

4.3 systemd unit 状态

# 显示系统状态
$ systemctl status
# 显示单个 Unit 的状态
$ sysystemctl status bluetooth.service
# 显示远程主机的某个 Unit 的状态
$ systemctl -H root@rhel7.example.com status httpd.service

4.4 systemd unit 管理

# 立即启动一个服务
$ sudo systemctl start apache.service
# 立即停止一个服务
$ sudo systemctl stop apache.service
# 重启一个服务
$ sudo systemctl restart apache.service
# 杀死一个服务的所有子进程
$ sudo systemctl kill apache.service
# 重新加载一个服务的配置文件
$ sudo systemctl reload apache.service
# 重载所有修改过的配置文件
$ sudo systemctl daemon-reload
# 显示某个 Unit 的所有底层参数
$ systemctl show httpd.service
# 显示某个 Unit 的指定属性的值
$ systemctl show -p CPUShares httpd.service
# 设置某个 Unit 的指定属性
$ sudo systemctl set-property httpd.service CPUShares=500

4.5 systemd unit 依赖

Unit 之间存在依赖关系:A 依赖于 B,就意味着 Systemd 在启动 A 的时候,同时会去启动 B。

#systemctl list-dependencies命令列出一个 Unit 的所有依赖
systemctl list-dependencies nginx.service
#上面命令的输出结果之中,有些依赖是 Target 类型(详见下文),默认不会展开显示
#如果要展开 Target,就需要使用--all参数
systemctl list-dependencies --all nginx.service

4.6 systemd 日志打印

# 查看所有日志(默认情况下 ,只保存本次启动的日志)
$ sudo journalctl

# 查看内核日志(不显示应用日志)
$ sudo journalctl -k

# 查看系统本次启动的日志
$ sudo journalctl -b
$ sudo journalctl -b -0

# 查看上一次启动的日志(需更改设置)
$ sudo journalctl -b -1

# 查看指定时间的日志
$ sudo journalctl --since="2012-10-30 18:17:16"
$ sudo journalctl --since "20 min ago"
$ sudo journalctl --since yesterday
$ sudo journalctl --since "2015-01-10" --until "2015-01-11 03:00"
$ sudo journalctl --since 09:00 --until "1 hour ago"

# 显示尾部的最新10行日志
$ sudo journalctl -n

# 显示尾部指定行数的日志
$ sudo journalctl -n 20

# 实时滚动显示最新日志
$ sudo journalctl -f

# 查看指定服务的日志
$ sudo journalctl /usr/lib/systemd/systemd

# 查看指定进程的日志
$ sudo journalctl _PID=1

# 查看某个路径的脚本的日志
$ sudo journalctl /usr/bin/bash

# 查看指定用户的日志
$ sudo journalctl _UID=33 --since today

# 查看某个 Unit 的日志
$ sudo journalctl -u nginx.service
$ sudo journalctl -u nginx.service --since today

# 实时滚动显示某个 Unit 的最新日志
$ sudo journalctl -u nginx.service -f

# 合并显示多个 Unit 的日志
$ journalctl -u nginx.service -u php-fpm.service --since today

# 查看指定优先级(及其以上级别)的日志,共有8级
# 0: emerg
# 1: alert
# 2: crit
# 3: err
# 4: warning
# 5: notice
# 6: info
# 7: debug
$ sudo journalctl -p err -b

# 日志默认分页输出,--no-pager 改为正常的标准输出
$ sudo journalctl --no-pager

# 以 JSON 格式(单行)输出
$ sudo journalctl -b -u nginx.service -o json

# 以 JSON 格式(多行)输出,可读性更好
$ sudo journalctl -b -u nginx.serviceqq
 -o json-pretty

# 显示日志占据的硬盘空间
$ sudo journalctl --disk-usage

# 指定日志文件占据的最大空间
$ sudo journalctl --vacuum-size=1G

# 指定日志文件保存多久
$ sudo journalctl --vacuum-time=1years

五、systemd的启动流程

5.1 systemd 启动过程

下图是centos6的systemd启动流程:

5.2 systemd 系统服务

systemd的一些(不全)组件是:

kernel-install

用于自动将内核及其各自的initramfs映像移动到启动分区的脚本;

systemd-boot

简单的 UEFI启动管理器;

systemd-creds

安全地存储和检索 systemd 单元使用的凭据;

systemd-cryptenroll

将 PKCS#11、FIDO2、TPM2 令牌/设备注册到 LUKS2 加密卷;

systemd-firstboot

首次启动前的基本系统设置初始化;

systemd-homed

便携式人类用户帐户;

systemd-logind(8)

会话管理;

systemd-networkd

网络配置管理;

systemd-nspawn

轻量级命名空间容器;

systemd-resolved

网络名称解析;

systemd-stub(7)

用于创建统一内核映像的UEFI 引导存根;

systemd-sysusers(8)

创建系统用户和组,并在软件包安装或启动时将用户添加到组中;

systemd-timesyncd

通过网络进行系统时间同步;

systemd/Journal

系统日志记录;

systemd/Timers

用于控制.service文件或事件的单调或实时计时器,是cron的合理替代方案

systemd-fsck

文件系统检查;

5.3 systemd-networkd

启动系统后,为了方面管理网络配置,我们可以在 /etc/systemd/network/ 目录中添加网络配置文件。例如,添加一个动态分配 IP 的配置文件 10-wired-dhcp.network,内容如下:
Match]
Name=eth0

[Network]
DHCP=yes

[DHCP]
RouteMetric=0

再添加一个静态 IP 配置文件 20-wired-static.network,内容如下:

[Match]
Name=eth0

[Network]
Address=192.168.1.100/24
DNS=192.168.1.1
DNS=114.114.114.114

[Route]
Gateway=192.168.1.1
Metric=100

文件名前面的数字表示优先级,数字越小优先级越高,因此上述两个配置文件会优先使用 dhcp 网络配置。

5.4 systemd-udevd

systemd-udevd的工作方式是侦听Linux内核中涉及设备状态更改的事件,当有新设备插入或拔出,或者设备状态发生变化时,内核会发出相应的事件。systemd-udevd会监听这些事件,并根据udev规则处理每个事件。

自动挂载u盘的例子如下:

automount-usb.rules:
ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", RUN{program}+="/bin/mkdir /media/%k" ,
RUN{program}+="/usr/bin/systemd-mount --no-block --collect $devnode /media/%k"

下面的表格是,rules.d的键值含义:

含义

ACTION

事件 (uevent) 的行为,例如:add( 添加设备 )、remove( 删除设备 )。

KERNEL

在内核里看到的设备名字,比如sd*表示任意SCSI磁盘设备

DEVPATH

内核设备路径,比如/devices/*

SUBSYSTEM

子系统名字,例如:sda 的子系统为 block。

BUS

总线的名字,比如IDE,USB

DRIVER

设备驱动的名字,比如ide-cdrom

ID

独立于内核名字的设备名字

SYSFS{filename}

设备的 devpath 路径下,设备的属性文件“filename”里的内容

ENV{key}

环境变量,可以表示任意

PROGRAM

可执行的外部程序,如果程序返回0值,该键则认为为真(true)

RESULT

上一个PROGRAM调用返回的标准输出。

NAME

根据这个规则创建的设备文件的文件名。 **注意:**仅仅第一行的NAME描述是有效的,后面的均忽略。如果你想使用使用两个以上的名字来访问一个设备的话,可以考虑SYMLINK键。

SYMLINK

为/dev/下的设备文件产生符号链接。由于udev只能为某个设备产生一个设备文件,所以为了不覆盖系统默认的 udev 规则所产生的文件,推荐使用符号链接。

OWNER

设备文件的属组

GROUP

设备文件所在的组。

MODE

设备文件的权限,采用8进制

RUN

为设备而执行的程序列表

LABEL

在配置文件里为内部控制而采用的名字标签(下下面的GOTO服务)

GOTO

跳到匹配的规则(通过LABEL来标识),有点类似程序语言中的GOTO

IMPORT{type}

导入一个文件或者一个程序执行后而生成的规则集到当前文件

WAIT_FOR_SYSFS

等待一个特定的设备文件的创建。主要是用作时序和依赖问题。

OPTIONS

特定的选项:last_rule 对这类设备终端规则执行; ignore_device 忽略当前规则; ignore_remove 忽略接下来的并移走请求。 all_partitions 为所有的磁盘分区创建设备文件。

六、在yocto中开启systemd

在local.conf文件或者DISTRO.conf文件中增加:

DISTRO_FEATURES_append = " systemd"
VIRTUAL-RUNTIME_init_manager = "systemd"

七、systemd service文件的配置

7.1 service配置案例

下面是一个test.service的写法案例:

[Unit]
Description=Test service
Documentation=pathto/xx.doc
After=network.target
Before=xx.service

[Service]
Type=forking
ExecStart=test
WorkingDirectory=/user/bin
User=root
Restart=on-failure

[Install]
WantedBy=multi-user.target

7.2 service 配置解释

[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 运行必须满足的条件,否则会报启动失败

[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:自动重启当前服务间隔的秒数
Restart:定义何种情况 Systemd 会自动重启当前服务,可能的值包括always(总是重启)、on-success、on-failure、on-abnormal、on-abort、on-watchdog
TimeoutSec:定义 Systemd 停止当前服务之前等待的秒数
Environment:指定环境变量

八、systemd mount文件的写法

[Unit]
Description=mount disk

[Mount]
What=/dev/mmcblk2p3
Where=/home/root/mount/
Type=ext4
Options=defaults

[Install]
WantedBy=multi-user.target

注意:.mount文件的名称需要与挂载点一致,如这里的挂载点是/home/root/mount,所以.mount文件必要名为home-root-mount.mount

九、基于yocto 开机启动服务的写法

9.1 service文件

[Unit]
Description=Test service

[Service]
Type=forking
ExecStart=systemd_test.sh 
WorkingDirectory=/usr/bin
User=root
Restart=on-failure

[Install]
WantedBy=multi-user.target

9.2 yocto bb文件

SUMMARY = "systemd test"
DESCRIPTION = "systemd test"
LICENSE = "CLOSED"
SECTION = "systemd_test"

inherit systemd

SYSTEMD_AUTO_ENABLE = "enable" //是否开机启动
SYSTEMD_SERVICE_${PN} = "systemd_test.service"

SRC_URI = " \
		   file://systemd_test.service \
		   file://systemd_test.sh \
		   "

do_install() {
	install -d ${D}${bindir}
	install -d  ${D}${systemd_system_unitdir}
	
	install -m 0755 ${WORKDIR}/systemd_test.sh  ${D}${bindir}/
	install -m 0644 ${WORKDIR}/systemd_test.service ${D}/${systemd_unitdir}/system/systemd_test.service
}

FILES_${PN} += "${bindir}/systemd_test.sh"
FILES_${PN} += "${systemd_unitdir}/system/systemd_test.service"

参考文档:

1、https://systemd.io/

2、https://cloud.tencent.com/developer/article/1516125

3、https://ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html

4、https://systemd-book.junmajinlong.com/systemd_bootup.html

5、https://getiot.tech/zh/imx8/systemd-network-configuration

6、https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system_administrators_guide/chap-managing_services_with_systemd

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值