简介
在计算领域,事情并不总是按计划进行。通常,意外的系统崩溃会促使系统管理员启动重启并重新启动单个服务。在系统崩溃或重启后,找出并重新启动应用程序运行所需的每个服务可能会非常繁琐。在这个由两部分组成的教程的第一部分中,我们将通过实际示例向您展示如何配置服务以在系统崩溃或服务器重启后自动启动。第二部分将涵盖理论信息,关于我们在第一部分中实现的内容。
我们将使用 MySQL 数据库服务进行实际示例。然而,同样的原理也适用于构成完整服务器的其他进程,例如 Nginx, Apache, Redis,或其他应用程序。您可以查看我们关于 如何安装 MySQL, Nginx,以及 Apache.
在 Linux 发行版中,有三个主要的 初始化 (init) 系统,具体取决于您运行的发行版。某些发行版可能带有两个或多个 init 系统,如下所述:
- System V – 存在于较旧发行版中的较旧 init 系统,例如:
- Ubuntu 9.04 及更早版本
- CentOS 5 及更早版本
- Debian 6 及更早版本
- Upstart – 用于以前的发行版,例如:
- CentOS 6
- Ubuntu 9.10 至 Ubuntu 14.10 以及 Ubuntu 14.04
- Systemd – 用于最新的发行版,例如:
- CentOS 7
- Debian 7 和 8。
- Ubuntu 15.04 及更新版本
背景
操作系统,尤其是 Linux 和 Unix 系统,在后台运行进程和服务是很常见的。此类服务可能随操作系统软件一起提供。有些可能随您安装的用户应用程序一起提供。
操作系统服务包括:
- sshd – 它是允许远程连接的守护进程。
- cupsd – 它是控制打印的守护进程。
已安装的应用程序服务包括:
- httpd/apache2 – Apache2 Web 服务器自带的服务。
- nginx – Nginx Web 服务器自带的服务。
为了确保我们的 Web 应用程序、数据库、邮件服务器等可以访问,此类服务必须持续运行。如果您是系统管理员或好奇的应用程序开发人员,您希望确保此类服务持续运行,并且在不幸发生系统崩溃的情况下,它们在系统重启后自动启动。这正是我们将在本动手教程中学习的内容。
虽然设置警报并持续监控您的 Linux 发行版至关重要,但如果配置得当,一些 Linux 服务可以自我修复,这要归功于管理服务的 init 系统。
在 Linux 发行版中,有一些实现系统初始化的模式操作,称为 运行级别。要使服务自动启动,必须将其添加到运行级别中。每个类 Linux 和 Unix 系统都有四个常见的运行级别,如下所示:
- 0 – 运行级别 0 表示系统关机。
- 1 – 运行级别 1 表示单用户、救援模式。
- 2, 3, 4 – 这些运行级别表示系统已在多用户、启用网络、文本模式下启动的状态。
- 5 – 运行级别 5 表示多用户、启用网络、图形模式。
- 6 – 运行级别 6 表示系统重启。
在本教程中,您将学习如何使用前面解释的三种不同的 init 模式(System V、Upstart 和 Systemd)配置 Linux 服务在系统重启时自动启动.
前提条件
本动手教程需要您拥有一个可用于后续操作的 Linux VPS。您可以利用 Cloudsigma 的免费试用期 并启动一些服务器来尝试这些命令。您可以按照我们的 关于如何设置 Ubuntu 服务器的分步教程.
您在本教程中创建的服务器纯粹是为了进行动手实践,您不应该在生产服务器上尝试这些命令,因为许多服务会被中断。
您将需要的一些发行版:
- Ubuntu 9.04 及更早版本,或 Debian 6 x64(将用于演示 System V init 系统)
- Ubuntu 14.04 x64(将用于演示 Upstart)
- CentOS 7 x64(将用于演示 systemd)。
请确保您已设置了具有 sudo 权限的非 root 用户。您可以查看我们的 此处的配置 sudoers 文件教程.
使用 System V
这是最古老的 init 系统,曾用于早期的 Linux 发行版,例如:
- Debian 6 及更早版本
- CentOS 5 及更早版本
- Ubuntu 9.04 及更早版本
大多数可安装的服务器应用程序(如 MySQL 和 Nginx)默认都带有保存于 /etc/init.d 目录中的 init 脚本。这些脚本使它们能够在重启后启动。但是,它们可能未配置为在系统崩溃后自动启动。
System V 自动启动检查清单
第一步是检查 /etc/init.d/service 目录中是否存在可用的 Bash init 脚本。要在 Debian 或 Ubuntu 发行版中启用该服务,请使用 update-rc.d 命令,在 CentOS 系统中,使用 chkconfig。请替换为您实际的服务名称:
|
1 |
sudo update-rc.d service enable |
上述命令会在 /etc/rc2.d 目录中创建一个符号链接,如下面的输出所示。请勿自行创建,因为它是自动生成的:
|
1 |
lrwxrwxrwx 1 root root 20 Dec 10 07:09 S02mysql -> ../init.d/service |
在文件 /etc/inittab 的底部,添加一行 respawn,如下面的通用示例所示。请记得将其替换为您应用程序启动脚本的实际路径:
|
1 |
id:2345:respawn:/bin/sh /path/to/your-application/startup |
输入以下命令来停止和启动该服务:
|
1 2 |
sudo service service-name stop sudo service service-name start |
接下来,重启服务器:
|
1 |
sudo reboot |
如何测试更改?
重启服务器后,使用以下命令搜索进程号,以验证服务是否已启动:
|
1 |
ps -ef | grep service-name |
使用以下命令杀死该进程:
|
1 |
sudo kill -9 process_number |
五分钟后,验证该服务是否已正常运行。
使用真实服务进行 System V 实际配置
在接下来的步骤中,我们将尝试一个真实的服务器应用程序,例如 MySQL。您应该能够访问一个 Debian 6 虚拟机。使用具有 sudo 权限的账户,通过 SSH 或 putty (如果您使用的是 Windows 桌面)连接到它。
步骤 1:安装 MySQL
输入以下命令安装 MySQL:
|
1 |
sudo apt-get install mysql-server -y |
开始安装时,系统会提示您输入 root 密码。然后,输入您选择的密码并确认。等待安装完成,然后输入以下命令开始对 MySQL 进行安全配置:
|
1 |
mysql_secure_installation |
系统会提示您输入之前设置的 root 密码。按 N 保持不变。接下来,按 Y 接受后续提示,以删除匿名用户、禁用远程 root 登录并删除测试数据库。最后,接受重新加载权限表,使更改自动生效。
这就完成了 MySQL 的安装。您可以通过输入以下命令来检查服务是否正在运行:
|
1 |
service mysql status |
步骤 2:配置 MySQL 在重启后自动启动
MySQL 默认情况下配置为在系统重启后启动。您可以在 /etc/rc2.d 目录中找到指向 MySQL 初始化脚本的符号链接。这些符号链接不是手动创建的。您可以使用 update-rc.d 命令来启用和禁用服务。
输入以下命令列出该目录的内容:
|
1 |
ls -l /etc/rc2.d |
检查您是否能注意到指向 MySQL init 脚本的符号链接:
|
1 |
lrwxrwxrwx 1 root root 15 Dec 2 10:42 S01mysql -> ../init.d/mysql |
其中 S 非常重要,因为只要您能看到一个 S 服务默认运行级别目录下的脚本,init 系统将在服务器启动时启动该服务。要验证 MySQL 是否会在重启后自动启动,请输入以下命令重启系统:
|
1 |
sudo reboot |
您的 ssh 连接在重启期间会断开。请等待一两分钟,然后重新连接。运行以下命令检查服务是否正在运行:
|
1 |
service mysql status |
输出将指示服务正在运行。这意味着它在重启后自动启动。对于未配置为自动启动的服务,您必须自己进行配置。
我们可以禁用 MySQL 服务并重启系统以测试它是否会自动启动。在 Debian 和 Ubuntu 系统中,您可以使用 update-rc.d 命令从 init 系统中添加或删除服务。输入以下命令禁用 MySQL 服务:
|
1 |
sudo update-rc.d mysql disable |
重启系统并使用 ssh 重新连接。尝试使用以下命令连接到 MySQL:
|
1 |
mysql -u root -p |
您将收到类似以下的 MySQL 错误:
|
1 |
ERROR 2002 (HY000): Can't connect to local MySQL server |
然后,输入以下命令重新启用该服务:
|
1 |
sudo update-rc.d mysql enable |
如果您使用的是 CentOS 发行版,命令将是:
|
1 |
sudo chkconfig mysql enable |
由于 MySQL 最初没有启动,您必须启动它。输入以下命令:
|
1 |
sudo service mysql start |
步骤 3:配置服务 (MySQL) 在系统崩溃后自动启动
System V 在崩溃后不会自动启动进程。我们可以通过查找 MySQL 进程 ID 并将其终止来模拟系统崩溃。输入以下命令查找 MySQL 进程 ID:
|
1 |
ps -ef | grep mysql |
从输出中找到 MySQL 进程。运行 MySQL 的主要进程是 mysqld_safe 和 mysqld。记录它们的进程 ID(这些是数字),并使用以下命令终止它们:
|
1 2 |
sudo kill -9 mysqldsafe_number sudo kill -9 mysqld_number |
使用以下命令检查 MySQL 服务 status:
|
1 |
sudo service mysql status |
输出将指示 MySQL 已停止。我们可以使用 service start 命令手动重启它。但是,我们希望这是一个自动过程。为了实现这种自动行为,我们需要编辑 /etc/inittab 文件。这是 System V init 在启动时读取的第一个文件。 /etc/inittab 文件包含有关进程在崩溃时应如何表现的指令。如果配置得当,它会在发生崩溃时再次重启系统。在我们的案例中,我们要确保 MySQL 是这些服务之一。
该 /etc/inittab 文件对 Linux 发行版至关重要。它决定了您的系统是否会重启。如果您在命令中犯了错误,系统在重启时可能无法启动。正如我们之前指出的,我们希望您仅在测试服务器环境中尝试这些命令,而不是在生产环境中。
首先,在开始编辑之前备份该文件:
|
1 |
sudo cp /etc/inittab /etc/inittab.original |
接下来,使用 nano 打开该文件:
|
1 |
sudo nano /etc/inittab |
滚动到文件末尾并添加以下代码片段:
|
1 |
ms:2345:respawn:/bin/sh /usr/bin/mysqld_safe |
上述命令在系统崩溃后重启 mysql_safe 进程。它有四个由冒号分隔的字段,说明如下:
- ms:指定进程的 ID。
- 2345:指定命令适用的运行级别。在本例中为:运行级别 2、3、4、5。
- respawn:指定操作。在本例中,我们是重新生成(respawning)或重启该进程。
- /bin/sh /usr/bin/mysqld_safe:最后一部分定义了进程——即为重启该进程而执行的命令。
现在按下 Ctrl + O 并回车以保存文件。然后,按下 Ctrl + X 关闭编辑器。输入以下命令启动服务:
|
1 |
sudo service mysql start |
重启服务器,然后运行前面解释的命令以查找进程号。接下来,终止这些进程,从以下命令开始:ps -ef | grep mysql。等待几分钟,然后输入以下命令检查 MySQL 的状态:
|
1 |
sudo service mysql status |
输出应该表明 MySQL 服务已启动并正在运行,这意味着它在崩溃后能够重新启动。您可以对服务器上的其他服务执行相同的过程。
使用 Upstart 自动启动服务
Upstart 是另一个初始化系统,最初在 Ubuntu 6 中引入,后来在 Ubuntu 9.10 中成为默认系统。RHEL 6 及其衍生版本以及 Google 的 Chrome OS 也使用 Upstart 初始化系统。对于本节中的步骤,您应该拥有一台运行以下任何发行版的服务器:
- Ubuntu 9.10 到 Ubuntu 14.10,以及 Ubuntu 的 LTS 版本,即 Ubuntu 14.04。
- CentOS 6
让我们看看如何配置 Upstart 文件,以便在重启或系统崩溃时自动启动服务器服务。Upstart 使用存储在 /etc/init 目录下的配置文件来控制 Linux 发行版中的服务。大多数最新版本的服务器应用程序(如 MySQL 和 Nginx)都会在 /etc/init 目录中安装自己的初始化脚本。因此,它们将在重启后和系统崩溃后启动,而无需您执行任何操作。
Upstart 自动启动检查清单
以下是一些参考配置,用于检查并确保您的服务已配置为自动启动。
- 确保服务在以下目录中有一个初始化脚本:/etc/init/service_name.conf – service_name 是您特定服务的实际名称。您应该检查 /etc/init/service_name.conf 文件中的以下两行:
- 包含类似于以下内容的一行:start on runlevel [2345]。它表示该服务将在系统重启时启动。
- 包含类似于以下内容的一行:respawn。它表示该服务在系统崩溃后将被重新生成/重新启动。
- 确保该目录中没有服务覆盖文件:/etc/init/service_name.override。除非您或其他系统管理员之前创建过它。
- 输入以下命令来停止和启动服务:
|
1 2 |
sudo initctl stop service_name sudo initctl start service_name |
- 重启系统,并在几分钟后重新连接。现在,运行一些测试以查看一切是否正常工作
- 重启后,验证服务是否已启动并正在运行。输入以下命令搜索进程号,将 service_name 替换为您正在测试服务的实际名称:
|
1 |
ps -ef | grep service_name |
- 获取进程号后,输入以下命令终止该进程:
|
1 |
sudo kill -9 process_number |
- 等待几秒钟,再次验证进程是否已启动并正在运行。
使用实际服务进行 Upstart 配置实战
在下一节中,我们将尝试演示如何将 Upstart 与实际服务结合使用。我们将在以 MySQL 作为服务的 Ubuntu 14.04 虚拟机服务器上运行测试。如果您使用的是 Windows,请使用 ssh 或 putty 连接到您的 Ubuntu 14.04 测试服务器。按照惯例,您应该使用具有 sudo 特权的非 root 用户。登录后,我们就可以开始以下步骤:
第 1 步:安装 MySQL
在安装任何新软件之前,请务必记得更新您的软件包:
|
1 |
sudo apt-get update |
现在,输入以下命令安装 MySQL 服务器:
|
1 |
sudo apt-get install mysql-server –y |
在提示时创建 root 密码。等待安装完成,然后运行以下命令开始保护您的 MySQL 安装:
|
1 |
mysql_secure_installation |
按照提示进行操作,就像您在前面章节中所做的那样。然后,刷新权限以使更改立即生效。
第 2 步:配置服务 (MySQL) 在系统重启后自动启动
MySQL 已设置为在重启后自动启动。我们查看其配置文件只是为了学习如何配置我们的自定义应用程序,使其也能在重启后自动启动。MySQL 服务在安装后已自动启动。不过,让我们通过输入以下命令来确认它正在运行:
|
1 |
sudo initctl status mysql |
您应该会看到表示 MySQL 服务正在运行的输出,类似于:
|
1 |
mysql start/running, process 2553 |
重启服务器并重新登录。再次输入以下命令以测试它是否正在运行:
|
1 |
sudo initctl status mysql |
输出将表明 MySQL 正在运行,这意味着它在重启后自动启动了。在这种情况下,不需要更改任何内容。然而,其他应用程序的行为可能并非如此。您可能会好奇 Upstart 初始化系统是如何知道应该在重启后自动启动 MySQL 的。MySQL 将其 Upstart 启动配置文件安装在以下位置:/etc/init/mysql.conf。Upstart 文件不是 Shell 脚本,而是包含用于启动前和启动后事件的脚本块的文本文件。这些块指示 Upstart 系统在 MySQLd 进程启动时或已经启动时要执行什么操作。
输入以下命令以在 nano 编辑器中打开该文件:
|
1 |
sudo nano /etc/init/mysql.conf |
该文件的输出可能类似于:
|
1 2 3 4 5 6 7 8 |
description "MySQL Server" author "Mario Limonciello <superm1@ubuntu.com>" start on runlevel [2345] stop on starting rc RUNLEVEL=[016] respawn respawn limit 2 5 |
如您所见,start 块指示 MySQL 在运行级别 2,3,4,5 启动,而不是 0,1,6。如果您正在为您的应用程序定义 Upstart 配置,您将在此部分中进行定义。respawn 块指示 Upstart 在崩溃后该怎么做。我们将在下一节中讨论这一点,因此请在 nano 编辑器中保持该文件打开。
第 3 步:配置服务 (MySQL) 在崩溃后自动启动
在 respawn 指令(位于 /etc/init/mysql.conf 文件中)指示 Upstart 在崩溃后重新启动 MySQL 服务。
respawn limit 指令指示 Upstart 在以秒为单位指定的间隔内应尝试重新启动已崩溃的 MySQL 服务的次数。第一个参数 (2) 表示尝试次数。第二个参数 (5) 表示以秒为单位的间隔。如果崩溃后,Upstart 未能在阈值内重新生成 MySQL 服务,它将保持停止状态。这种行为旨在保护系统,防止在不断尝试重新启动持续崩溃的服务时影响其稳定性。您现在可以关闭编辑器,无需进行任何更改。
让我们测试一下 MySQL 在崩溃后是否会自动恢复。输入以下命令以检查状态并获取 MySQL 服务的进程号:
|
1 |
sudo initctl status mysql |
输出应该类似于这样。请记下进程号,因为我们稍后会用到它:
|
1 |
mysql start/running, process 738 |
接下来,输入以下命令来终止该进程。这模拟了一次崩溃。请替换为您在上一条命令中获得的进程号:
|
1 |
sudo kill -9 7738 |
再次输入以下命令检查 MySQL 的状态:
|
1 |
sudo initctl status mysql |
它应该已经重新运行,但可能具有不同的进程号:
|
1 |
mysql start/running, process 1428 |
发生这种情况是因为其中的 respawn 指令 /etc/init/mysql.conf 文件。它确保在发生任何系统故障时,MySQL 都会自动启动。因此,依赖于 MySQL 数据库的应用程序将继续按预期运行。
使用 Systemd 自动启动服务
Systemd 是大多数最新 Linux 发行版中使用的初始化系统。这很可能是您在创建新的 VPS时会使用的系统。它最初是在 Fedora 中引入的。它随 RHEL 7 及其衍生版本(如 CentOS 7)一起提供。从 Ubuntu 15.04 开始,您会发现 Systemd 是原生支持的。Systemd 向后兼容 System V 初始化脚本和命令。因此,任何 System V 服务都应该可以在 Systemd 下运行。System V 和 Upstart 中使用的大多数命令都已修改为适用于 Systemd。
使用 Systemd,大多数服务器应用程序(如 MySQL 和 Nginx)在重启或关机后都会自动启动,而无需您进行任何更改。对于您的自定义应用程序,您必须创建自己的初始化脚本来自动重启服务。
有关 Systemd 的更多深入信息,请查看我们的关于如何使用 Systemctl 管理 Systemd 服务和单元的教程.
Systemd 自动启动检查清单
以下是一些参考配置,用于检查并确保您的服务已配置为使用 Systemd 自动启动。
- 该服务必须在以下位置拥有一个可用的 Systemd 初始化脚本:/etc/systemd/system/multi-user.target.wants/serviceName.service。ServiceName 是您正在配置的服务的实际名称。
- 启用该服务的命令是:
|
1 |
sudo systemctl enable serviceName.service |
- 该命令会在以下目录中创建一个符号链接:/etc/systemd/system/multi-user.target.wants/ 目录,其外观可能类似于:
|
1 |
lrwxrwxrwx 1 root root 11 Dec 1 04:43 /etc/systemd/system/multi-user.target.wants/serviceName.service -> /usr/lib/systemd/system/serviceName.service |
- 有了该符号链接,您就已启用了开机后自动重启。
- 要使更改生效,请使用以下命令重新加载系统守护进程,然后重新加载服务:
|
1 2 3 |
sudo systemctl daemon-reload sudo systemctl restart serviceName.service |
- 要测试您的配置是否会在重启后启动服务,您可以重启系统:
|
1 |
sudo reboot |
- 系统重启后,使用以下命令搜索进程号:
|
1 |
ps -ef | grep serviceName |
- 记录进程号并使用以下命令将其杀死:
|
1 |
sudo kill -9 process_number |
- 等待几秒钟,然后再次搜索该服务以验证其是否已恢复运行。
使用真实服务进行 Systemd 配置实战
在本节中,我们将尝试在 Ubuntu 20.04 虚拟机上配置 MySQL 服务。
步骤 1:连接到您的虚拟专用服务器(Ubuntu 20.04 或 CentOS 7 x64)
登录您的 VPS,或在 Cloudsigma 面板 中创建一个,如果您使用的是 Windows,请使用 ssh 或 putty 进行连接。在本节教程中,我们使用的是 Ubuntu 20.04 服务器。相同的命令也适用于 CentOS 7。请确保使用具有 sudo 特权的非 root 用户。
步骤 2:安装 MySQL(我们正在配置的服务)
首先,更新您的系统:
|
1 |
sudo apt update |
然后,您可以使用以下命令安装 MySQL 服务器:
|
1 |
sudo apt install mysql-server –y |
接下来,运行以下命令开始保护 MySQL 的安全:
|
1 |
sudo mysql_secure_installation |
该脚本会询问您是否要设置 VALIDATE PASSWORD(验证密码)组件,或者按任意字母继续而不启用该组件。点击此链接以了解有关 MySQL 验证密码组件.
按 1 启用它,然后按 1 选择中等水平。输入一个强密码:大写字母、小写字母、特殊字符和数字的组合。确认密码,并确认询问您是否要将输入的密码用作 root 密码的提示。对于其余的其他提示,按 y 接受它们,就像您在前面章节中所做的那样。最后,刷新 MySQL 的权限以重新加载更改。
步骤 3:配置 MySQL 在重启后自动启动
MySQL 已配置为在重启后启动,因此您无需进行任何更改。但是,我们可以使用 MySQL 配置文件来学习如何配置我们的自定义文件。
首先,检查 MySQL 服务是否已配置为在开机时启动。输入以下命令(注意,在 Centos 中,MySQL 服务被称为 mysqld):
|
1 |
sudo systemctl is-enabled mysql.service |
以下是输出结果:

接下来,输入以下命令重启 VPS:
|
1 |
sudo reboot |
使用 ssh 重新连接,并输入以下命令来检查 MySQL 服务的状态:
|
1 |
sudo systemctl status mysql.service |
您应该会得到类似于下图屏幕截图中的输出:

要禁用 MySQL 服务,请输入以下命令:
|
1 |
sudo systemctl disable mysql.service |
输出表明指向 MySQL 服务的符号链接已从 Systemd 中删除:

您可以通过输入以下命令来测试该服务是否在 Systemd 初始化系统中启用:
|
1 |
sudo systemctl is-enabled mysql.service |
输出将显示它已被禁用。如果您重启系统,MySQL 将不会在开机时启动:
![]()
输入以下命令启用该服务:
|
1 |
sudo systemctl enable mysql.service |
输出显示了在 Systemd 初始化中创建的指向 MySQL 服务的符号链接:

重启时,MySQL 服务将自动启动。
步骤 4:配置 MySQL 在崩溃后自动启动
MySQL 已配置为在崩溃后自动重启。让我们来看看这个配置在 Systemd 中是如何实现的。Systemd 使用单元文件进行配置。输入以下命令在 nano 中打开 mysql.service 配置文件:
|
1 |
sudo nano /etc/systemd/system/multi-user.target.wants/mysql.service |
输出如下所示:

我们关注的是 Restart 指令。根据定义,如果发生故障,MySQL 将重启。Restart 指令定义了 Systemd 中应该发生什么,就像 Upstart 中的 Respawn 指令一样。
并非所有服务都具有此指令。要使服务在崩溃后能够重启,您始终可以添加 Restart 指令,在 [Service] 块中。如果 [Service] 标头不存在,请添加它。现在,按 Ctrl + X 退出编辑器。
要模拟崩溃,请输入以下命令找到 MySQL 进程 ID:
|
1 |
sudo systemctl status mysql.service |
状态检查命令会显示一个进程 ID,在我们的例子中是 3555:

输入以下命令杀死该进程。将其替换为您在服务器上获取的进程 ID:
|
1 |
sudo kill -9 3555 |
输入以下命令检查状态:
|
1 |
sudo systemctl status mysql.service |
输出显示 MySQL 正在运行,但具有一个新的进程 ID。这意味着它在崩溃后自动重启了:

结论
在本教程中,我们向您介绍了 Linux 发行版中的三种初始化系统:System V、Upstart 和 Systemd。我们学习了如何使用任何一种初始化系统来配置您的持续运行服务,使其在重启或系统崩溃后自动启动。当您需要配置服务时,这应该可以作为一个起点。本系列的第一部分主要是一个动手实践教程。该 第二部分更偏向理论,并包含我们在第一部分中所做工作的更多细节。请先不要删除您的测试服务器,因为您在第二部分中也会用到它们。
祝您计算愉快!
评论
暂无评论。发表第一条评论吧。