介绍
初始化是摆在任何基于Unix操作系统的心脏,控制每个脚本和服务的运行的一个关键步骤。 这在服务器环境中是至关重要的,其中问题可能发生在启动和关闭的关键点,并且确保最佳性能是优先级。
实质上,初始化遵循这种过程:
- 服务器引导
- init进程运行(通常为
PID 1
) - 预定义的一组启动任务按顺序激活
初始化负责确保云服务器可以完全启动和关闭。
使用Unix基础,一些发行版使用初始化的标准init进程。 在本文中,我们将看看Upstart -实用和强大的替代品,可以增压服务器的操作。
经典的init有什么问题?
传统初始化遵循线性过程:单个任务在系统引导时以预定义的顺序加载。 这不是那么有帮助,特别是在快速变化的情况下。 为了理解为什么,想象一下,例如,您通过添加额外的存储设备来修改服务器的环境。
初始化过程不能考虑环境的突然变化,这意味着您的云服务器必须重新初始化,然后才能识别额外的存储。 动态检测是所需要的,虽然它不是经典初始化过程的能力。
以线性顺序引导也需要时间,这在基于云的环境中是特别不利的,其中快速部署是必要的。
在系统加载后,您还可能会担心任务的状态。 不幸的是,init将涉及序列只有当你启动或关闭电源。
不再需要同步引导序列。 刚性系统可以支持昨天的系统,但今天是动态的。
这就是Upstart进来-解决这些问题,先进的功能。
基于实时事件,而不是按顺序任务的预设列表,这种替换的init守护进程处理任务的启动和停止,并监视这些流程,同时在系统运行- “全覆盖”,是形容它的最好方式。
这种新的异步处理消除了对刚性引导序列的需要。 实时处理可能是凌乱的概念化,但Upstart能支持的系统最复杂和使用的作业结构,把一切都在检查。
Upstart概述
从一开始就灵活设计,Upstart事件系统利用了与传统初始化系统不同的各种概念。 默认情况下,该解决方案安装在Red Hat Enterprise Linux(RHEL)6以及Google的Chrome操作系统和Ubuntu上,尽管最近的辩论已经引起了人们是否会继续这样做的混乱。
工作
在Upstart的世界中,作业是工作流程,分为任务作业(有目的)和服务作业(可以在后台运行)。 还有抽象作业 - 永远运行的进程,直到具有管理权限的用户停止。
事件
事件 ,但是,是信号或用于触发与作业或另一事件某个动作“呼叫”。 事件的常见的形式是指一个过程的监测: starting
, started
, stopping
和stopped
。
发射事件
广播事件的过程称为“发射”。 这通常是由一个进程或作业状态造成的,但管理员也可以通过执行手动发出一个事件initctl emit <event>
命令。 你会发现,在init control
导航与Upstart相关的操作多如牛毛命令时,变得非常有用。
编写您的第一个作业配置
Upstart众所周知,在Ubuntu上运行良好,因此在开始之前旋转起来一个Ubuntu 14.04Droplet 。
现在你已经准备好了,重要的是要理解,作业配置文件必须遵守三个基本原则才能有效。
- 它不能为空(一个没有内容的文件)
- 它不能包含任何语法错误
- 它必须至少包含一个命令块,被称为节
让我们现在保持基本。 在某一时刻,我们将创建一个名为testjob.conf
中/etc/init
目录中。 在这种情况下,“init”只是用作“初始化”的缩短版本。
注意.conf
文件关联-这说明你会写的作业配置文件 。
对于本教程的目的,建议使用命令行的文本编辑器纳米 。 其中一些命令可能需要具有管理权限sudo
,所以检查出这篇文章 ,以创建一个相应的用户。
要为测试作业创建新的配置文件,请运行:
sudo nano /etc/init/testjob.conf
让我们现在概述目标。 我们希望这项工作写一个消息和当前时间戳到一个日志文件 。
有两种基本的节,可以帮助你定义一个作业脚本的目的,谁创造了它: description
和author
。 将它们写为文件中的第一行。
description "A test job file for experimenting with Upstart"
author "Your Name"
现在,我们希望在系统服务和进程已经加载(以防止任何冲突)之后发生此作业,因此您的下一行将包含以下事件:
start on runlevel [2345]
你可能想知道运行级是什么。 基本上,它是表示当前系统配置的单个值。 在[2345]
指的是与一般的Linux访问和网络,这是理想的一个基本的测试示例中的所有配置状态。
然后我们将添加执行代码。 此行开头exec
表明,以下命令应通过Bash shell中运行:
exec echo Test Job ran at `date` >> /var/log/testjob.log
注意这个echo
命令使用反引号来运行date
为命令,然后整个消息写入日志文件。 如果你写的字date
没有反引号,这个词本身就被打印,而不是命令的输出。
保存并关闭此文件。
您可以通过手动启动作业来验证此操作是否正常,但让我们先检查配置文件语法:
init-checkconf /etc/init/testjob.conf
如果检测到任何问题,此命令将指示特定的行号和问题。 但是,使用测试作业,您应该看到如下输出:
File /etc/init/testjob.conf: syntax ok
此命令可用于控制Upstart作业和其他后台服务,如Web服务器。
基本命令语法是:
sudo service <servicename> <control>
此语法适用于以下基本控件:
- restart:这将停止,然后启动一个服务
- start:这将启动一个服务,如果它没有运行
- 停止:这将停止服务,如果它正在运行
- status:这将显示服务的状态
我们想手动启动我们的测试作业,所以命令应该如下所示:
sudo service testjob start
现在,检查testjob.log
通过运行以下命令文件:
cat /var/log/testjob.log
这个命令会将文件读入shell; 您应该看到类似于下面的一行:
Test Job ran at Fri Aug 1 08:43:05 BST 2014
这表明您的测试作业已设置好,可以开始使用。
重新启动Droplet,然后再次登录并再次读取日志文件:
cat /var/log/testjob.log
您应该在日志中看到第二行显示以后的时间戳记,以确认它作为Upstart作业运行。
Test Job ran at Fri Aug 1 08:44:23 BST 2014
这只是划破了你可以用Upstart做什么的表面。 稍后我们将介绍一个详细的示例,但现在,让我们继续解释作业状态和事件。
工作状态和事件
系统作业驻留在/etc/init/
目录下,用户作业驻留在用户自己的init目录, ~/.init/
。
用户作业在用户自己的会话中运行,因此也称为会话作业。 这些不运行的全系统和不在PID 1
指定。 对于我们测试工作的目的,我们使用/etc/init
,以便它可以作为系统启动加载。
不管它的类型,作业总是在一个配置文件(.conf文件),其中它的文件名应该代表所涉及的服务或任务定义。
每个职位都有一个目标- start
或stop
。 在这两个目标之间是一组任务状态,其定义关于目标的作业的当前动作。 重要的状态如下:
- 等待:初始状态的处理
- 开始:作业即将开始
- 预启动:加载预启动部分
- spawned:脚本部分即将运行的位置
- 后启动:启动后操作发生的地方
- 运行:作业完全可操作
- 预停:预停止操作发生的地方
- 停止:作业正在停止的位置
- killed:作业停止的位置
- 后停止:后停止操作发生 - 清理
在后启动状态之后,作业被定义为运行。 它保持运行,直到预停止被触发时,那里的工作已经准备好停止,则作业被杀害和停止后的清理过程发生,如果定义。
您可以查看如何通过设置Upstart系统日志的优先级状态之间的转换工作(位于/var/log/upstart/
目录),以debug
使用这个命令:
sudo initctl log-priority debug
请记住, 状态不是事件,和事件都没有的状态 。 这四个事件(启动,启动,停止和停止)由Upstart发出,但任务状态定义作业生命周期的阶段之间的转换。
我们现在已准备好开始一个更集中的例子,通过编写一个服务作业,整合你的第一个配置的元素。 这将演示如何从运行基本测试配置转换到生产就绪脚本。
深入示例:服务作业
在简介中简要介绍,服务作业涉及脚本配置文件,允许进程在后台运行。 我们将建立一个从无到有的基本的Node.js服务器 。
如果你不熟悉Node,本质上它是一个“跨平台环境的服务器端和网络应用程序”(维基百科)。
Node.js是一个非常轻量级的包,虽然它没有在Ubuntu 14.04上默认安装。 要开始,请继续安装在云服务器上。
sudo apt-get install nodejs
现在,让我们开始使用服务作业。 创建一个新的工作配置文件/etc/init
称为nodetest.conf
。 参考其目的命名文件是必不可少的,因此您将能够识别此服务作业是用于Node.js测试。
sudo nano /etc/init/nodetest.conf
我们将在后面的示例中介绍Node应用程序本身,因为预先了解Upstart配置很重要。
第一件事。 首先输入作业描述和作者行以定义配置。
description "Service for a test node.js server"
author "Your Name"
我们希望这个基于节点的服务器应用程序在服务器启动和运行时启动,并且在服务器正常关闭时停止。 因此,请务必同时指定两个条件:
start on filesystem or runlevel [2345]
stop on shutdown
记住前面的运行级别标准吗? 与合并filesystem
事件,这将确保工作负载在服务器启动并正常运行。
这些是基础,但现在它变得更复杂; 我们将使用我们前面提到过的节 。
由于这是一个服务器应用程序,我们将在作业配置中包含一个日志记录元素。 因为我们希望在节点应用程序的启动和停止,我们将使用三种不同的节分隔我们的服务行动记录- script
, pre-start script
和pre-stop script
。
如果你觉得这些声音很熟悉,你绝对是对的。 预启动和预停止是作业状态,但它们也可以在节中工作。 这意味着,可以根据作业所处的状态运行不同的命令。
但是,第一节要写的是作业脚本本身。 这将获取Node后台服务器的进程ID,然后运行应用程序脚本。 注意在一个节中的命令缩进 - 这对于语法正确的格式化是必不可少的。
script
export HOME="/srv"
echo $$ > /var/run/nodetest.pid
exec /usr/bin/nodejs /srv/nodetest.js
end script
节点需要一个主目录变量被设置,因此,为什么/srv
在节的第一行导出。 接下来, $$
用于获取可用的进程ID,并为我们的工作一个PID文件。 在准备好之后,Node.js应用程序被加载,我们将在后面写。
现在是时候把重点放在pre-start
和pre-stop
,这将用于我们的简单应用程序日志。 日期以及开始或停止消息将附加到作业的日志文件中:
pre-start script
echo "[`date`] Node Test Starting" >> /var/log/nodetest.log
end script
请注意,停止前节包含另一行:作为关闭服务器过程的一部分,删除PID文件(什么停止前)。
pre-stop script
rm /var/run/nodetest.pid
echo "[`date`] Node Test Stopping" >> /var/log/nodetest.log
end script
这是整个Upstart作业配置排序; 这里是整个事情再次参考:
description "Test node.js server"
author "Your Name"
start on filesystem or runlevel [2345]
stop on shutdown
script
export HOME="/srv"
echo $$ > /var/run/nodetest.pid
exec /usr/bin/nodejs /srv/nodetest.js
end script
pre-start script
echo "[`date`] Node Test Starting" >> /var/log/nodetest.log
end script
pre-stop script
rm /var/run/nodetest.pid
echo "[`date`] Node Test Stopping" >> /var/log/nodetest.log
end script
保存并关闭文件。
正如指出的exec
线,Node.js的脚本是从服务器上运行,所以创建一个nodetest.js
在你想要的位置的文件( /srv/
用于此为例):
sudo nano /srv/nodetest.js
由于这是一个Upstart教程,我们不会花太多时间审查Node.js代码,虽然这里有一个脚本将完成的内容:
- 需要并加载Node的HTTP模块
- 创建HTTP Web服务器
- 在标题中提供状态200(OK)响应
- 写“Hello World”作为输出
- 在8888端口监听
这里是你需要的代码来获得Node应用程序的运行,可以直接复制到节省时间:
var http = require("http");
http.createServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}).listen(8888);
保存Node.js文件后,最后要检查的是Upstart作业语法是否有效。 像往常一样,运行配置检查命令,您应该收到一个确认输出:
init-checkconf /etc/init/nodetest.conf
File nodetest.conf: syntax ok
你有你的作业配置,检查它的语法,并保存了Node.js的代码-一切都准备好了,所以重新启动Droplet,然后访问的http:// IP:** ** 8888 ,或相关领域。
如果你在窗口的左上角遇到“Hello World”,Upstart服务工作就可以了!
对于基于状态的记录进行确认,请阅读预定义的日志文件,你会看到一个时间戳Starting
线。 关闭服务器或手动停止服务工作会写一个Stopping
线到日志中,您还可以检查如果你想。
cat /var/log/nodetest.log
[Sun Aug 17 08:08:34 EDT 2014] Node Test Starting
[Sun Aug 17 08:13:03 EDT 2014] Node Test Stopping
您可以对此服务以及任何其他类似的Upstart作业运行starndard start,stop,restart等命令,其语法如下所示:
sudo service nodetest restart
结论
本教程只讨论了Upstart事件系统的表面。 你已经阅读了传统初始化的背景,发现为什么开源的Upstart解决方案是一个更强大的选择,并开始编写自己的工作。 现在你知道的基础,可能性是无止境的。
Logo从Upstart官方网站,版权原创设计师/ Canonical有限公司