如何使用Systemctl管理Systemd服务和单元
介绍
systemd
是一个初始化系统和系统管理器,已广泛成为 Linux 发行版的新标准。 由于它的大量采用,熟悉 systemd
是值得的,因为它将使管理服务器变得相当容易。 了解和使用构成 systemd
的工具和守护程序将帮助您更好地了解它提供的强大功能、灵活性和功能,或者至少可以帮助您更轻松地完成工作。
在本指南中,我们将讨论 systemctl
命令,它是用于控制 init 系统的中央管理工具。 我们将介绍如何管理服务、检查状态、更改系统状态以及使用配置文件。
请注意,尽管 systemd
已成为许多 Linux 发行版的默认初始化系统,但它并未在所有发行版中普遍实现。 在您阅读本教程时,如果您的终端输出错误 bash: systemctl is not installed
,那么您的机器很可能安装了不同的 init 系统。
服务管理
init 系统的基本目的是初始化 Linux 内核启动后必须启动的组件(传统上称为“用户态”组件)。 init 系统还用于在系统运行时随时管理服务器的服务和守护程序。 考虑到这一点,我们将从一些基本的服务管理操作开始。
在 systemd
中,大多数动作的目标是“单元”,即 systemd
知道如何管理的资源。 单元按它们所代表的资源类型进行分类,并使用称为单元文件的文件进行定义。 每个单元的类型可以从文件末尾的后缀中推断出来。
对于服务管理任务,目标单元为服务单元,其单元文件后缀为.service
。 但是,对于大多数服务管理命令,您实际上可以省略 .service
后缀,因为 systemd
足够聪明,可以知道您在使用服务管理命令时可能想要对服务进行操作。
启动和停止服务
要启动 systemd
服务,执行服务单元文件中的指令,使用 start
命令。 如果您以非 root 用户身份运行,则必须使用 sudo
因为这会影响操作系统的状态:
sudo systemctl start application.service
正如我们上面提到的,systemd
知道为服务管理命令查找 *.service
文件,因此可以这样键入命令:
sudo systemctl start application
尽管您可以将上述格式用于一般管理,但为了清楚起见,我们将在其余命令中使用 .service
后缀,以明确我们正在操作的目标。
要停止当前正在运行的服务,您可以使用 stop
命令代替:
sudo systemctl stop application.service
重新启动和重新加载
要重启正在运行的服务,可以使用 restart
命令:
sudo systemctl restart application.service
如果有问题的应用程序能够重新加载其配置文件(无需重新启动),您可以发出 reload
命令来启动该过程:
sudo systemctl reload application.service
如果您不确定服务是否具有重新加载其配置的功能,您可以发出 reload-or-restart
命令。 如果可用,这将就地重新加载配置。 否则,它将重新启动服务,以便获取新配置:
sudo systemctl reload-or-restart application.service
启用和禁用服务
上述命令对于在当前会话期间启动或停止服务很有用。 要告诉 systemd
在启动时自动启动服务,您必须启用它们。
要在启动时启动服务,请使用 enable
命令:
sudo systemctl enable application.service
这将创建一个符号链接,从系统的服务文件副本(通常在 /lib/systemd/system
或 /etc/systemd/system
中)到磁盘上 systemd
查找自动启动文件的位置(通常 [ X189X]。 我们将在本指南后面介绍目标是什么)。
要禁用服务自动启动,您可以键入:
sudo systemctl disable application.service
这将删除指示服务应自动启动的符号链接。
请记住,启用服务不会在当前会话中启动它。 如果您希望启动该服务并在启动时启用它,则必须同时发出 start
和 enable
命令。
检查服务状态
要检查系统上服务的状态,可以使用 status
命令:
systemctl status application.service
这将为您提供服务状态、cgroup 层次结构和前几行日志。
例如,在检查 Nginx 服务器的状态时,您可能会看到如下输出:
Output● nginx.service - A high performance web server and a reverse proxy server Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled) Active: active (running) since Tue 2015-01-27 19:41:23 EST; 22h ago Main PID: 495 (nginx) CGroup: /system.slice/nginx.service ├─495 nginx: master process /usr/bin/nginx -g pid /run/nginx.pid; error_log stderr; └─496 nginx: worker process Jan 27 19:41:23 desktop systemd[1]: Starting A high performance web server and a reverse proxy server... Jan 27 19:41:23 desktop systemd[1]: Started A high performance web server and a reverse proxy server.
这使您可以很好地了解应用程序的当前状态,通知您任何问题和可能需要的任何操作。
还有一些检查特定状态的方法。 例如,要检查一个单元当前是否处于活动状态(正在运行),您可以使用 is-active
命令:
systemctl is-active application.service
这将返回当前单元状态,通常为 active
或 inactive
。 如果退出代码处于活动状态,则退出代码将为“0”,从而使结果更易于在 shell 脚本中解析。
要查看该单元是否启用,可以使用 is-enabled
命令:
systemctl is-enabled application.service
这将输出服务是 enabled
还是 disabled
,并根据命令问题的答案再次将退出代码设置为“0”或“1”。
第三个检查是该单元是否处于故障状态。 这表明启动相关单元时出现问题:
systemctl is-failed application.service
如果运行正常,这将返回 active
,如果发生错误,则返回 failed
。 如果单元被故意停止,它可能会返回 unknown
或 inactive
。 退出状态“0”表示发生故障,退出状态“1”表示任何其他状态。
系统状态概述
到目前为止,这些命令对于管理单个服务很有用,但它们对于探索系统的当前状态并不是很有帮助。 有许多 systemctl
命令可提供此信息。
列出当前单位
要查看 systemd
知道的所有活动单元的列表,我们可以使用 list-units
命令:
systemctl list-units
这将向您显示 systemd
当前在系统上处于活动状态的所有单元的列表。 输出将如下所示:
OutputUNIT LOAD ACTIVE SUB DESCRIPTION atd.service loaded active running ATD daemon avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack dbus.service loaded active running D-Bus System Message Bus dcron.service loaded active running Periodic Command Scheduler dkms.service loaded active exited Dynamic Kernel Modules System getty@tty1.service loaded active running Getty on tty1 . . .
输出具有以下列:
- UNIT:
systemd
单位名称 - LOAD:单元的配置是否已经被
systemd
解析。 加载单元的配置保存在内存中。 - ACTIVE:关于单元是否处于活动状态的摘要状态。 这通常是判断单元是否成功启动的相当基本的方法。
- SUB:这是一个较低级别的状态,表示有关单元的更多详细信息。 这通常因单元类型、状态和单元运行的实际方法而异。
- DESCRIPTION:单位是什么/做什么的简短文字描述。
由于 list-units
命令默认仅显示活动单位,因此上述所有条目将在 LOAD 列中显示 loaded
,在 ACTIVE 列中显示 active
。 这个显示实际上是 systemctl
在没有附加命令的情况下调用时的默认行为,所以如果你在没有参数的情况下调用 systemctl
你会看到同样的事情:
systemctl
我们可以通过添加额外的标志来告诉 systemctl
输出不同的信息。 例如,要查看 systemd
已加载(或尝试加载)的所有单元,无论它们当前是否处于活动状态,您都可以使用 --all
标志,如下所示:
systemctl list-units --all
这将显示 systemd
加载或尝试加载的任何单元,无论其当前在系统上的状态如何。 某些单元在运行后变为非活动状态,并且 systemd
尝试加载的某些单元可能尚未在磁盘上找到。
您可以使用其他标志来过滤这些结果。 例如,我们可以使用 --state=
标志来指示我们希望看到的 LOAD、ACTIVE 或 SUB 状态。 您必须保留 --all
标志,以便 systemctl
允许显示非活动单位:
systemctl list-units --all --state=inactive
另一个常见的过滤器是 --type=
过滤器。 我们可以告诉 systemctl
只显示我们感兴趣的类型的单位。 例如,要仅查看活动服务单元,我们可以使用:
systemctl list-units --type=service
列出所有单元文件
list-units
命令仅显示 systemd
尝试解析并加载到内存中的单元。 由于 systemd
只会读取它认为需要的单位,这不一定包括系统上所有可用的单位。 要查看 systemd
路径中的 every 可用单元文件,包括 systemd
未尝试加载的单元文件,可以使用 list-unit-files
命令代替:
systemctl list-unit-files
单位是 systemd
知道的资源的表示。 由于 systemd
不一定会读取此视图中的所有单元定义,因此它仅显示有关文件本身的信息。 输出有两列:单元文件和状态。
OutputUNIT FILE STATE proc-sys-fs-binfmt_misc.automount static dev-hugepages.mount static dev-mqueue.mount static proc-fs-nfsd.mount static proc-sys-fs-binfmt_misc.mount static sys-fs-fuse-connections.mount static sys-kernel-config.mount static sys-kernel-debug.mount static tmp.mount static var-lib-nfs-rpc_pipefs.mount static org.cups.cupsd.path enabled . . .
状态通常为 enabled
、disabled
、static
或 masked
。 在这种情况下,静态意味着单元文件不包含用于启用单元的 install
部分。 因此,这些单位无法启用。 通常,这意味着该单元执行一次性操作或仅用作另一个单元的依赖项,不应单独运行。
我们将暂时介绍 masked
的含义。
单位管理
到目前为止,我们一直在使用服务并显示有关 systemd
知道的单元和单元文件的信息。 但是,我们可以使用一些附加命令找到有关单位的更多具体信息。
显示单元文件
要显示 systemd
已加载到其系统中的单元文件,您可以使用 cat
命令(这是在 systemd
版本 209 中添加的)。 例如,要查看 atd
调度守护进程的单元文件,我们可以输入:
systemctl cat atd.service
Output[Unit] Description=ATD daemon [Service] Type=forking ExecStart=/usr/bin/atd [Install] WantedBy=multi-user.target
输出是当前运行的 systemd
进程已知的单元文件。 如果您最近修改了单元文件,或者您正在覆盖单元文件片段中的某些选项(我们将在稍后介绍),这可能很重要。
显示依赖项
要查看单元的依赖关系树,可以使用 list-dependencies
命令:
systemctl list-dependencies sshd.service
这将显示一个层次结构,映射为启动相关单元必须处理的依赖关系。 在这种情况下,依赖关系包括那些上面的单元需要或想要的单元。
Outputsshd.service ├─system.slice └─basic.target ├─microcode.service ├─rhel-autorelabel-mark.service ├─rhel-autorelabel.service ├─rhel-configure.service ├─rhel-dmesg.service ├─rhel-loadmodules.service ├─paths.target ├─slices.target . . .
递归依赖项仅显示为 .target
单位,表示系统状态。 要递归列出所有依赖项,请包含 --all
标志。
要显示反向依赖关系(依赖于指定单位的单位),您可以在命令中添加 --reverse
标志。 其他有用的标志是 --before
和 --after
标志,它们可用于显示依赖于指定单位的单位,这些单位分别在其之前和之后开始。
检查单元属性
要查看单元的低级属性,可以使用 show
命令。 这将显示使用 key=value
格式为指定单位设置的属性列表:
systemctl show sshd.service
OutputId=sshd.service Names=sshd.service Requires=basic.target Wants=system.slice WantedBy=multi-user.target Conflicts=shutdown.target Before=shutdown.target multi-user.target After=syslog.target network.target auditd.service systemd-journald.socket basic.target system.slice Description=OpenSSH server daemon . . .
如果要显示单个属性,可以将 -p
标志与属性名称一起传递。 例如,要查看 sshd.service
单元的冲突,您可以键入:
systemctl show sshd.service -p Conflicts
OutputConflicts=shutdown.target
掩蔽和取消掩蔽单元
我们在服务管理部分看到了如何停止或禁用服务,但是 systemd
还可以通过将其链接到 /dev/null
。 这称为屏蔽单元,可以使用 mask
命令:
sudo systemctl mask nginx.service
这将阻止 Nginx 服务自动或手动启动,只要它被屏蔽。
如果您检查 list-unit-files
,您将看到该服务现在被列为屏蔽:
systemctl list-unit-files
Output. . . kmod-static-nodes.service static ldconfig.service static mandb.service static messagebus.service static nginx.service masked quotaon.service static rc-local.service static rdisc.service disabled rescue.service static . . .
如果您尝试启动该服务,您将看到如下消息:
sudo systemctl start nginx.service
OutputFailed to start nginx.service: Unit nginx.service is masked.
要取消屏蔽一个单元,使其再次可用,请使用 unmask
命令:
sudo systemctl unmask nginx.service
这将使设备返回到之前的状态,允许它被启动或启用。
编辑单元文件
虽然单元文件的具体格式超出了本教程的范围,但 systemctl
提供了内置机制,用于在您需要进行调整时编辑和修改单元文件。 此功能是在 systemd
版本 218 中添加的。
默认情况下,edit
命令将为相关单元打开一个单元文件片段:
sudo systemctl edit nginx.service
这将是一个空白文件,可用于覆盖或添加指令到单元定义。 将在 /etc/systemd/system
目录中创建一个目录,其中包含附加了 .d
的单元名称。 例如,对于 nginx.service
,将创建一个名为 nginx.service.d
的目录。
在此目录中,将创建一个名为 override.conf
的片段。 加载单元时,systemd
将在内存中将覆盖片段与完整的单元文件合并。 片段的指令将优先于原始单元文件中的指令。
如果你想编辑完整的单元文件而不是创建一个片段,你可以传递 --full
标志:
sudo systemctl edit --full nginx.service
这会将当前的单元文件加载到编辑器中,可以在编辑器中对其进行修改。 当编辑器退出时,更改的文件将被写入 /etc/systemd/system
,这将优先于系统的单位定义(通常在 /lib/systemd/system
的某处找到)。
要删除您所做的任何添加,请删除设备的 .d
配置目录或从 /etc/systemd/system
中修改的服务文件。 例如,要删除一个片段,我们可以输入:
sudo rm -r /etc/systemd/system/nginx.service.d
要删除完整修改的单元文件,我们将键入:
sudo rm /etc/systemd/system/nginx.service
删除文件或目录后,您应该重新加载 systemd
进程,以便它不再尝试引用这些文件并恢复使用系统副本。 您可以通过键入以下内容来执行此操作:
sudo systemctl daemon-reload
使用目标调整系统状态(运行级别)
目标是描述系统状态或同步点的特殊单元文件。 与其他单位一样,定义目标的文件可以通过其后缀来标识,在本例中为 .target
。 目标本身不做太多事情,而是用于将其他单位组合在一起。
这可以用来使系统进入某些状态,就像其他 init 系统使用运行级别一样。 它们用作某些功能可用时的参考,允许您指定所需的状态,而不是产生该状态所需的单个单元。
例如,有一个 swap.target
用于指示交换已准备好使用。 作为此过程一部分的单元可以通过在其配置中指示它们是 WantedBy=
或 RequiredBy=
或 swap.target
来与此目标同步。 需要交换可用的单元可以使用 Wants=
、Requires=
和 After=
规范指定此条件,以指示它们关系的性质。
获取和设置默认目标
systemd
进程有一个在引导系统时使用的默认目标。 满足来自该单个目标的级联依赖关系将使系统进入所需状态。 要查找系统的默认目标,请键入:
systemctl get-default
Outputmulti-user.target
如果您想设置不同的默认目标,您可以使用 set-default
。 例如,如果您安装了一个图形桌面并且您希望系统默认启动到该桌面,您可以相应地更改您的默认目标:
sudo systemctl set-default graphical.target
列出可用目标
您可以通过键入以下内容获取系统上可用目标的列表:
systemctl list-unit-files --type=target
与运行级别不同,多个目标可以同时处于活动状态。 激活的目标表示 systemd
已尝试启动与目标绑定的所有单元,并且没有尝试再次拆除它们。 要查看所有活动目标,请键入:
systemctl list-units --type=target
隔离目标
可以启动与目标关联的所有单元并停止不属于依赖关系树的所有单元。 我们需要执行此操作的命令适当地称为 isolate
。 这类似于在其他初始化系统中更改运行级别。
例如,如果您在 graphical.target
处于活动状态的图形环境中操作,则可以通过隔离 multi-user.target
来关闭图形系统并使系统进入多用户命令行状态。 由于 graphical.target
依赖于 multi-user.target
而不是相反,所有图形单元都将停止。
在执行此过程之前,您可能希望查看您正在隔离的目标的依赖关系,以确保您没有停止重要服务:
systemctl list-dependencies multi-user.target
当您对将保持活动的单位感到满意时,您可以通过键入以下内容来隔离目标:
sudo systemctl isolate multi-user.target
使用重要事件的快捷方式
为重要事件定义了目标,例如关闭或重新启动。 但是,systemctl
也有一些添加一些额外功能的快捷方式。
例如,要将系统置于救援(单用户)模式,您可以使用 rescue
命令代替 isolate rescue.target
:
sudo systemctl rescue
这将提供向所有登录用户发出事件警报的附加功能。
要停止系统,您可以使用 halt
命令:
sudo systemctl halt
要启动完全关闭,您可以使用 poweroff
命令:
sudo systemctl poweroff
可以使用 reboot
命令启动重启:
sudo systemctl reboot
这些都向登录用户发出事件正在发生的警报,而仅运行或隔离目标不会执行此操作。 请注意,大多数机器将为这些操作链接更短、更常规的命令,以便它们与 systemd
一起正常工作。
例如,要重新启动系统,您通常可以键入:
sudo reboot
结论
到目前为止,您应该熟悉 systemctl
命令的一些基本功能,这些功能允许您与 systemd
实例进行交互和控制。 systemctl
实用程序将成为您进行服务和系统状态管理的主要交互点。
虽然 systemctl
主要使用核心 systemd
进程运行,但 systemd
生态系统的其他组件由其他实用程序控制。 其他功能,如日志管理和用户会话,由单独的守护程序和管理实用程序处理(分别为 journald
/journalctl
和 logind
/loginctl
)。 花时间熟悉这些其他工具和守护程序将使管理变得更容易。