提供:ZStack云计算
系列教程
本教程为如何配置Linux服务,确保崩溃或重启后自动加以运行系列两篇中的第一篇。
内容简介
本教程将讲解如何配置系统服务,旨在遭遇崩溃或服务器重启后能够自动加以运行。
本示例使用MySQL,但大家也可利用同样的方式重新运行服务器上的其它服务,例如Nginx或Apache等。
本教程中我们将涵盖三种最为常见的init系统,因此请选择适用于您具体发行版的内容。(很多发行版提供多种选项,或者允许用户安装其它init系统。)
System V为较早的init系统:
- Debian 6及更早版本
- Ubuntu 9.04及更早版本
- CentOS 5及更早版本
Upstart:
- Ubuntu 9.10到Ubuntu 14.10,包括Ubuntu 14.04
- CentOS 6
systemd为各最新发行版中的init系统:
- Debian 7与Debian 8
- Ubuntu 15.04及更新版本
- CentOS 7
大家也可参阅本系列文章的第二篇查看相关参考资料。
背景介绍
运行中的Linux或Unix系统始终拥有大量后台进程处于执行状态。这些进程——或者可称为服务或守护程序——可能属于操作系统的原生组件,或者作为应用程序的一部分存在。
操作系统服务示例:
- sshd守护程序,用于远程连接
- cupsd守护程序,用于控制打印
应用程序守护程序示例:
- httpd/apache2属于Web服务器服务
- mongod属于数据库守护程序
这些服务需要持续运行以支持我们的网站、邮件、数据库及其它应用。
作为管理员,我们需要确保Linux服务:
- 持续运行且不存在故障
- 在系统重启或崩溃时能够自动运行
但有时候这些服务仍会停止,并导致网站或应用不再可用。
本文的目标在于以自动化方式重新启动并运行。
我们可以变更服务管理守护程序的处理方式确保Linux服务拥有自我修复能力,而此类守护程序正是之前所提到的init系统。
不同Linux发行版往往配备不同的服务管理守护程序,我们之前已经提到了各常见发行版所使用的默认init系统。
更多细节可参阅本系列文章的第二部分。在这部分中,我们将首先了解Linux系统中所存在的四项基本runlevel:
- 0 - Runlevel 0代表系统停机
- 1 - Runlevel 1代表单用户援助模式
- 5 - Runlevel 5代表多用户、网络可用、图形模式
- 6 - Runlevel 6代表系统重启
总体而言,runlevel 2、3与4代表着Linux处于多用户、网络启用、文本模式。
当我们将某项服务设为自动启动,即相当于将其添加到了一种runlevel当中。
目标
在本系列教程中,我们将了解如何配置一项Linux服务,从而确保其在系统重启或崩溃后能够再次自动运行。
在第一部分教程内,我们将了解如何使用三种不同的init(即初始化)模式:
- System V init (亦被称为经典init)
- Upstart
- systemd
先决条件
要完成本教程,大家需要创建数个DigitalOcean Droplets(或者自己的Linux服务器),其各自需要至少1 GB内存。关于Droplet的具体创建方法,大家可以参阅此处。
我们将在示例中使用多种不同发行版。
- Debian 6 x64(这款较早版本的OS用于演示System V init系统)
- Ubuntu 14.04 x64 (演示Upstart)
- CentOS 7 x64 (演示systemd)
- 大家还需要在每台服务器上设置一个sudo用户。欲了解更多与sudo权限机制相关的信息,可参阅启用sudo访问相关教程
最后提醒大家,请不要将本教程中的任何命令、查询或者配置应用于生产服务器当中。
利用System V实现服务自动启动
首先来看System V init。
- Debian 6及更早版本
- Ubuntu 9.04及更早版本
- CentOS 5及更早版本
在System V中,大家安装的大部分标准应用——例如Nginx或MySQL——都会在重启后默认自动运行,但崩溃后其无法自动运行。这些应用将在/etc/init.d文件中拥有其init脚本。
对于定制化应用,大家需要创建自己的init脚本并手动启用其自动运行机制。
本文不会介绍如何创建init脚本,但大家可以参考现有示例了解其内容设定方式。System V利用Bash实现init脚本。
System V的自动启动清单
配置清单
- 确保/etc/init.d/service当中存在该服务的功能性Bash init脚本
使用update-rc.d命令以启用该服务(在CentOS系统中,命令为chkconfig):
- sudo update-rc.d service enable
此命令会在/etc/rc2.d中创建一条symlink,如下所示(不要手动进行创建):
lrwxrwxrwx 1 root root 15 Jul 31 07:09 S02mysql -> ../init.d/service
请注意,我们应当看到/etc/rc3.d到/etc/rc5.d这几个目录,我们将在后续的runlevel部分对具体数字进行讲解。
在/etc/inittab文件末尾为该服务添加respawn行。示例如下:
/etc/inittab id:2345:respawn:/bin/sh /path/to/application/startup
停止该服务,而后重新启动:
- sudo service service stop - sudo service service start
重启该服务器。
- sudo reboot
测试
要测试上述设置是否有效,大家可以:
- 重启服务器并检查服务是否正在运行
搜索进程数字:
- ps -ef | grep service
关闭该进程:
- sudo kill -9 process_number
等待五分钟,而后检查该服务是否正在运行。
第一步——接入Debian 6 Droplet
现在我们将利用MySQL运行实例。首先在DigitalOcean控制面板中创建一个内存为1 GB的Debian 6.0 x64 Droplet。
Droplet初始化完成后,使用SSH以接入该服务器(Windows用户可以利用PuTTY等工具实现接入)。
- ssh sammy@your_server_ip
在以下操作中,我们假定大家的账户已经拥有sudo权限。
第二步——安装MySQL
我们将利用MySQL作为测试对象。执行以下命令以安装MySQL Server:
- sudo apt-get install mysql-server -y
下图所示为新的root密码输入界面:
再输入一次密码:
按下回车以确认。
MySQL安装完成后,运行以下命令以保护安装结果:
- mysql_secure_installation
此次我们需要输入当前root密码。按下N以继续使用原有密码。而后按下Y以移除匿名用户、禁用远程root登录并移除测试数据库。最后,按下Y以重新载入权限表。
到这里安装工作就完成了。
执行以下命令以检查该服务是否正在运行:
- service mysql status
输出结果将显示为数行信息,其中一行显示了MySQL服务的运行时间:
Output
/usr/bin/mysqladmin Ver 8.42 Distrib 5.1.73, for debian-linux-gnu on x86_64
. . .
Uptime: 4 days 18 hours 58 min 27 sec
Threads: 1 Questions: 18 Slow queries: 0 Opens: 15 Flush tables: 1 Open tables: 8 Queries per second avg: 0.0.
第三步——配置MySQL确保在重启后自动运行
在默认情况下,MySQL会在重启后自动运行。
大家可以在/etc/rc2.d目录中的MySQL init脚本内查看到这条symlink。请注意,请不要手动创建这些symlink,使用update-rc.d命令以启用及禁用这些服务。
- ls -l /etc/rc2.d
Output
lrwxrwxrwx 1 root root 15 Jul 31 07:09 S02mysql -> ../init.d/mysql
只要对应的默认runlevel目录下仍有S脚本存在,则init就会在服务器启动后自动运行该服务。
现在我们需要进行验证。重启设备:
- sudo reboot
当服务器再次上线,利用SSH进行接入。
再次运行service mysql status命令,结果显示其正在运行,意味着我们的实验已经获得成功。
不过在某些情况下,我们需要手动配置部分服务才能实现自动运行。在Debian系统中,使用update-rc.d命令以添加或移除需要自动运行的服务。
下面禁用MySQL服务,而后了解如何重新启动其自动运行机制。使用以下命令禁用MySQL:
- sudo update-rc.d mysql disable
为了进行测试,再次重启服务器。
- sudo reboot
通过SSH接入服务器。
使用MySQL客户端工具接入MySQL:
- mysql -u root -p
这时获得的信息如下:
Output
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
重新启用该服务:
- sudo update-rc.d mysql enable
输出结果变为:
Output
update-rc.d: using dependency based boot sequencing
如果大家使用的是CentOS系统配合System V,则将update-rc.d命令替换为chkconfig。
请注意,启动时自动执行并不代表某项服务能够在被关闭后自行开启。要启动MySQL,请使用以下命令:
- sudo service mysql start
第四步——配置MySQL以实现崩溃后自动运行
现在我们开始考虑崩溃后的情况。在System V中,崩溃后重启并非默认选项。
我们将突然关闭进程以模拟崩溃情况。利用以下命令找到其进程ID:
- ps -ef | grep mysql
输出结果如下:
Output
root 1167 1 0 07:21 pts/0 00:00:00 /bin/sh /usr/bin/mysqld_safe
mysql 1292 1167 0 07:21 pts/0 00:00:00 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/run/mysqld/mysqld.sock --port=3306
root 1293 1167 0 07:21 pts/0 00:00:00 logger -t mysqld -p daemon.error
root 1384 1123 0 07:21 pts/0 00:00:00 grep mysql
MySQL的主进程为mysqld_safe与mysqld。其中mysqld_safe为mysqld的父进程。
在本示例中,我们可以看到其进程ID分别为1167与1292。其进程数字以红色进行高亮显示。
下面使用kill -9命令模拟崩溃情况:
- sudo kill -9 1167
- sudo kill -9 1292
检查服务状态:
- sudo service mysql status
输出结果显示该服务已经停止:
Output
MySQL is stopped..
现在我们的服务已经崩溃。接下来考虑如何以自动方式使其重新运行——具体办法为编辑/etc/inittab文件。
我们将在第二部分教程内详尽探讨/etc/inittab文件,现在我们只需要知晓其为System V init在启动时读取的第一个文件。
事实上,/etc/inittab负责决定某一进程在崩溃后该如何反应。对于某些进程,其需要重新启动服务——MySQL自然也属于这一类。因此首先将其拷贝出来:
- sudo cp /etc/inittab /etc/inittab.orig
请注意:在编辑/etc/inittab文件时需要万分小心。如果大家在命令中出现错误或者删除了现有配置,那么系统将无法在重启后正常运行。
在文本编辑器中打开/etc/inittab:
- sudo nano /etc/inittab
在文件末尾添加以下行:
/etc/inittab
ms:2345:respawn:/bin/sh /usr/bin/mysqld_safe
其含义是,我们在/etc/inittab文件内添加了命令,旨在恢复崩溃了的mysqld_safe进程。其中包含四个字段,彼此之间以冒号分隔。
- ms: 前两个字母负责指定目标进程的ID。
- 2345: 第二字段负责指定其应用的runlevel。在本示例中,其runlevel为2、3、4、5。
- respawn: 第三字段指定具体操作(即恢复该服务)。
- /bin/sh /usr/bin/mysqld_safe: 最后,第四字段为目标进程(即命令的执行对象)。
完成后保存并退出。
再次启动该服务:
- sudo service mysql start
重启服务器以应用变更:
- sudo reboot
现在再次搜索进程ID,关闭进程,检查运行状态,等待5分钟后执行以下命令:
- sudo service mysql status
现在可以看到,MySQL已经在崩溃后自动重启。
成功了!MySQL已经能够在系统崩溃与重启这两种情况下自行恢复运转。
利用Upstart实现服务自动运行
Upstart属于另一种init方法,其最初出现在Ubuntu 6当中。目前其在Ubuntu 9.10、RHEL 6以及谷歌Chrome OS等系统中作为默认选项。
- Ubuntu 9.10到Ubuntu 14.10, 包括Ubuntu 14.04
- CentOS 6
Upstart在处理系统服务方面比System V表现得更好,而且也易于掌握。不过我们在这里不会深入探讨,感兴趣的朋友可以参阅Upstart使用教程。
Upstart利用配置文件实现服务控制。这些文件位于/etc/init目录,采用纯文本内容并以易于阅读的方式存在于stanzas区段之内。每条stanza负责描述服务的一个方面以及执行方式。
在默认情况下,Nginx或MySQL等标准应用都能够在重启或崩溃后自动恢复运行,因为其init脚本已经直接存在于/etc/init当中。
对于其它定制化应用,大家需要进行手动设置。要了解更多与定制Upstart脚本相关的内容,请参阅之前提到的Upstart使用教程。
Upstart的自动运行列表
配置列表
确保服务在/etc/init/service.conf处拥有一个功能性Upstart init脚本
- /etc/init/service.conf文件应当包含诸如start on runlevel [2345]的一行,从而在重启后实现自动恢复
- /etc/init/service.conf文件应当包含respawn行以确保服务在崩溃后能够自动恢复
确保此处不存在目标服务的override文件:
/etc/init/service.override
(此文件只应在我们自己或者其他管理员此前创建过时存在)
停止后重新启动服务:
- sudo initctl stop service - sudo initctl start service
重启服务器:
- sudo reboot
测试
要测试上述设置是否有效,大家可以:
- 重启服务器并检查服务是否正在运行
搜索进程数字:
- ps -ef | grep service
关闭该进程:
- sudo kill -9 process_number
等待数秒并验证服务是否已经重新运行。
第一步——接入Ubuntu 14.04 Droplet
这里我们使用Ubuntu 14.04服务器,运行MySQL以演示Upstart。
利用Ubuntu 14.04 x64作为基础镜像,创建一套内存为1 GB的Droplet。
利用SSH接入该服务器:
- ssh sammy@your_server_ip
在以下操作中,我们假定大家的账户拥有sudo权限。
第二步——安装MySQL
下面安装MySQL。执行以下命令以更新软件包列表:
- sudo apt-get update
安装MySQL Server:
- sudo apt-get install mysql-server -y
为MySQL创建新的root密码并确定。
安装完成后,运行mysql_secure_installation命令:
- mysql_secure_installation
其余部分与此前Debian中的安装流程一致。
第三步——配置MySQL以实现重启后服务运行
默认情况下,MySQL会在重启后自动恢复运行。大家可以查看其配置,并将方法应用于其它服务。
首先检查MySQL进程是否正在运行:
- sudo initctl status mysql
结果如下:
Output
mysql start/running, process 2553
重启服务器:
- sudo reboot
在服务器重新上线后,使用SSH重新接入。
检查MySQL状态:
- sudo initctl status mysql
可以看到,MySQL已经自动启动。
请注意,对于其它应用守护程序,我们需要在/etc/init/目录内手动创建Upstart文件以实现自动启动。
那么,要如何告知Upstart在服务器重启后自动运行MySQL?
首先利用文本编辑器打开MySQL的Upstart init文件/etc/init/mysql.conf:
- sudo nano /etc/init/mysql.conf
Upstart文件与我们之前提到的shell脚本完全不同。
MySQL的init配置文件中将包含用于实现pre-start与post-start事件的脚本块。这些代码片段负责告知Upstart系统在mysqld进程正在启动或者已经启动时应执行哪些操作。
下面来看文件的前十行:
/etc/init/mysql.conf
...
description "MySQL Server"
author "Mario Limonciello <superm1@ubuntu.com>"
start on runlevel [2345]
stop on starting rc RUNLEVEL=[016]
respawn
respawn limit 2 5
可以看到,MySQL应该以runlevel 2、3、4、5启动,而非runlevel 0、1与6。
在这里我们可以对Upstart守护程序进行服务启动定义。在这里,我们直接使用服务配置文件即可。
其中respawn指令负责在崩溃后重新启动该服务,我们将在下一节中进行详细说明。
第四步——配置MySQL确保崩溃后自动启用服务
现在打开/etc/init/mysql.conf文件。
其中respawn命令的作用非常明确:MySQL会在崩溃后自动恢复。
接下来的指令则非常有趣:respawn limit指令限制了Linux尝试恢复崩溃服务的次数与尝试之间的相隔秒数。在本示例中,(2)为尝试次数,(5)为间隔秒数。如果服务无法在阈值之内顺利完成重启,则将一直处于停止状态。
现在,退出文本编辑器。
正如之前所见,默认情况下MySQL已经能够在崩溃后自动重启。
下面检查该服务的PID以进行测试:
- sudo initctl status mysql
重启后的新PID如下:
Output
mysql start/running, process 961
请注意这里的进程ID。下面利用kill -9命令将该进程关闭:
- sudo kill -9 961
再次检查MySQL状态,其应该再次运行并使用新的PID:
- sudo initctl status mysql
输出结果如下:
Output
mysql start/running, process 1552
如果大家愿意,可以多次重复上述操作:
之所以MySQL能够始终在线,是因为mysql.conf文件中的respawn命令。
/etc/init/mysql.conf
respawn
再次强调,MySQL属于默认自动恢复对象,但其它应用则需要大家修改其配置以实现同样的效果。
利用systemd实现服务自动恢复
systemd是一款Linux平台上的系统与服务管理器,且已经成为大多数新型Linux发行版的默认初始化守护程序。
- Debian 7与Debian 8
- Ubuntu 15.04
- CentOS 7
systemd能够向下兼容System V命令与初始化脚本。
利用systemd,大多数安装的标准应用都能够在重启及崩溃后自动实现恢复。这些应用在/etc/systemd/system 当中拥有自己的init脚本。
对于定制化应用,大家需要创建自己的init脚本并借此实现服务恢复。关于这部分内容,请参阅systemd教程。
systemd的自动启动列表
配置列表
- 确保该服务在/etc/systemd/system/multi-user.target.wants/service.service当中拥有一条功能性systemd init脚本。
使用systemctl命令以启动该服务:
- sudo systemctl enable service.service
以上命令会创建一条指向/etc/systemd/system/multi-user.target.wants/的symlink,内容如下:
lrwxrwxrwx 1 root root 38 Aug 1 04:43 /etc/systemd/system/multi-user.target.wants/service.service -> /usr/lib/systemd/system/service.service
意味着服务将在重启后自动恢复。
- /etc/systemd/system/multi-user.target.wants/service.service文件中应当包含Restart=always行,其位于[Service]区段之下,负责在崩溃后重新恢复服务:
加载systemd守护程序,而后重启该服务:
- sudo systemctl daemon-reload - sudo systemctl restart service.service
测试
下面测试实际效果:
重启服务器后检查服务是否正在运行:
- sudo reboot
搜索其进程号:
- ps -ef | grep service
关闭该进程:
- sudo kill -9 process_number
数秒之后,服务即可重新上线。
第一步——接入CentOS 7 Droplet
在本示例中,我们使用CentOS 7与MySQL以说明如何配置systemd服务。
首先创建一个1 GB内存的Droplet,并选择CentOS 7 x64作为其基础镜像。
使用SSH接入该服务器。
- ssh sammy@your_server_ip
这里我们假设大家的账户拥有sudo权限。
第二步——安装MySQL
运行以下命令以下载并安装MySQL Community server repo:
- sudo wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm
- sudo rpm -ivh mysql-community-release-el7-5.noarch.rpm
安装MySQL server:
- sudo yum install mysql-server -y
安装完成后,启动mysqld服务。
(请注意,在Debian与Ubuntu中的MySQL安装流程有所区别。在Debian中,安装完成后MySQL会自动启动。)
另外,我们使用systemctl命令来控制该服务:
- sudo systemctl start mysqld
接下来运行mysql_secure_installation命令。
- mysql_secure_installation
在这里MySQL root密码为空,大家可以根据需要创建一条新密码。其余流程部分与之前提到的Debian或Ubuntu一致。
第三步——配置MySQL以实现重启后自动恢复
默认情况下,MySQL会在重启后自动恢复运行。为了了解其实现原理,我们首先检查mysqld守护程序的具体配置。执行以下命令:
- sudo systemctl is-enabled mysqld.service
结果如下:
Output
enabled
重启设备:
- sudo reboot
服务器重新上线后,利用SSH进行接入。
执行以下命令检查服务状态:
- sudo systemctl status mysqld.service
输出结果如下:
Output
mysqld.service - MySQL Community Server
Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled)
Active: active (running) since Fri 2015-07-31 21:58:03 EDT; 1min 52s ago
Process: 662 ExecStartPost=/usr/bin/mysql-systemd-start post (code=exited, status=0/SUCCESS)
Process: 625 ExecStartPre=/usr/bin/mysql-systemd-start pre (code=exited, status=0/SUCCESS)
Main PID: 661 (mysqld_safe)
...
运行以下命令禁用该服务:
- sudo systemctl disable mysqld.service
这时服务并不会停止,但会被禁用。从输出结果中可以看到,symlink已经被删除了:
Output
rm '/etc/systemd/system/multi-user.target.wants/mysqld.service'
rm '/etc/systemd/system/mysql.service'
大家也可以重复以上过程,查看MySQL server是否会恢复运行。
或者再次执行systemctl is-enabled,结果如下:
- sudo systemctl is-enabled mysqld.service
Output
disabled
再次启用该服务:
- sudo systemctl enable mysqld.service
输出结果显示,symlink已经再次启用:
Output
ln -s '/usr/lib/systemd/system/mysqld.service' '/etc/systemd/system/mysql.service'
ln -s '/usr/lib/systemd/system/mysqld.service' '/etc/systemd/system/multi-user.target.wants/mysqld.service'
这意味着服务器重启后,服务将能够自动恢复。
第四步——配置MySQL确保崩溃后服务自动恢复
现在看看如何配置MySQL以确保崩溃后自动恢复。
首先打开mysqld.service unit文件(请记住,systemd服务使用unit文件以实现配置):
- sudo nano /etc/systemd/system/multi-user.target.wants/mysqld.service
在文件末尾可以看到一条重启指令:
/etc/systemd/system/multi-user.target.wants/mysqld.service
[Unit]
...
[Install]
...
[Service]
...
...
Restart=always
...
这里Restart参数被设定为always,意味着MySQL服务将在完全或不完全退出或者超时后始终自动重启。
这就是systemd中的自动重启定义方式。
与Upstart中的respawn指令类似,Restart参数负责定义服务在崩溃后执行何种操作。
并非所有systemd服务都在默认条件下启用自动恢复,不过大家可以在对应服务的unit文件内[Service]区段下添加额外指令以实现这一效果。
为了模拟崩溃情况,我们退出编辑器并检查MySQL进程ID:
- sudo systemctl status mysqld.service
Output
mysqld.service - MySQL Community Server
Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled)
Active: active (running) since Fri 2015-07-31 21:58:03 EDT; 1h 7min ago
Main PID: 661 (mysqld_safe)
...
在本示例中,主PID为661,大家需要将其替换为自己的实际PID:
- sudo kill -9 661
检查服务状态:
- sudo systemctl status mysqld.service
输出结果如下:
Output
mysqld.service - MySQL Community Server
Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled)
Active: active (running) since Fri 2015-07-31 23:06:38 EDT; 1min 8s ago
Process: 11218 ExecStartPost=/usr/bin/mysql-systemd-start post (code=exited, status=0/SUCCESS)
Process: 11207 ExecStartPre=/usr/bin/mysql-systemd-start pre (code=exited, status=0/SUCCESS)
Main PID: 11217 (mysqld_safe)
...
...
可以看到,服务能够在崩溃后自动实现恢复。
总结
在本教程的第一部分中,我们了解了System V、Upstart与systemd服务如何在重启或崩溃后实现服务自动恢复。
我们也了解了各文件、配置参数与命令如何控制对应操作。
在本部分内,我们只探讨操作方式。在第二部分文章中,我们将进一步探讨更多概念与基础信息。
请暂时不要删除Droplet——保持运行,因为我们还将在下一部分文章中继续使用。
本文来源自DigitalOcean Community。英文原文:How To Configure a Linux Service to Start Automatically After a Crash or Reboot – Part 1: Practical Examples By Sadequl Hussain
翻译:diradw