如何配置 Linux 服务以便在崩溃或重启后自动启动 - 第 1 部分:实用示例

作者选择了 自由和开源基金作为 写给捐款计划的一部分接受捐款。

介绍

在这两部分的教程中,您将学习如何配置一个Linux服务在使用systemd重新启动或崩溃后自动重新启动。

第一部分涵盖了一般的Linux服务管理概念,如initdaemonrunlevels。它以systemd的服务管理示范结束,在这里你将检查targets,wants,requiresunit文件。

第二部分提供了一个逐步的教程来完成一个实用的和常见的systemd任务,具体来说,您将配置一个MySQL数据库服务器在崩溃或重新启动后自动启动。

<$>[注] 注: 您也可以考虑阅读(我们非常流行的关于使用 `systemctl 来控制 systemd 服务和单元的教程)(https://andsky.com/tech/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-units)。

前提条件

要完成本教程,您将需要:

引入服务管理 DAEMON

Linux 服务可以在很大程度上通过改变服务管理 DAEMON(又称INIT DAEMON)处理的方式来实现自我治愈。

init是Linux系统在机器启动和内核加载到内存后启动的第一个过程,它决定了用户流程或系统服务应该如何加载,以何种顺序,以及是否应该自动启动。

随着Linux的演变,init大象的行为也一样。最初,Linux从系统Vinit开始,它是Unix中所使用的系统,从那时起,Linux就实现了Upstartinit大象(由Ubuntu创建),现在是系统dinit大象(由Fedora首次实现)。

大多数现代的Linux发行版已经逐步迁移到系统V,目前使用系统d。旧式init(如果使用)仅用于后向兼容性。

我们将在本文中涵盖 systemd,因为这是当今Linux发行版中使用的最新的和最常见的服务管理器,但在必要时我们还会谈论System V和Upstart,并看看系统d是如何从那里演变的。

  • System V 是最古老的init系统,用于 Debian 6 和之前的 * Ubuntu 9.04 和之前的 * CentOS 5 和之前的 * ** Upstart** 来自 System V 之后,被用于 * Ubuntu 9.10 到 Ubuntu 14.10,包括 Ubuntu 14.04 * CentOS 6 * ** systemd** 是最新的 Linux 服务管理器,用于 * Debian 7 和之前的 * Ubuntu 15.04 和以上的 * CentOS 7 和以上

要了解init大象,让我们从一个叫做runlevel的东西开始。

跑步

例如,运行水平可以是 Linux 服务器的关闭状态、单用户模式、重新启动模式等。

某些服务可以运行在一个或多个运行级别,但不能运行在其他级别。 运行级别以 0 到 6 之间的值表示。

  • Runlevel 0 :系统关闭 * ** Runlevel 1** :单用户,救援模式 * ** Runlevel 2, 3, 4** :多用户,网络启用文本模式 * ** Runlevel 5** :多用户,网络启用,图形模式 * ** Runlevel 6** :系统重新启动

运行级别2,3和4因分布而异,例如,一些Linux分布不执行运行级别4,而其他分布则有明显的区别,一般来说,运行级别2,3或4意味着Linux在多用户、网络启用、文本模式下启动的状态。

当你允许一个服务自动启动时,Linux实际上会将其添加到一个运行级别,例如在系统V中,操作系统将从一个特定的运行级别开始;当它启动时,它将尝试启动与该运行级别相关的所有服务。

引进系统Vinit戴蒙

System V 使用一个inittab文件,后来的init方法保持了后向兼容性。

  1. 联合国 " init " 守护进程由 二进制文件 / sbin/ init 创建
  2. 联合国 init守护进程的第一个文件是 /etc/inittab 3个 此文件中的一个条目决定了机器应该启动的运行级别. 例如,如果运行级的值被指定为3,Linux将在多用户中启动,文本模式启用了网络. (这个运行级别被称为默认运行级别) 4.四. 接下来,init守护进程进一步查看/etc/inittab文件并读取它需要运行的init脚本

因此,当init大象找到init脚本需要运行给定的运行水平时,它实际上正在找出需要启动的服务。

一个init脚本是控制一个特定的服务在系统 V. 服务的init脚本是由应用程序的供应商提供的,或与Linux发行版(原生服务)。

当一个过程或服务,如MySQL服务器在系统V下启动时,它的二进制程序文件必须加载到内存中。 根据服务的配置,这个程序可以连续执行背景(并接受客户端连接)。 启动,停止或重新加载这个二进制应用程序的工作由该服务的开始脚本处理。

在系统V中,一个init脚本是一个壳脚本,它们也被称为rc(运行命令)脚本,这些脚本位于/etc/init.d目录下。这些脚本与/etc/rc目录进行了同步链接。在/etc目录中,有多个rc目录,每个目录都有一个名称。数字代表不同的运行水平。所以我们有/etc/rc0.d,/etc/rc1.d,/etc/rc2.d等等。

要在事故或重新启动后重新启动服务,您通常可以在init脚本中添加这样的行:

1ms:2345:respawn:/bin/sh /usr/bin/service_name

若要允许系统 V 服务在系统启动时启动,请运行此命令:

1sudo chkconfig service_name on

要禁用它,请运行此命令:

1sudo chkconfig service_name off

要检查状态(运行或停止),运行此命令

1sudo service service_name status

引入Upstart Daemon

随着系统 V 的序列化工作和服务的加载方式变得越来越耗时和复杂,Upstart DAEMON 被引入用于更快的操作系统加载,优雅的服务崩溃的清理,以及系统服务之间的可预测依赖。

Upstartinit在几个方面比系统Vinit更好:

  • 联合国 并没处理装入和管理服务的北极壳脚本。 相反,它使用简单易懂和修改的配置文件
  • 服务没有像系统V那样连续装入,系统启动时间缩短
  • 联合国 它使用一个灵活的活动系统来定制各州如何处理服务
  • 联合国 启动有更好的方法 处理如何恢复崩溃的服务。
  • 联合国 没有必要保留一些多余的符号链接,它们都指向相同的脚本

为了让事情变得简单,Upstart 是与 System V 兼容的。 `/etc/init.d/rc’ 脚本仍在运行,以管理原生 System V 服务。 它的主要区别在于它允许多个事件与服务相关联的方式。 这种基于事件的架构使 Upstart 成为一个灵活的服务管理器。

  • 開始 * 開始 * 停止 * 停止

在这些事件之间,服务可以处于多个状态,如等待、预启动、启动、运行、预停、停止等。

在启动时,Upstart将正常运行任何系统Vinit脚本,然后在/etc/init目录下查看并执行每个服务配置文件中的壳命令。

这些文件具有service_name.conf的命名风格,并且具有不同的节点,称为 stanzas 的简单文本内容,每个 stanza 描述了服务的不同方面,以及该服务应该如何运作。

 1[label /etc/init/cron.conf]
 2
 3...
 4
 5description "regular background program processing daemon"
 6
 7start on runlevel [2345]
 8
 9stop on runlevel [!2345]
10
11expect fork
12
13**respawn**
14
15exec cron

引入systemd DAEMON

事实上,它不仅仅是一个init daemon:systemd是一个框架,涵盖了现代Linux系统的许多组件。

它的功能之一是作为Linux的系统和服务管理员工作,在这种能力下,systemd控制服务如果崩溃或机器重新启动时应该如何行为。

systemd 与 System V 命令和初始化脚本相反兼容,这意味着任何 System V 服务也将在 systemd 中运行,因为大多数 Upstart 和 System V 管理命令已被修改为在 systemd 中工作。

systemd 配置文件:单元文件

systemd 的核心是单元文件. 每个单元文件代表一个特定的系统资源. 有关该资源的信息在单元文件中进行跟踪. 服务单元文件是简单的文本文件(如 Upstart.conf 文件)具有声明语法。

systemd 與其他兩種「init」方法的主要區別在於 systemd 負責初始化服務 DAEMON 和其他類型的資源,如裝置作業系統路徑、安裝點、接口等。

目录结构

在像CentOS这样的基于Red Hat的系统中,单元文件位于两个位置. 主要位置是 /lib/systemd/system/. 自定义创建的单元文件或系统管理员修改的现有单元文件将生活在 /etc/systemd/system

假设一个服务在启动时或任何其他目标/运行级别启用,在这种情况下,将为该服务单元文件在/etc/systemd/system中的适当目录中创建一个象征链接。

systemd init 序列:目标单位

一个特殊类型的单元文件是 target unit

目标单元文件名为.target. 目标单元与其他单元文件不同,因为它们不代表一个特定的资源. 相反,它们代表系统的状态在任何时候。

例如,我们有multi-user.target而不是runlevel 3reboot.target而不是runlevel 6。当Linux服务器启动multi-user.target时,它基本上会将服务器带到runlevel 2, 3 或 4,这是具有网络功能的多用户文本模式。

它如何将服务器带到这个阶段,就是区别所在。 与 System V 不同,systemd 不会连续提供服务。 沿途,它可以检查其他服务或资源的存在,并决定其加载的顺序。

目标单位和运行级别的另一个区别在于,在 System V 中,Linux 系统只能存在一个运行级别,你可以更改运行级别,但系统只能存在于新的运行级别。

例如,一个使用图形用户界面启动的 Linux 系统将有 graphical.target 启用,这反过来会自动确保 multi-user.target 也被加载和激活。

下表比较了跑步水平和目标:

Runlevel (System V init)Target Units (Systemd)
runlevel 0poweroff.target
runlevel 1resuce.target
runlevel 2, 3, 4multi-user.target
runlevel 5graphical.target
runlevel 6reboot.target

系统d 默认。目标

systemd default.target 等同于 System V 默认运行级别。

在 systemd 中,该文件被 default.target 取代,默认的目标单元文件居住在 /etc/systemd/system 目录下,它是指向 /lib/systemd/system 下的目标单元文件之一的象征链接。

当您更改默认目标时,您基本上正在重建该象征链接并改变系统的运行水平。

System V中的 inittab 文件还指定了 Linux 将从哪个目录执行其init脚本:它可能是任何 rcn.d 目录。

當單位被激活時,所有單位都會並行或連續激活,一個資源單位的負載方式可能取決於它想要或需要的其他資源單位。

systemd 依赖:想要和要求

systemd wants 和 ** requires** 控制 systemd 如何解决服务 DAEMON 之间的依赖。

如前所述,Upstart使用配置文件确保了服务的并行加载。在System V中,一个服务可以在特定运行级别开始,但也可以等到另一个服务或资源变得可用。

在 systemd 中,需要另一个单元的单元不会启动,直到所需单元被加载和激活。

这确保了系统的稳定性。这样一来,一个要求某个特定目录存在的服务可以让它等到该目录的安装点是活跃的。另一方面,一个想要另一个单元的单元不会施加这种限制。

实用示例:了解系统d 启动序列

为了了解 systemd 中的服务启动行为,我们正在使用 CentOS 8.3 Droplet. 我们将尽可能地遵循.target rabbit-trail。

首先,让我们运行此命令来列出默认目标单元文件:

1sudo ls -l /etc/systemd/system/default.target

这表明输出如下:

1[secondary_label Output]
2lrwxrwxrwx. 1 root root 37 Dec 4 17:42 /etc/systemd/system/default.target -> /lib/systemd/system/multi-user.target

正如你所看到的,默认目标实际上是一个象征性的链接到 /lib/systemd/system 下的多用户目标文件,因此,系统应该在 multi-user.target 中启动,这类似于 System V init 中的 runlevel 3。

多用户.目标。

接下来,让我们运行以下命令来检查 multi-user.target 文件想要的所有服务:

1sudo ls -l /etc/systemd/system/multi-user.target.wants/*.service

这应该显示一个符号链接文件列表,指向 /usr/lib/systemd/system/下面的实际单元文件:

1[secondary_label Output]
2lrwxrwxrwx. 1 root root 38 Dec 4 17:38 /etc/systemd/system/multi-user.target.wants/auditd.service -> /usr/lib/systemd/system/auditd.service
3lrwxrwxrwx. 1 root root 39 Dec 4 17:39 /etc/systemd/system/multi-user.target.wants/chronyd.service -> /usr/lib/systemd/system/chronyd.service
4lrwxrwxrwx. 1 root root 37 Dec 4 17:38 /etc/systemd/system/multi-user.target.wants/crond.service -> /usr/lib/systemd/system/crond.service
5lrwxrwxrwx. 1 root root 42 Dec 4 17:39 /etc/systemd/system/multi-user.target.wants/irqbalance.service -> /usr/lib/systemd/system/irqbalance.service
6lrwxrwxrwx. 1 root root 37 Dec 4 17:41 /etc/systemd/system/multi-user.target.wants/kdump.service -> /usr/lib/systemd/system/kdump.service
7...

除了「multi-user.target」之外,还有不同类型的目标,例如「system-update.target」或「basic.target」。

1sudo systemctl show --property "Requires" multi-user.target | fmt -10

产出显示:

1[secondary_label Output]
2Requires=basic.target

关键字: 目标

您可以运行以下命令,以查看 basic.target 是否需要任何单位:

1sudo systemctl show --property "Requires" basic.target | fmt -10

事实证明, basic.target 需要 sysinit.target:

1[secondary_label Output]
2Requires=sysinit.target
3-.mount

它也需要一些目标:

1sudo systemctl show --property "Wants" basic.target | fmt -10

命令将返回如下:

1[secondary_label Output]
2Wants=slices.target
3paths.target
4timers.target
5microcode.service
6sockets.target
7sysinit.target

回归,您可以看到 sysinit.target 是否还需要其他目标运行:

1sudo systemctl show --property "Requires" sysinit.target | fmt -10

但是,sysinit.target 想要的其他目标将是:

1systemctl show --property "Wants" sysinit.target | fmt -10

这样的输出会出现:

 1[secondary_label Output]
 2Wants=systemd-random-seed.service
 3dev-mqueue.mount
 4rngd.service
 5systemd-modules-load.service
 6proc-sys-fs-binfmt_misc.automount
 7local-fs.target
 8sys-fs-fuse-connections.mount
 9systemd-sysusers.service
10systemd-update-done.service
11systemd-update-utmp.service
12systemd-journal-flush.service
13dev-hugepages.mount
14dracut-shutdown.service
15swap.target
16systemd-udevd.service
17import-state.service
18sys-kernel-debug.mount
19nis-domainname.service
20systemd-journald.service
21selinux-autorelabel-mark.service
22kmod-static-nodes.service
23loadmodules.service
24ldconfig.service
25cryptsetup.target
26systemd-sysctl.service
27systemd-ask-password-console.path
28systemd-journal-catalog-update.service
29systemd-udev-trigger.service
30systemd-tmpfiles-setup.service
31systemd-hwdb-update.service
32sys-kernel-config.mount
33systemd-binfmt.service
34systemd-tmpfiles-setup-dev.service
35systemd-machine-id-commit.service
36systemd-firstboot.service

检查一个systemd单元文件

现在再进一步一步,让我们看看服务单元文件的内部,即 sshd 的文件:

1sudo vi /etc/systemd/system/multi-user.target.wants/sshd.service

它看起来像这样:

 1[label /etc/systemd/system/multi-user.target.wants/sshd.service]
 2[Unit]
 3Description=OpenSSH server daemon
 4Documentation=man:sshd(8) man:sshd_config(5)
 5After=network.target sshd-keygen.target
 6Wants=sshd-keygen.target
 7
 8[Service]
 9Type=notify
10EnvironmentFile=-/etc/crypto-policies/back-ends/opensshserver.config
11EnvironmentFile=-/etc/sysconfig/sshd
12ExecStart=/usr/sbin/sshd -D $OPTIONS $CRYPTO_POLICY
13ExecReload=/bin/kill -HUP $MAINPID
14KillMode=process
15Restart=on-failure
16RestartSec=42s
17
18[Install]
19WantedBy=multi-user.target

您可以看到服务单元文件清洁,易于理解。

第一个重要部分是[单位]部分中的条款,这意味着在加载 network.target 和 sshd-keygen.target 后, sshd 服务需要加载。

[安装]部分显示了多用户.target 想要的服务,这意味着多用户.target 将加载 sshd 戴蒙,但如果 sshd 在加载过程中失败,它不会关闭或崩溃。

由于「multi-user.target」是默认的目标,所以 sshd daemon 应该在启动时启动。 在「[服务]」部分中,「重启」参数具有值「在故障时」。

结论

在本文中,您了解了 System V、Upstart 和 systemd 服务管理 DAEMON,您探索了启动脚本和配置文件,重要参数,启动序列,以及控制服务启动行为的命令。

在本文的第二部分中,我们将将这些技能应用于现实生活中的例子,并使用systemd来配置MySQL。一旦完成,您的MySQL实例将在重新启动或崩溃后自动重新启动。

Published At
Categories with 技术
comments powered by Disqus