-
目录
学习systemd init系统的基本原理:如何配置它并使用它来管理系统。
理解systemd
Systemd是Linux的系统和服务管理器,兼容SysV和LSB初始化脚本。Systemd提供:
- 先进的并行处理能力
- 用socket和D-Bus激活来启动服务
- 提供按需启动守护进程,使用Linux cgroups跟踪进程
- 支持对系统状态进行快照和恢复
- 维护挂载和自动挂载点
- 实现一个复杂的基于事务依赖关系的服务控制逻辑。
systemctl 命令是管理systemd 的主要工具。它将SysVinit的服务和chkconfig命令的功能组合成一个工具,您可以使用它来永久启用和禁用服务,或者只针对当前会话来启用和禁用服务。
Systemd管理的服务称为units,它们是系统资源和服务的表示。下面的列表显示了systemd可以管理的单元类型:
service
系统上的服务,包括了启动,重启和停止服务的相关说明
socket
与服务相关联的网络套接字。
device
一种由systemd专门管理的设备。
mount
用systemd管理的挂载点。
automount
在引导时自动挂载的挂载点。
swap
系统上的交换空间。
target
其他单元的同步点,通常用于在系统启动时启动开启了开机启动的服务
path
用于基于路径激活的路径。例如,您可以根据某个路径的状态启动服务,例如该路径是否存在。
timer
调度激活其他单元的定时器
snapshot
当前systemd状态的快照。通常用于对systemd进行临时更改后的回滚。
slice
通过Linux控制组节点(cgroups)限制资源。
scope
来自systemd总线接口的信息。通常用于管理外部系统进程。
启动、停止和查询systemd服务
你可以使用systemctl命令执行各种管理任务来控制systemd服务。下面是一组命令示例,演示如何使用systemctl管理systemd服务。
下面的命令控制一个foo服务:
- 立即激活服务:
systemctl start foo
- 立即停用服务:
systemctl stop foo
- 重启服务
systemctl restart foo
- 显示服务的状态,是否服务在运行:
systemctl status foo
- 启用服务的开机启动
systemctl enable foo
- 禁用服务的开机启动
systemctl disable foo
- 阻止服务自动启动甚至手动启动,除非解除
systemctl mask foo
- 检查服务是否启用开机自启
systemctl is-enabled foo
详细信息请运行man systemctl。
修改已有systemd服务
这个例子展示了如何修改现有的服务。服务修改存储在/etc/systemd/system目录中的单个文件中或以服务命名的子目录中。例如,修改mysqld服务。
1. 可以使用systemctl edit修改系统服务
systemctl edit httpd.service
这将创建一个覆盖文件/etc/systemd/system/httpd.service.d/override.conf 并且在文本编辑器中打开它。你在该文件中写的任何内容都将附加到已经存在的服务文件
2. 添加一个自定义配置,例如:
[Service]
Restart=always
RestartSec=30
要替换一个可以被多次设值得选项,你必须首先清空它,否则这个覆盖文件将再次附加这个选项
[Service]
ExecStart=
ExecStart=<new command>
3. 保存文件。Systemd自动加载新的服务配置
4. 重启这个mysqld服务
systemctl restart httpd
要完全的替换(而不是仅仅的添加或者修改)一个已经存在的服务文件,使用systemctl edit --full命令.
例如systemctl edit --full mysqld.service。这将创建/etc/systemctl/system/mysqld.service,它将取代现有的服务文件。
创建新的systemd服务
这个例子展示了如何为自定义服务创建单元文件。自定义单元文件位于/etc/systemd/system/中,扩展名为.service。例如,自定义foo服务使用/etc/systemd/system/foo.service单元文件。
1. 创建和编辑新配置文件
nano /etc/systemd/system/foo.service
2. 接下来的几个步骤描述了要添加到文件中的每个部分的参数:
a. [Unit]部分提供了关于该服务的基本信息。foo服务使用以下参数:
Description
描述单元的字符串。Systemd将此描述显示在用户界面的单元名称旁边。
After
定义与第二个单元的关系。如果你激活这个单元,systemd只会在第二个单元之后激活它。例如,foo服务可能需要网络连接,这意味着foo服务指定了 network.target作为After=条件。
生成的[Unit]部分如下所示:
[Unit]
Description=My custom service
After=network.target
b. [Service]部分提供如何控制服务的说明。foo服务使用以下参数:
Type
定义systemd服务的类型。在这个例子中,foo服务是一个simple
的服务,它在启动服务时没有任何特殊的考虑。
ExecStart
启动服务的命令。这包括命令的完整路径和修改服务的参数。
得到的[Service]部分是这样的:
[Service]
Type=simple
ExecStart=/usr/bin/sleep infinity
c. [Install]部分提供了systemd如何安装服务的说明。foo服务使用以下参数:
WantedBy
如果该服务使用systemctl enable启用开机自启,该选项定义哪一个服务触发这个自定义服务。这主要用于在引导时启动这个自定义服务。在该例中,foo.service使用multi-user.target, 这标示着当systemd加载multi-user.target时启动foo.service
3. 完整的foo.service文件包含下面的内容:
[Unit]
Description=My custom service
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/sleep infinity
[Install]
WantedBy=multi-user.target
4. 使systemd发现新的服务,重载服务文件:
systemctl daemon-reload
5. 启动自定义foo服务:
systemctl start foo.service
6. 检查该服务的状态确保这个服务是运行中:
$ systemctl status foo.service
● foo.service - My custom service
Loaded: loaded (/etc/systemd/system/foo.service; disabled; vendor preset: disabled)
Active: active (running) since 一 2021-10-11 09:39:26 CST; 5s ago
Main PID: 2183 (sleep)
CGroup: /system.slice/foo.service
└─2183 /usr/bin/sleep infinity
10月 11 09:39:26 localhost.localdomain systemd[1]: Started My custom service.
将SysVinit服务转换为systemd服务
旧版本的系统使用SysVinit脚本管理服务,本节提供了一些关于如何将SysVinit脚本转换为systemd等价脚本的指南。
1. 在你的SysVinit脚本中确定服务运行级别。这通常定义在脚本的开头注释部分的chkconfig指令。例如,下面这行标识着该服务使用runlevels 2,3和5:
# chkconfig: 235 20 80
systemd使用targets替代runlevels. 使用这个表Table 1. Runlevel to target mapping去转换运行级别到targets。在该例中,运行级别2,3和5都是multi-user runlevels.所以这个systemd服务可以使用下面的配置:
[Install]
WantedBy=multi-user.target
如果你启用这个自定义服务为开机自启(systemctl enable foo.service),当系统启动并加载multi-user.target时systemd将加载这个服务
2. 确定依赖的services和targets。例如,如果该自定义服务需要网络连接,指定network.target作为依赖:
[Unit]
Description=My custom service
After=network.target
3. 在SysVinit脚本中确定启动该服务的命令并将其转换为systemd等效的配置。例如,init脚本可能包含一个start函数使用下面的格式:
start() {
echo "Starting My Custom Service..."
/usr/bin/myservice -D
}
在这个例子中,/usr/bin/myservice命令是一个自定义服务命令并且带有一个-D选项。设置ExecStart参数以使用此命令:
[Service]
ExecStart=/usr/bin/myservice -D
4. 检查SysVinit脚本,看看服务是否使用特殊命令重新启动服务。例如,脚本可能包含一个重新加载服务的reboot函数:
reboot() {
echo "Reloading My Custom Service..."
/usr/bin/myservice reload
}
在本例中,/usr/bin/myservice命令是自定义服务命令,并使用reload子命令重新加载服务。设置ExecReload参数以使用此命令:
[Service]
ExecReload=/usr/bin/myservice reload
或者,您可以省略ExecReload并使用默认行为,这将kill掉该服务并重新启动它。
5. 检查SysVinit脚本,看看服务是否使用特殊命令停止服务。例如,脚本可能包含一个stop函数来重新加载服务:
reboot() {
echo "Stopping My Custom Service..."
/usr/bin/myservice shutdown
}
在本例中,/usr/bin/myservice命令是自定义服务命令,并使用shutdown子命令优雅地停止服务。设置ExecStop参数以使用此命令:
[Service]
ExecStop=/usr/bin/myservice shutdown
或者,您可以省略ExecStop并使用默认行为,这将kill掉该服务。
6. 检查SysVinit脚本并识别任何附加参数或函数。使用systemd参数复制可能与您的服务相关的任何标识的SysVinit函数。
公共服务参数
Unit Parameters
此部分包含可以在服务的[Unit]部分中使用的参数。这些参数对其他systemd单位是通用的。
Description
一个自由格式的描述字符串
Documentation
该服务相关的文档或者配置URI.仅仅接受这几种类型:http://
, https://
, file:
, info:
, man:
.
Requires
配置对其他服务的依赖。如果这个服务被激活,这里列出的单元也会被激活。如果一个依赖的服务无法激活,systemd将不会启动该服务。此选项可以指定多次,也可以指定多个空格分隔的单元。
Wants
类似于Requires,除了失败的单元对该服务没有任何影响。
BindsTo
类似于Requires,除了停止依赖的单元也会停止该服务。
PartOf
类似于Requires,除了停止和重新启动依赖的单元,也要停止和重新启动该服务。
Conflicts
由空格分隔的单元名称列表,如果运行该列表的服务,将导致该服务不运行。
Before, After
用空格分隔的单元名称列表,用于配置服务之间依赖关系的排序。
OnFailure
以空格分隔的单元名称列表,当此服务进入失败状态时激活。
Install Parameters
本节包含可在服务的[Install]部分中使用的参数。这些参数对其他systemd单元是通用的。
Alias
在此服务下安装的附加名称以空格分隔的列表。这里列出的名称必须具有与服务文件名相同的后缀(即类型)。
RequiredBy, WantedBy
将服务定义为依赖于另一个服务。这通常定义target来触发已启用的服务运行。这些选项类似于[Unit]一节中的Requires
和Wants
。
Also
安装或卸载此服务时要安装或卸载的附加单元。
Service Parameters
此部分包含可在服务单元的[Service]部分中使用的参数。这些参数仅适用于systemd service单元。
Type
配置该服务的进程启动类型:
-
simple
- The service starts as the main process. This is the default. -
forking
- The service calls forked processes and run as part of the main daemon. -
oneshot
- Similar tosimple
, except the process must exit before systemd starts follow-up services. -
dbus
- Similar tosimple
, except the daemon acquires a name of the D-Bus bus. -
notify
- Similar tosimple
, except the daemon sends a notification message usingsd_notify
or an equivalent call after starting up. -
idle
- Similar tosimple
, except the execution of the service is delayed until all active jobs are dispatched.
RemainAfterExit
一个布尔值,指定即使服务的所有进程都退出了,该服务是否仍被认为是活动的。默认为no。
GuessMainPID
一个布尔值,指定如果无法可靠地确定服务的主PID, systemd是否应该猜测它。这个选项将被忽略,除非设置了Type=forking并且没有设置PIDFile。默认值为yes。
PIDFile
指向这个守护进程的PID文件的绝对文件名。对于Type=fork的服务,建议使用此选项。Systemd在服务启动后读取守护进程主进程的PID。Systemd不会写入此处配置的文件,尽管它会在服务关闭后删除该文件。
BusName
到达此服务的D-Bus总线名称。对于Type=dbus的服务,此选项是必须的。
ExecStart
服务启动时执行的命令和参数。
ExecStartPre, ExecStartPost
在ExecStart命令之前或之后执行的附加命令。
ExecReload
服务重新加载时要执行的命令和参数。
ExecStop
服务停止时要执行的命令和参数。
ExecStopPost
在服务停止后执行的附加命令。
RestartSec
重启服务前休眠的时间(以秒为单位)。
TimeoutStartSec
等待服务启动的时间,以秒为单位。
TimeoutStopSec
等待服务停止的时间,以秒为单位。
TimeoutSec
同时配置TimeoutStartSec和TimeoutStopSec的简写。
RuntimeMaxSec
服务运行的最大时间,以秒为单位。传递infinity
(默认值)以配置无运行时限制。
Restart
配置服务进程退出、终止或超时时是否重新启动服务:
-
no
- The service will not be restarted. This is the default. -
on-success
- Restart only when the service process exits cleanly (exit code 0). -
on-failure
- Restart only when the service process does not exit cleanly (node-zero exit code). -
on-abnormal
- Restart if the process terminates with a signal or when a timeout occurs. -
on-abort
- Restart if the process exits due to an uncaught signal not specified as a clean exit status. -
always
- Always restart.
将runlevels对应到targets
systemd targets提供一个与SysVinit runlevels相似的目的,但是表现得又有点不同。每个target都有一个名称而不是数字,每个target都有特定的用途。Systemd通过继承另一个target的所有服务并向其添加额外的服务来实现一些target。 一些systemd target模拟常见的sysvinit运行级别,这意味着您可以使用熟悉的telinit RUNLEVEL命令切换targets,在之前系统中安装的特定runlevels(0、1、3、5和6)与特定的systemd target有1:1的映射。
然而,用户自定义的运行级别2和4并不是如此的。要使用这些运行级别,创建一个新的命名systemd target,例如/etc/systemd/system/$YOURTARGET,该目标以一个现有的运行级别为基础,创建一个目录/etc/systemd/system/$YOURTARGET.wants,然后将要启用的附加服务符号链接到该目录中。
下面是SysVinit运行级别到systemd目标的映射。
Sysvinit Runlevel | systemd Target | Notes |
---|---|---|
0 | runlevel0.target, poweroff.target | Halt the system. |
1, s, single | runlevel1.target, rescue.target | Single user mode. |
2, 4 | runlevel2.target, runlevel4.target, multi-user.target | User-defined/Site-specific runlevels. By default, identical to 3. |
3 | runlevel3.target, multi-user.target | Multi-user, non-graphical. Users can usually login via multiple consoles or via the network. |
5 | runlevel5.target, graphical.target | Multi-user, graphical. Usually has all the services of runlevel 3 plus a graphical login. |
6 | runlevel6.target, reboot.target | Reboot |
emergency | emergency.target | Emergency shell |
对应service命令
下表演示了SysVinit命令的systemd等效命令。
所有最新版本,如果不使用服务名后缀,systemctl的都使用.service后缀。例如,systemctl启动frobozz.service与systemctl start frobozz相同。
Sysvinit Command | systemd Command | Notes |
---|---|---|
|
| Used to start a service (not reboot persistent) |
|
| Used to stop a service (not reboot persistent) |
|
| Used to stop and then start a service |
|
| When supported, reloads the config file without interrupting pending operations. |
|
| Restarts if the service is already running. |
|
| Tells whether a service is currently running. |
|
| Used to list the services that can be started or stopped |
|
| Turn the service on, for start at next boot, or other trigger. |
|
| Turn the service off for the next reboot, or any other trigger. |
|
| Used to check whether a service is configured to start or not in the current environment. |
|
| Print a table of services that lists which runlevels each is configured on or off |
|
| Print a table of services that will be started when booting into graphical mode |
|
| Used to list what levels this service is configured on or off |
|
| Used when you create a new service file or modify any configuration |
表中列出的所有/sbin/service和/sbin/chkconfig命令在基于systemd的系统上仍然可以继续工作。除了一个例外:
chkconfig --list