如何使用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

这将删除指示服务应自动启动的符号链接。

请记住,启用服务不会在当前会话中启动它。 如果您希望启动该服务并在启动时启用它,则必须同时发出 startenable 命令。

检查服务状态

要检查系统上服务的状态,可以使用 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

这将返回当前单元状态,通常为 activeinactive。 如果退出代码处于活动状态,则退出代码将为“0”,从而使结果更易于在 shell 脚本中解析。

要查看该单元是否启用,可以使用 is-enabled 命令:

systemctl is-enabled application.service

这将输出服务是 enabled 还是 disabled,并根据命令问题的答案再次将退出代码设置为“0”或“1”。

第三个检查是该单元是否处于故障状态。 这表明启动相关单元时出现问题:

systemctl is-failed application.service

如果运行正常,这将返回 active,如果发生错误,则返回 failed。 如果单元被故意停止,它可能会返回 unknowninactive。 退出状态“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
. . .

输出具有以下列:

  • UNITsystemd 单位名称
  • 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
. . .

状态通常为 enableddisabledstaticmasked。 在这种情况下,静态意味着单元文件不包含用于启用单元的 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/journalctllogind/loginctl)。 花时间熟悉这些其他工具和守护程序将使管理变得更容易。