systemd&systemctl

2018/12/20 14:13
阅读数 15

systemd is a system and service manager for Linux operating systems. When run as first process on boot (as PID 1), it acts as init system that brings up and maintains userspace services. Systemd是一个系统管理守护进程、工具和库的集合,用于取代System V初始进程。Systemd的功能是用于集中管理和配置类UNIX系统。

系统初始化需要做的事情非常多。需要启动后台服务,比如启动 SSHD 服务;需要做配置工作,比如挂载文件系统。这个过程中的每一步都被 systemd 抽象为一个配置单元,即 unit。可以认为一个服务是一个配置单元;一个挂载点是一个配置单元;一个交换分区的配置是一个配置单元等等。systemd 将配置单元归纳为以下一些不同的类型。

  • service :代表一个后台服务进程,比如 mysqld。这是最常用的一类。
  • socket :此类配置单元封装系统和互联网中的一个 套接字 。当下,systemd 支持流式、数据报和连续包的 AF_INET、AF_INET6、AF_UNIX socket 。每一个套接字配置单元都有一个相应的服务配置单元 。相应的服务在第一个"连接"进入套接字时就会启动(例如:nscd.socket 在有新连接后便启动 nscd.service)。
  • device :此类配置单元封装一个存在于 Linux 设备树中的设备。每一个使用 udev 规则标记的设备都将会在 systemd 中作为一个设备配置单元出现。
  • mount :此类配置单元封装文件系统结构层次中的一个挂载点。Systemd 将对这个挂载点进行监控和管理。比如可以在启动时自动将其挂载;可以在某些条件下自动卸载。Systemd 会将/etc/fstab 中的条目都转换为挂载点,并在开机时处理。
  • automount :此类配置单元封装系统结构层次中的一个自挂载点。每一个自挂载配置单元对应一个挂载配置单元 ,当该自动挂载点被访问时,systemd 执行挂载点中定义的挂载行为。
  • swap: 和挂载配置单元类似,交换配置单元用来管理交换分区。用户可以用交换配置单元来定义系统中的交换分区,可以让这些交换分区在启动时被激活。
  • target :此类配置单元为其他配置单元进行逻辑分组。它们本身实际上并不做什么,只是引用其他配置单元而已。这样便可以对配置单元做一个统一的控制。这样就可以实现大家都已经非常熟悉的运行级别概念。比如想让系统进入图形化模式,需要运行许多服务和配置命令,这些操作都由一个个的配置单元表示,将所有这些配置单元组合为一个目标(target),就表示需要将这些配置单元全部执行一遍以便进入目标所代表的系统运行状态。 (例如:multi-user.target 相当于在传统使用 SysV 的系统中运行级别 5)
  • timer:定时器配置单元用来定时触发用户定义的操作,这类配置单元取代了 atd、crond 等传统的定时服务。
  • snapshot :与 target 配置单元相似,快照是一组配置单元。它保存了系统当前的运行状态。
  • slice:负责资源的分配。

systemctl命令

systemctl – Control the systemd system and service manager

systemctl may be used to introspect and control the state of the “systemd”system and service manager. Systemctl是一个systemd工具,主要负责控制systemd系统和服务管理器。

启动一个服务:systemctl start postfix.service

关闭一个服务:systemctl stop postfix.service

重启一个服务:systemctl restart postfix.service

重载一个服务:systemctl reload postfix.service   重新读取配置

显示一个服务的状态:systemctl status postfix.service

在开机时启用一个服务:systemctl enable postfix.service

在开机时禁用一个服务:systemctl disable postfix.service

查看服务是否开机启动:systemctl is-enabled postfix.service;echo $?

查看所有已经启动(active)的unit(已经加载到内存的unit)(默认):systemctl list-units

查看所有启动和未启动(已加载到内存)的unit:systemctl list-units --all

查看已安装的unit列表(包括没有被加载到内存的unit):systemctl list-unit-files

说明:启用服务就是在当前“runlevel”的配置文件目录/etc/systemd/system/multi-user.target.wants/里,建立/usr/lib/systemd/system里面对应服务配置文件的软链接;禁用服务就是删除此软链接。

常用命令:

1)  systemctl –version

2)  systemd-analyze  分析systemd启动进程

3)  systemd-analyze blame  分析启动时各个进程花费的时间

4)  systemd-analyze critical-chain  分析启动时的关键链

5)  systemctl list-unit-files   列出所有可用单元

6)  systemctl list-units        列出所有运行中单元

7)  systemctl --failed  列出所有失败单元

8)  systemctl is-enabled crond.service  检查某个单元是否启用

9)  systemctl status firewalld.service  检查某个单元或服务是否运行

10)      systemctl list-unit-files --type=service    列出所有服务(包括启用的和禁用的)

11)      systemctl mask x.service    屏蔽服务(让它不能启动)

12)      systemctl unmask x.service  显示服务

13)      systemctl rescue        启动系统救援模式

14)      systemctl emergency     进入紧急模式

15)      systemctl get-default  查看默认target,即默认运行级别,对应于旧的“renlevel”

16)      systemctl set-default multi-user.target   设置默认target

17)      systemctl list-dependencies multi-user.target  查看某一target下的unit

18)      systemctl isolate runlevel5.target/graphical.target     启动运行等级5,即图形模式

19)      systemctl isolate runlevel3.target/multiuser.target     启动运行等级3,即多用户模式(命令行)

20)      systemclt set-default runlevel3.target 设置多用户模式为默认运行等级

21)      systemctl cat nginx.service   查看unix文件

22)      systemctl list-dependencies nginx  查看unit所有依赖

23)      systemctl list-dependencies --all nginx.service    递归的列出所有依赖

24)      systemctl list-timers  查看所有运行的定时器

25)      systemctl show nginx.service  列出unit的详细信息

26)      systemctl edit nginx.service   --full     修改unit配置文件

27)      systemctl daemon-reload   修改的配置生效

28)      systemctl reboot                重启

29)      systemctl halt              停止

30)      systemctl suspend           挂起

31)      systemctl hibernate         休眠系统

32)      systemctl hybrid-sleep          系统进入混合睡眠

 

日志log

journald是systemd中专门收集日志的模块,采用压缩和格式化的二进制格式保存所有日志信息,可以查看日志,相应命令是journalctl

查看所有日志:journalctl

如果journald配置了保存上次启动的日志的话, 这个默认显示的自系统上次启动到现在的所有日志。有的发行版可能没有配置,可以/etc/system/journald.conf中将storage设置为persistent,或者创建/var/log/journal目录。当然如果我们只想查看本次启动之后的日志,可以加上-b标志:

journalctl -b

如果只想查看内核日志的话,可以加上-k(可以和-b联合使用):

journalctl -k

查看服务的日志:

journalctl -u xxx.service

systemd配置文件

systemd管理的基本对象称为单元unit,是单个进程的描述。一个个小的单元互相调用和依赖,组成一个庞大的任务管理系统,这就是 Systemd 的基本思想。unit有很多类型,如.service(后台服务), .timer(定时器), .slice(资源分配) .socket, .device, .mount, .swap, .automount等,其实任何系统知道如何操作和管理的资源systemd都可以去管理。最常见的就是服务单元systemd service unit(一般以.service为后缀)。

Systemd Service 是一种替代/etc/init.d/下脚本的更好方式,它可以灵活的控制你什么时候要启动服务,一般情况下也不会造成系统无法启动进入紧急模式。所以如果想设置一些开机启动的东西,可以试着写 Systemd Service。

systemd服务是一种以.service结尾的单元(unit)配置文件,用于控制由systemd控制或监视的进程。简单说,用于后台以守护精灵(daemon)的形式运行程序。

systemd服务的内容主要分为三个部分,控制单元(unit)的定义、服务(service)的定义以及安装部分。

1.   systemd配置文件位置

这里我们先要说明一下unit的文件位置,一般主要有三个目录:

  • /lib/systemd/system
  • /run/systemd/system
  • /etc/systemd/system

这三个目录的配置文件优先级依次从低到高,如果同一选项三个地方都配置了,优先级高的会覆盖优先级低的。系统安装时,默认会将unit文件放在/lib/systemd/system目录。如果我们想要修改系统默认的配置,比如nginx.service,一般有两种方法:

  • 在/etc/systemd/system目录下创建nginx.service文件,里面写上我们自己的配置。
  • 在/etc/systemd/system下面创建nginx.service.d目录,在这个目录里面新建任何以.conf结尾的文件,然后写入我们自己的配置。推荐这种做法。

/run/systemd/system这个目录一般是进程在运行时动态创建unit文件的目录,一般很少修改,除非是修改程序运行时的一些参数时,即Session级别的,才在这里做修改。

2.   配置文件状态

systemctl list-unit-files命令用于列出所有配置文件。

UNIT FILE                                  STATE   
proc-sys-fs-binfmt_misc.automount          static  
kubelet.service                            enabled 
module-init-tools.service                  static  
mosquitto.service                          disabled
motd.service                               masked

配置文件的状态有四种,注意从该列表不能看出unit的运行情况,需要通过命令systemctl status查看。

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

3.   定义控制单元 [Unit]

在 Systemd 中,所有引导过程中 Systemd 要控制的东西都是一个单元。基本的用法如下:

Description:代表整个单元的描述,可根据需要任意填写。

Documentation这里一般是服务文档的链接等。

Requires: 这个单元启动了,那么它“需要”的单元也会被启动; 它“需要”的单元被停止了,它自己也活不了。但是请注意,这个设定并不能控制启动顺序,因为它“需要”的单元启动也需要时间,若它“需要”的单元启动还未完成,就开始启动本单元,则本单元也无法启动,所以不建议使用这个字段。

Wants:与“Requires”类似但相对宽松些,即使依赖的服务启动失败了,本服务也可以继续正常启动。一般的依赖都推荐使用这个命令。

BindsTo和Requires类似,但是如果依赖的服务停止了,本服务也会停止。

Before和After:这两个需要和上面描述依赖关系的命令一起使用,表示依赖的当前服务与依赖的服务启动的先后顺序:Before表示当前服务启动成功后才可以启动依赖服务,即当前unit应在before指定的unit之前启动,After相反。

Conflicts这个命令后面跟的服务将不能和当前服务同时运行,如果当前服务运行则会导致该命令列举的服务被停止。

Condition...这个命令往往和许多其他命令一起使用,用来测试一些条件,比如测试当前的操作系统。如果条件不满足,则跳过当前服务的启动。

Assert...和Condition...类似,但是如果条件检测不满足会导致失败

OnFailure若本单元启动失败了,那么启动这个单元作为折衷。

看一个实际的例子:

[Unit]
Description=Protect ARP list
Wants=network-online.target
After=network.target

其中network.target代表有网路,network-online.target代表一个连通着的网络。

4.   定义服务本体 [service]

unit对象有很多种类型,其中device,target,snapshot,scope这几种类型没有对应该类型的Section,其他的都有。在定义完了 Systemd 用来识别服务的单元后,我们来定义服务本体。基本的用法如下:

Type:服务的类型,各种类型的区别如下所示

  • simple:默认,这是最简单的服务类型。意思就是说启动的程序就是主体程序,这个程序要是退出那么一切皆休。
  • forking:标准 Unix Daemon 使用的启动方式。启动程序后会调用 fork() 函数,把必要的通信频道都设置好之后父进程退出,留下守护精灵的子进程。
  • oneshot:适用于那些被一次性执行的任务或者命令,它运行完成后便了无痕迹。因为这类服务运行完就没有任何痕迹,我们经常会需要使用 RemainAfterExit=yes。意思是说,即使没有进程存在,Systemd 也认为该服务启动成功了。同时只有这种类型支持多条命令,命令之间用;分割,如需换行可以用\。
  • dbus:这个程序启动时需要获取一块 DBus 空间,所以需要和 BusName一起用。只有它成功获得了 DBus 空间,依赖它的程序才会被启动。这种类别的告诉systemd该unit会在D-Bus上面获取一个名字。
  • notify:这种类别的服务会在启动完之后发出一个消息,systemd必须等到接收到这个消息后才可以接着去处理其它unit。
  • idle:这种类别表示在收到所有任务前,服务都不会运行。

ExecStart:在输入的命令是start时候执行的命令,这里的命令启动的程序必须使用绝对路径,比如你必须用/sbin/arp而不能简单的以环境变量直接使用arp。如果在命令之前加上-的话表示进程如果以非0退出,也不算失败。

ExecStartPre和ExecStartPost:通过这两个指令可以指定在进程运行前和运行后执行的命令,同样也可以加-,表示接受非0的退出状态。

ExecReload重启当前服务时执行的命令。

ExecStop在输入的命令是stop时候执行的命令,如果未指定,服务停止后将使用kill来杀掉进程。

ExecStopPost指定服务停止后运行的命令。

RestartSec如果服务的设置了自动重启的话,这个命令指定多久重启。

Restart指定systemd在何种状态下重启服务,可能的值包括:"always", "on-success", "on-failure", "on-abnormal", "on-abort", "on-watchdog"。

TimeoutSec指定systemd停止当前服务之前等待的秒数,即若时间到后start或stop命令仍未完成则以失败退出。也可以分别指定TimeoutStartSec和TimeoutStopSec。

Environment:指定环境变量

ExecReload这个不是必需,如果不写则你的service就不支持restart命令。ExecStart和ExecStop是必须要有的。

看一个实际的例子:

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/arp -f /etc/ip-mac
ExecReload=/sbin/arp -f /etc/ip-mac
ExecStop=/sbin/arp -d -a

这里在start和restart的时候会读取并添加/etc/ip-mac文件中的ARP条目到ARP表中,而stop时清空ARP表。

5.   安装服务 [install]

Install一般是最后一部分,用来描述unit的行为或者是否开机自启动等,是可选的。而且只有可以开机自启的(即可以被enable)的才会有这个Section。定义安装单元各个字段如下:

WantedBy:设置服务被谁装载,一般设置为multi-user.target。这个命令是最通用的用来指定服务如何被enable,即在哪些target/runlevel下被设置为开机自启动。我们可以通过这个命令来指定服务捡的依赖关系,有点像[Unit]部分的Wants,但是这个只是辅助性的。当一个unit被enable后,就会在/etc/systemd/system目录下创建以.wants为后缀的目录,比如当前unit文件里面写了WantedBy=multi-user.target,那么enable当前unit后,就会在/etc/systemd/system目录下创建multi-user.target.wants目录,并且将当前unit及其依赖的unit的符号链接放在新创建的目录里面。disable该unit之后,它的软连接及其依赖的unit的软连接都将被删除。

RequiredBy和WantedBy类似,但是它指定的依赖条件如果不满足,就会导致服务启动失败。如果enable的话,创建的是.requires结尾的目录。

Alias:为service设置一个别名,可以使用多个名字来操作服务。当设置别名后,/etc/systemd/system下会增加别名软链接。

Also:当前unit激活(enable)时,会被同事激活的其他unit。

6.   完整的 Systemd Service 配置实例

组合上面的三个模块,我们可以得到一个完整的 Systemd Service 配置实例:

[Unit]
Description=Protect ARP list
Wants=network-online.target
After=network.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/arp -f /etc/ip-mac
ExecReload=/sbin/arp -f /etc/ip-mac
ExecStop=/sbin/arp -d -a
[Install]
WantedBy=multi-user.target

7.   timer单元

systemd timers可以替换cron jobs实现定时管理任务的目的。

server单元只是定义了如何执行任务,要定时执行这个service,还必须定义timer单元。

timer除了包含通用的[Unit]和[Install]章节section外,还包含[Timer]用于指定timer相关配置项。

对于每个timer配置文件,一个匹配的单元unit文件必须存在,用来描述timer到期后执行的动作等。默认情况下,一个与timer配置文件相同的service配置文件被使能执行。如:timer配置文件是foo.timer,使能一个service文件foo.service。使能的单元可以被[timer]section中Unit=指定。

OnActiveSec=, OnBootSec=, OnStartupSec=, OnUnitActiveSec=, OnUnitInactiveSec=,指定单调定时器属性。

OnCalendar=,指定日历定时器属性。

OnActiveSec:定时器生效后,多少时间开始执行任务

OnBootSec:系统启动后,多少时间开始执行任务

OnStartupSec:Systemd 进程启动后,多少时间开始执行任务

OnUnitActiveSec:该单元上次执行后,多少时间再次执行

OnUnitInactiveSec: 定时器上次关闭后多少时间,再次执行

OnCalendar:基于绝对时间,而不是相对时间执行

AccuracySec:如果因为各种原因,任务必须推迟执行,推迟的最大秒数,默认是60秒

RandomizedDelaySec将此单元的定时器随机延迟一小段时间,这一小段时间介于0和该指令设置的时间长度之间。

Unit真正要执行的任务,默认是同名的带有.service后缀的单元

Persistent:如果设置了该字段,即使定时器到时没有启动,也会自动执行相应的单元

WakeSystem:如果系统休眠,是否自动唤醒系统

注:时间单位后缀:us/usec(微秒), ms/msec(毫秒), s/sec/second/seconds(秒), m/min/minute/minutes(分), h/hr/hour/hours(时), d/day/days(天), w/week/weeks(周),m/month/months(月),y/year/years(年) 。 如果省略了时间单位,那么表示使用默认单位"秒"。 可以同时使用多个时间单位,例如 "OnBootSec=5h 30min" 表示系统启动之后的5小时30分钟。

具体配置步骤如下:

1) 确认要周期执行的程序或脚本,如/usr/local/bin/myscript,每隔一分钟执行一次。

2) 增加service配置文件,/lib/systemd/system/myscript.service。

[Unit] 
Description=myscript
 
[Service]
Type=simple
ExecStart=/usr/local/bin/myscript

注意:Type变量的值设置为simple,而不是oneshot。使用oneshot使得脚本只执行一次。

3) 增加timer配置文件,/lib/systemd/system/myscript.timer。

[Unit] 
Description=Run myscript every minute
 
[Timer]
OnBootSec=5m
OnUnitActiveSec=1m
Unit=myscript.service
 
[Install]
WantedBy=multi-user.target

4) 授权并运行的是timer文件,而不是service文件。

systemctl start myscript.timer
systemctl enable myscript.timer

 

附注:

系统运行等级

Runlevel 0 : 关闭系统

Runlevel 1 : 救援?维护模式

Runlevel 3 : 多用户,无图形系统

Runlevel 4 : 多用户,无图形系统

Runlevel 5 : 多用户,图形化系统

Runlevel 6 : 关闭并重启机器

 

参考:

  1. systemctl 命令完全指南https://linux.cn/article-5926-1.html
  2. 如何编写一个Systemd Service
  3. 浅析 Linux 初始化 init 系统,第 3 部分: Systemd
  4. systemd学习总结
  5. Systemd 入门教程:命令篇
  6. Systemd 入门教程:实战篇
  7. Systemd 定时器教程
  8. 如何使用 systemd 中的定时器
  9. systemd.timer 中文手册
展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部