沈雅

努力,以不负沈雅之名!
嵌入式、Linux、Cosplay、Acg、动漫、各种文学 全为我所爱矣!
交流联系:QQ88459122

Linux运维之systemd

青梅煮酒:


        systemd 是 Linux 下的一款系统和服务管理器,兼容 SysV 和 LSB 的启动脚本。systemd 的特性有:支持并行化任务;同时采用 socket 式与 D-Bus 总线式激活服务;按需启动守护进程(daemon);利用 Linux 的 cgroups 监视进程;支持快照和系统恢复;维护挂载点和自动挂载点;各服务间基于依赖关系进行精密控制。

 

一、systemd的基本控制

        检视和控制systemd的主要命令是systemctl。该命令可用于查看系统状态和管理系统及服务。

1.分析系统状态

>输出激活的单元: 
$ systemctl
与以下命令等效: 
$ systemctl list-units

>输出运行失败的单元: 
$ systemctl --failed

>查看所有已安装服务单元: 
$ systemctl list-unit-files

2.使用单元

>立即启动单元:
# systemctl start <单元>

>立即禁用单元:
# systemctl stop <单元>

>重新启动单元:
# systemctl restart <单元>

>重新加载单元:
# systemctl reload <单元>

>输出单元运行状态:
$ systemctl status <单元>

>开机自动启动单元:
# systemctl enable <单元>

>取消开机自动启动单元:
# systemctl disable <单元>

>检查单元是否配置自动启动:
$ systemctl is-enabled <单元>

>扫描单元变动并重载到systemd:
# systemctl daemon-reload

>显示单元manual(必须由单元文件提供):
# systemctl help <单元>

3.电源管理:安装 polkit 后才可以一般用户身份使用电源管理。 

>重启: 
$ systemctl reboot

>退出系统并停止电源: 
$ systemctl poweroff

>待机: 
$ systemctl suspend

>休眠: 
$ systemctl hibernate

>混合休眠模式: 
$ systemctl hybrid-sleep


二、编写与控制单元文件

        systemd 单元的语法灵感来自于 XDG 桌面系统的入口规范 .desktop 文件,又受到微软 Window 中的 .ini 文件的启发。所有的单元文件存放在两个位置,按优先级从低到高依次是:

  • /usr/lib/systemd/system/: units provided by installed package/

  • etc/systemd/system/: units installed by the system administrator

        某一单元配置文件可以描述如下内容之一:系统服务(.service)、挂载点(.mount)、sockets(.sockets) 、系统设备(.device)、交换分区(.swap)、文件路径(.path)、启动目标(.target)以及由 systemd 管理的计时器(.timer)。详情参阅 man 5 systemd.unit。 

        使用 systemctl 控制单元时,通常需要使用单元文件的全名,包括扩展名(如 <unit>.service)。但是有些单元可以在systemctl中使用简写方式。 
◾ 如果无扩展名,systemctl 默认把扩展名当作 .service。
◾ 挂载点会自动转化为相应的 .mount 单元。如 /home 等价于 home.mount。
◾ 设备会自动转化为相应的 .device 单元。所以 /dev/sda2 等价于 dev-sda2.device。

NOTE: 有一些单元的名称包含一个 @ 标记, (e.g. name@string.service): 这意味着它是模板单元 name@.service 的一个实例。 string 被称作实例标识符, 在 systemctl 调用模板单元时,会将其当作一个参数传给模板单元,模板单元会使用这个传入的参数代替模板中的 %I 指示符; 在实例化之前,systemd 会先检查 name@string.suffix 文件是否存在(如果存在,系统认为模板已经实例化了)。大多数情况下,包含 @ 标记就意味着这个文件是模板。如果一个模板单元没有实例化就调用,该调用会返回失败,因为模板单元中的 %I 指示符没有被替换。 

        要更改现存的单元配置,先创建名为 /etc/systemd/system/<单元名>.d/ 的目录(如 /etc/systemd/system/httpd.service.d/),然后放入 *.conf 文件,其中可以添加或重置参数。这里设置的参数优先级高于原来的单元文件。例如,如果想添加一个额外的依赖,创建这么一个文件即可: 

==================================================
/etc/systemd/system/<unit>.d/customdependency.conf
--------------------------------------------------
[Unit]
Requires=<自定义依赖>
After=<自定义依赖>
==================================================

再如, 为了替换一个非 oneshot 型的单元 ExecStart 的指令, 创建如下的文件即可: 
==========================================
/etc/systemd/system/unit.d/customexec.conf
------------------------------------------
[Service]
ExecStart=
ExecStart=<自定义指令>
==========================================
ExecStart 前必须将其置空。

下面是自动重启服务的一个例子: 
=======================================
/etc/systemd/system/unit.d/restart.conf
---------------------------------------
[Service]
Restart=always
RestartSec=30
=======================================
然后运行以下命令使更改生效: 
# systemctl daemon-reload
# systemctl restart <单元>


此外,把旧的单元文件从 /usr/lib/systemd/system/ 复制到 /etc/systemd/system/,然后进行修改,也可以达到同样效果。在 /etc/systemd/system/ 目录中的单元文件的优先级总是高于 /usr/lib/systemd/system/ 目录中的同名单元文件。注意,当 /usr/lib/ 中的单元文件因软件包升级变更时,/etc/ 中自定义的单元文件不会同步更新。此外,你还得执行 systemctl reenable <unit>,手动重新启用该单元。因此,建议使用前面一种利用 *.conf 的方法。 

 

三、处理依赖关系

        使用systemd时,可通过正确编写单元配置文件来解决其依赖关系。典型的情况是,单元A要求单元B在A启动之前运行。在此情况下,向单元A配置文件中的 [Unit] 段添加 Requires=B 和 After=B 即可。若此依赖关系是可选的,可添加 Wants=B 和 After=B。请注意 Wants= 和 Requires= 并不意味着 After=,即如果 After= 选项没有制定,这两个单元将被并行启动。 

        依赖关系通常被用在服务(service)而不是目标(target)上。例如, network.target 一般会被某个配置网络接口的服务引入,所以,将自定义的单元排在该服务之后即可,因为 network.target 已经启动。 

 

四、服务类型

        编写自定义的 service 文件时,可以选择几种不同的服务启动方式。启动方式可通过配置文件 [Service] 段中的 Type= 参数进行设置。具体的参数说明请参阅 man systemd.service 。 


◾ Type=simple(默认值):该类服务会立即启动。如果该服务要启动其他服务,不要使用此类型启动,除非该服务是socket型。
◾ Type=forking:该服务进程需要分叉,且在父进程退出后服务启动成功。对于常规的守护进程,除非你确定此启动方式无法满足需求,使用此类型启动即可。使用此启动类型应同时指定 PIDFile=,以便systemd能够跟踪服务的主进程。
◾ Type=oneshot:用于只执行单项任务,随后立即退出的服务。可能需要同时设置 RemainAfterExit=yes 使得 systemd 在服务进程退出之后仍然认为服务处于激活状态。
◾ Type=notify:与 Type=simple 相同,但约定服务会在就绪后向 systemd 发送一个信号。这一通知信号的实现由 libsystemd-daemon.so 提供。
◾ Type=dbus:若以此方式启动,当指定的 BusName 出现在DBus系统总线上时,systemd认为服务就绪。
◾ Type=idle: 与 type=simple 类似,但是,它会在所有任务处理后,才会执行。这种方式可以避免不同shell服务输出到控制台的状态信息出现交错的情况。

 

五、目标

        启动级别(runlevel)是一个旧的概念。现在,systemd 引入了一个和启动级别功能相似又不同的概念——目标(target)。不像数字表示的启动级别,每个目标都有名字和独特的功能,并且能同时启用多个。一些目标继承其他目标的服务,并启动新服务。systemd 提供了一些模仿 sysvinit 启动级别的目标,仍可以使用旧的 telinit 启动级别的命令进行切换。获取当前目标,不要使用 runlevel 命令了: 

$ systemctl list-units --type=target

 

SysV 启动级别               systemd 目标                          注释 

0                                    poweroff.target                中断系统[halt]

1                                    rescue.target                    单用户模式

2|4                                 multi-user.target              用户自定义启动级别,通常识别为级别3

3                                    multi-user.target              多用户,无图形界面

5                                    graphical.target                多用户,图形界面

6                                    reboot.target                    重启模式

emergency                    emergency.target             急救模式

 

评论
热度(2)
  1. 沈雅青梅煮酒 转载了此文字

© 沈雅 | Powered by LOFTER