Ubuntu从6.10开始逐步用Upstart()代替原来的SysVinit进行服务进程的管理。RHEL(CentOS)也都从版本6开始转用Upstart代替以往的init.d/rcX.d的线性启动方式。 SysVinit守护进程(sysvinit软件包)是一个基于运行级别的系统,它使用运行级别(单用户、多用户以及其他更多级别)和链接(位于/etc /rc?.d目录中,分别链接到/etc/init.d中的init脚本)来启动和关闭系统服务。SysV启动是线性、顺序的。一个S20的服务必须要等待S19启动完成才能启动,如果一个启动要花很多时间,那么后面的服务就算完全无关,也必须要等。 UpStart(Upstart init daemon)是基于事件的启动系统,它使用事件来启动和关闭系统服务。Upstart是是并行的,只要事件发生,服务可以并发启动。这种方式无疑要优越得多,因为它可以充分利用现在计算机多核的特点,大大减少启动所需的时间。
Upstart是基于事件的,当系统中的什么情况发生变化时,它会运行某个特定的程序。这里被运行的程序多半是用来启动或终止服务的脚本。这个配置方式和System V在系统进入某个运行级别的时候运行init脚本的链接的概念实际上是非常类似的。只不过Upstart更加灵活一些,Upstart不仅能在运行级别改变的时候启动或终止服务,也能在接收到系统发生其他改变的信息的时候启动或终止服务。这些系统的改变被称为“事件”。例如,当Upstart从udev接收到运行时文件系统加载、打印机安装或其他类似的设备添加或删除的信息,并采取相应的行动。Upstart也可以在系统启动、关闭或某个任务状态改变的时候启动或关闭服务。 一个作业(job)是init可以理解的一系列指令。典型的指令包括一个程序(二进制文件或是脚本)和事件的名称。Upstart init daemon会在事件触发的时候运行相应的作业。用户也可以分别手动用initctl start和stop 命令手动启动或终止某项工作。 作业又可以分为任务作业(Task)、服务作业(Services)、抽象作业(Abstact Job)。 任务作业是有确定的生命周期和终止状态的,运行并在执行结束后返回到等待状态的作业。例如:删除一个文件。 服务作业是那些长期运行的进程,例如守护进程,通常不会自己终止。比如数据库、web服务器、ftp服务器等就被实现为服务。 抽象作业是没有exec节或script节的作业,这样的作业仍然可以被启动和终止,但是不会被分配PID。这样作业启动后如果没有被管理员终止,会永久的运行。抽象作业只存在于Upstart自己内部,但有时个它非常有用,例如定义“永久运行”的作业,用来同步等。 作业的10种状态:
waiting: 初始状态。 作业的状态可通过inictl status命令输出的中status域来显示给用户。
init daemon会监测每个服务的状态,如果服务出现问题会重启服务,在某些事件触发时或手工停止时会杀死服务。 Upstart init daemon只能监测哪些使用exec运行的作业,无法监测使用script…end script运行的作业。也就是说,服务应该使用exec运行,而任务则可以使用任意的方法。 Upstart init守护进程读取/etc/init目录下的作业配置文件,并使用inotify来监控它们的改变。配置文件名必须以.conf结尾,可以放在/etc/init/下的子目录中。每个文件定义一个服务或作业,其名称按路径名来称呼。例如定义在/etc/init/rc-sysinit.conf中的作业就称为rc-sysinit,而定义在/etc/init/net/apache.conf的作业称为net/apache。这些文件必须是纯文本且不可执行的。 二、进程(Process) Process是由工作(jobs)定义的服务(Services)或者任务(Task),它将被init daemon运行。每个job可以定义一个或者多个不同的process,分别在其生命周期的不同状态运行。除抽象作业(Abstact Job)外的所有作业配置文件都必须要含有exec节(exec stanza)或者script节(script stanza)。它们指定这个工作运行什么文件。 在运行exec或者script指定的程序之前或者之后,你可以运行一些附加的shell代码。附加代码不是用来启动主进程的,实际上他们也不能启动主进程。附加代码是用来准备运行环境和进行清理工作的。启动前运行的脚本指定主进程运行前所要执行的shell代码,跟script一样,所以任何一个命令执行失败都将终止运行脚本。它也以”end script”作为结束。 Process定义如下:
定义作业要运行的主进程,注意若有特殊的字符(如引号或$符)将导致整个命令被传递给Shell来运行。例如exec /usr/sbin/acpid -c $EVENTSDIR -s $SOCKET。
定义Shell脚本来运行指定的主进程,该脚本由sh来执行。Shell的-e选项总是被使用,因此任何命令失败将导致脚本终止。注意作业的主进程只能用exec或script节中的一种来定义,不能同时用exec和script配置节来定义。
本进程在作业的starting事件完成之后,主进程运行之前执行。通常用来准备相关环境,例如创建必要的目录。
本进程在作业的started事件触发之前,主进程产生之前执行。通常用来发送必要的命令给主进程,或者用来延迟started事件,直到主进程准备好接收客户端的访问。
本进程在作业被stop on节中的一个事件停止或被stop命令停止时执行。它在作业的stopping事件之前,及主进程被杀死之前执行。通常用来发送必要的shutdown命令给主进程,或调用不带参数的start命令来取消stop。
本进程在主进程被杀死之后,作业的stopped事件触发之前执行。通常用来清理相关环境,例如删除临时的目录。 三、事件(event) 事件(event)是指系统状态的一种改变,这种改变会被通知给init进程。init进程可以得到的状态变更信息,几乎系统所有的内部或外部状态变更都可以触发一个事件。比如引导程序会触发启动(startup)事件,系统进入运行级别2会触发运行级别2(runlevel 2)事件,而文件系统加载则会触发路径加载(path-mounted)事件,拔掉或安装一个热插拔或USB设备(如打印机)也会触发一个事件。这些事件会被通知给init进程,然后init进程来决定系统如何处理这些事件。用户还可以通过initctl emit命令来手动触发一个事件。 你可以用start on列出一些事件,表明发出这些事件时你想要启动这个工作,也可以用stop on来指明发出某些事件时你想要停止这个工作。 事件定义格式如下:
事件定义示例:
用户也可以自己定义一个事件,并让一个作业被这个事件触发。如下的myjob作业定义文件定义了一个被hithere事件触发的作业:
这段代码指定在接收到hithere事件时将触发该作业。然后代码执行指定的操作(将一条消息和日期输出到/tmp/myjob.out 文件)。 用户也可以使用initctl emit命令手动触发事件来执行这个作业。
Upstart的事件数量是没有限制的,但init守护进程和telinit工具定义了一组常用的标准事件。主要有以下几个:
starting: 当作业被调度并开始运行时,由Upstart触发。 当upstart init进程启动时,它会发出startup事件,这将激活实现了System V兼容性的事件和runlevel事件。随着作业的启动和停止,init守护进程将触发starting, started, stopping,stopped事件。另一个核心事件shutdown则是在系统关闭时发出的。其他核心事件包括ctrlaltdel,它说明您按下了Ctrl-Alt-Delete或kbdrequest,它用来说明您按下了Alt-Up(向上箭头)键组合。 Upstart有三种事件类型 Signal Event 非阻塞的即异步的。触发信号型事件会立即返回,调用者继续往下执行。信号型的意思就是广播者并不关心谁会接收它,也不需要等待是否发生某种事情,它只是用来提供信息用作通信。使用带–no-wait选项的initctl emit命令来创建信号型事件。例如initctl emit –no-wait mysignal。注意事件触发的非阻塞特性并不会直接影响那些与此事件有关的作业,它只是影响触发者程序,允许其继续执行,而无需等待任何使用这个事件的作业。作业本身的非阻塞特性则会影响作业自己,它使得作业不能被终止或延迟,不能以任何形式持有触发者的操作。 Method Event 阻塞的即同步的。它通常与Task job结合使用。方法型事件的行为类似于编程语言中的method或function call,调用者需要等待这个工作的完成。例如initctl emit mymethod,这个方法型事件被同步地触发,调用者需要等待直到initctl命令完成。在mymethod事件上启动的任务可能运行成功,也可能失败,假设有一个作业/etc/init/myapp.conf,如下: Hook Event 阻塞的即同步的。钩子介于信号和方法之间。它是一种通知,表示系统发生了一些改变。不同于信号,钩子型事件的触发者需要等待作业的完成。因此钩子通常用来标志即将发生的改变一些事情。starting和stopping是钩子型事件,被Upstart触发以表明作业即将启动或即将终止。 注意事件与状态是有区别的,虽然Upstart内部使用状态(这些状态可以通过initctl status和list命令显示给用户看),但事件是配置文件指定作业期望行为的一种方式,starting, started, stopping, stopped是事件,不是状态。这些事件在一些特殊的状态转移发生之前触发。例如,starting事件在与此事件相关的作业实际进行运行队列之前被触发。 四、作业生命周期 启动一个作业的流程
1)Upstart把作业的目标从stop改成start。正如目标的名字指示的一样,作业(实例)现在尝试启动。目标可以用initctl list和status命令显示。 终止一个作业的流程
1)Upstart把作业的目标从start改为stop。现在作业(实例)尝试终止。 五、initctl(init daemon control tool) initctl是一个具有root权限的管理员可以使用init进程管理控制工具,可以通过这个工具和Upstart init daemon进行通信。initctl可以用来启动或终止作业、列表作业、以及获取作业的状态、发出事件、重启init 进程等等。比如initctl list让您可以通过标识作业状态来深入了解系统操作,它告诉您目前正在等待哪些服务以及哪些服务目前是活动的。initctl工具还可以显示用于调试而接收的事件。 initctl基本用法
initctl使用示例 通过initctl手动启动、停止、重启MySQL服务
更简单的方法:
start、stop和restart工具都是initctl的软链接,会直接运行initctl工具中的对应命令。 采用Upstart做启动管理的系统,服务的启动均依赖于/etc/init/下的每个服务对应的配置文件,通过修改这配置文件,可以更改服务的运行级别。所以即使你将rcX.d下的文件删除,也都不会影响系统的启动。
以Ubuntu下MySQL服务为例,我们先看看基于UpStart的系统下/etc/init.d/mysql脚本详细信息
这里和以前基于Sysv init的系统有很大的不同,这里不在是启动MySQL的执行脚本,而是指向/lib/init/upstart-job的一个软链接,而upstart-job这个脚本会调用initctl工具启动对应的服务。所以用传统的System V方式删掉/etc/init.d/mysql或/etc/rcX.d中是不会影响到MySQL的开机启动的。正是这个原因,网上很多文章说sysv-rc-conf、update-rc.d,rcconf三个基于以前Sysv init的启动管理工具不会生效的原因。不过这种现象只针对以Upstart工作配置文件为基础的服务。那些还是以SystemV脚本管理的软件包依然可以用上面三个管理工具进行启动行的管理,必定还有很多软件包还未采用Upstart方式进行管理。目前Ubuntu系统也都还兼容System V方式的脚本。 六、Ubuntu下常见系统状态下Upstart调用过程
系统启动
1)Upstart执行内部的初始化。 系统关闭 在系统关闭过程中,有一些重要的事实需要知道:
1)Upstart决不会关闭自己。Upstart会在系统断电时终止,如果它之前终止过,说明是一个bug。 关闭系统需要先执行关机动作,例如在图形用户界面中单击”Shut Down…”,运行命令shutdown -h now等。关机的流程如下:
1)假设当前运行级别为2,关机动作将会使Upstart触发runlevel事件,即runlevel RUNLEVEL=0 PREVLEVEL=2。 系统重启 先要执行重启动作,例如在图形界面中单击”Restart…”,运行shutdown -r now或reboot。重启的流程如下:
1)假设当前运行级别为2,重启动作将会使Upstart触发runlevel事件,即 runlevel RUNLEVEL=6 PREVLEVEL=2。 恢复模式 Ubuntu提供了恢复模式以应对系统出现问题的情况。这由friendly-recovery软件包来处理。
七、参考文档 |