Chinaunix首页 | 论坛 | 博客
  • 博客访问: 238651
  • 博文数量: 108
  • 博客积分: 3285
  • 博客等级: 中校
  • 技术积分: 1360
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-28 15:43
文章分类

全部博文(108)

文章存档

2014年(1)

2012年(3)

2011年(28)

2010年(20)

2009年(24)

2008年(32)

我的朋友

分类: LINUX

2009-08-07 10:48:41

By on February 08, 2008 (9:00:00 AM)
原文链接:
翻译时间:2008年3月7日
译者:王旭(gnawux at gmail.com)

译注:尽管译者是一位铁杆的Debian粉丝,但也注意 upstart 很久了,就译者本人观点,upstart 应该说是 Ubuntu 所做的众多工作中最为杰出的一个,它将可以极大地加快 Linux 系统启动的过程。尽管它不是惟一的下一代 init 程序,但它已经作为 Ubuntu 的缺省 init 进程工作了相当长的时间,这点将极大有助于程序的成熟;而且,upstart 使用了基于事件的模型,而不是简单的将各个 daemon 并行化,这个架构上的突破也是具有革命性的,下面我们来看这篇文章吧。
因为传统的System V 的 init daemon (Sysvinit)无法很好地处理现代硬件,如热插拔设备、USB硬盘或山村、网络文件系统等,Ubuntu 使用了 init daemon。

本文抽取自最近出版的 .


SysVinit

Init is the parent of all processes. Its primary role is to create processes from a script stored in the file /etc/inittab. This package also contains well known and used utilities like reboot, shutdown, killall, poweroff, tellinit, sulogin, wall, etc.

Upstart

Upstart is an event-based replacement for the /sbin/init daemon which handles starting of tasks and services during boot, stopping them during shutdown and supervising them while the system is running.

It was originally developed for the distribution, but is intended to be suitable for deployment in all Linux distributions as a replacement for the venerable System-V init.

SysVinit守护进程(sysvinit软件包)是一个基于运行级别的系统,它使用运行级别(单用户、多用户以及其他更多级别)和链接(位于 /etc/rc?.d目录中,分别链接到/etc/init.d中的init脚本)来启动和关闭系统服务。Upstartinit守护进程 (upstart软件包)则是基于事件的系统,它使用事件来启动和关闭系统服务。当Feisty发布的时候,Ubuntu切换到Upstartinit守 护进程,同时开始从SysVinit设置转换到Upstart设置。本节讨论Upstart以及SysVinit尚存的部分:/etc/init.d和 /etc/rc?.d目录以及运行级别概念。请参见1.1节前的相关术语提示信息。

  Upstartinit守护进程是基于事件的系统, 当系统中的某部分发生变化的时候它就运行指定的程序。这些程序(通常是脚本)用来启动和关闭系统服务。从概念上讲,这种设置与SysVinit的init 脚本链接类似,当系统进入不同运行级别时,SysVinit就会调用这些init脚本,区别在于Upstart更加灵活一些。除了在系统运行级别发生改变 的时候启动和关闭服务之外,Upstart还能够根据接收到的(系统某部分发生变化的)信息来启动和关闭服务。这类变化被称为事件(event)。例如, 当Upstart从udev(参见2.2.2节)那里了解到某个文件系统、打印机或者其他设备被添加到系统中或者从系统中移除时,它能够相应地采取行动。 当系统启动的时候、系统关闭的时候或者某项作业状态发生改变的时候,它也能够启动和关闭服务。


目前已经有多种 sysvinit 的替代产品了,这其中最为著名的一个就是 , 它已经可以用于 Debian 了,并且在 Ubuntu 上也能工作。在同一位置上,Solaris 使用 SMF (Service Management Facility),而 Mac OS 则使用 launchd。而 Ubuntu 则更倾向于集这些软件的优点于一身。
Sysvinit daemon 是一个基于运行级别的初始化程序,它使用了运行级别(如单用户、多用户等)并通过从 /etc/rc?.d 目录到 /etc/init.d 目录的初始化脚本的链接来启动与终止系统服务。自从 Feisty 开始,Ubuntu 转向了 Upstart init daemon,并开始将Sysvinit 设置转换为 Upstart 的设置。本文探讨 Upstart 和残存的部分 Sysvinit 遗迹:/etc/rc?.d 和 /etc/init.d 目录以及运行级别的概念。
Upstart init daemon 是基于事件的,当系统中的什么情况发生变化时,它会运行某个特定的程序。这里被运行的程序多半是用来启动或终止服务的脚本。这个配置方式和systemv 在系统进入某个运行级别的时候运行init脚本的链接的概念实际上是非常类似的,只不过 upstart 更加灵活一些。Upstart 不仅能在运行级别改变的时候启动或终止服务,也能在接收到系统发生其他改变的信息的时候启动或终止服务。这些系统的改变被称为“事件”。例如,当 upstart 从 udev 接收到运行时文件系统加载、打印机安装或其他类似的设备添加或删除的信息,并采取相应的行动。Upstart 也可以在系统启动、关闭或某个任务状态改变的时候启动或关闭服务。
Upstart由五个包组成,(Ubuntu 中)它们都会被缺省安装:

  • upstart 提供Upstart init daemon 和 initctl 工具。
  • upstart-logd 提供 logd daemon 和 logd 服务的工作定义文件。
  • upstart-compat-sysv 提供了 rc 任务的工作定义文件,并提供了 reboot, runlevel, shutdown, telinit 等工具,以便与 sysvinit 相兼容。
  • startup-tasks 提供了系统启动任务的工作定义文件。
  • system-services 提供了 tty 服务的工作定义文件。

定义

有几个名词帮助我们理解 init 相关的东西。事件(event)是 init 可以得到的状态变更信息。几乎系统所有的内部或外部状态变更都可以触发一个事件。比如,引导程序会触发启动(startup)事件,系统进入运行级别2会 触发运行级别2(runlevel 2)事件,而文件系统加载则会触发路径加载(path-mounted)事件,拔掉或安装一个热插拔或USB设备(如打印机)也会触发一个时间。用户还可 以通过 initctl emit 命令来手动触发一个事件。
一个工作(job)是 init 可以理解的一系列指令。典型的指令包括一个程序(二进制文件或是脚本)和事件的名称。Upstart init daemon 会在事件触发的时候运行相应的程序。用户可以分别用 initctl start 和 stop 命令手动启动或终止一项工作。工作又可以分为任务和服务。
任务是运行、并在执行结束后返回到等待状态的工作。
服务是那些通常不会自己结束的工作。比如,logd daemon 和 gettys 就被实现为服务。init daemon 会监测每个服务的状态,如果服务出现问题会重启服务,在某些事件触发时或手工停止时会杀死服务。
/etc/event.d 目录下包含着一系列的工作定义文件(定义了 upstart init daemon 运行的工作的文件)。最初,这个目录由 Upstart 包来生成。在 Feisty 之后的 Ubuntu 中,被安装的服务会向这个目录中添加控制服务的文件,替代哪些安装到 /etc/rc?.d 和 /etc/init.d 目录的文件。
Upstart init daemon 的核心是一个状态机。它持续跟踪各个工作的状态,当有事件触发的时候,跟踪工作的状态改变。当 init 跟踪到一个工作的状态从一个转变到了另一个的时候,就可能会执行工作的命令或是终止工作。
System V 的 init daemon 通过改变运行级别来启动或停止服务。而使用 Upstart init daemon 的 Ubuntu 系统没有运行级别的概念。为了将基于运行级别的系统平滑移植到基于事件的系统,并为面向其他发布版的软件提供一定的兼容性,Ubuntu 使用 Upstart 模拟了运行级别。
在 /etc/event.d/rc? 文件中定义的 rc? 工作会运行 /etc/init.d/rc 脚本,这个脚本会运行链接到 /etc/rc?.d 目录中的 /etc/init.d 中的启动脚本,以模拟 SysVinit 的行为。当系统进入一个运行级别的时候,rc? 工作就会运行这些脚本。同时,Upstart 提供了 runlevel 和 telinit 工具以提供与 SysVinit 的兼容性。
使用 initctl (init control) 工具,具有 root 权限的管理员可以和 Upstart init daemon 通信。这个工具可以用来启动、停止或报告(report)一项工作。 比如,initctl list 命令会列出所有的工作和它们的状态:

$ sudo initctl list 
logd (stop) waiting
rc-default (stop) waiting
rc0 (stop) waiting

tty5 (start) running, process 4720
tty6 (start) running, process 4727

要获得更详细的信息,可以参考 initctl 的 man page 或本节的例子。使用 initctl help 命令 (help 前没有横杠)可以列出 initctl 的命令列表。此外,也可以用 initctl list –help 来列出 list 命令的帮助信息,当然,将 list 换乘其它的 initctl 命令会得到该命令对应的信息。start, stop 和 status 工具是 initctl 的链接,会直接运行 initctl 的对应命令。

工作(Job)

/etc/event.d 目录下的每个文件都定义了一个工作,其中至少应该包含一个事件和一个命令。当事件被触发的时候,init 执行对应的命令。本节将介绍管理员自定义的工作和 Upstart 包中包含的工作。

下面的管理员自定义的工作使用 exec 关键字执行了一条 shell 命令。实际上,也可以用这个关键字执行一个 shell 脚本或一个二进制可执行文件。

$ cat /etc/event.d/mudat 
start on runlevel 2
exec echo “Entering multiuser mode on ” $(date) > /tmp/mudat.out

这个文件定义了一个任务:当系统进入到多用户模式(运行级2)的时候执行 echo 命令。这个命令会向 /tmp/mudat.out 文件写出一条包含日期时间消息。shell 会运行 date 命令替换其中的内容。在任务结束后, mudat 任务会停止并进入等待状态。
在下一个的例子中,cat 命令展示了 /tmp/mudat.out 文件的内容和 initctl list 命令关于这个任务的输出(status 工具也可以得到同样的信息):

$ cat /tmp/mudat.out 
Entering multiuser mode on Tue Jul 10 17:34:39 PDT 2007

$ sudo initctl list mudat
mudat (stop) waiting

如果 exec 命令行中包含 shell 的特殊字符, init 会运行 /bin/sh(dash 的符号链接)并把命令行交给它来处理。否则,exec 会直接运行命令行。如果要执行多个 shell 命令,可以把他们放到脚本文件中并运行脚本,或是使用 script….end script (下面会介绍)。
Upstart initdaemon  只能监测哪些使用 exec 运行的工作(服务),无法监测使用 script…end script 运行的工作。换句话说,服务应该使用 exec 运行,而任务则可以使用任意的方法。

myjob 示例

用户也可以自己定义一个事件,并让一个工作被这个事件触发。如下的 myjob 工作定义文件定义了一个被 hithere 事件触发的工作:

$ cat /etc/event.d/myjob 
start on hithere
script
echo “Hi there, here I am!” > /tmp/myjob.out
date >> /tmp/myjob.out
end script

myjob 文件提供了另一种运行命令的方法:在 script 和 end script 关键字之间包含了两行命令。这两个关键字常常导致 init 去运行 /bin/sh。例中的命令将一条消息和日期输出到了 /tmp/myjob.out 文件。现在可以使用 initctl emit 命令触发这个工作。如下,init 展示了 myjobs 在我们的触发下所经历的各个状态:

$ sudo initctl emit hithere
hithere
myjob (start) waiting
myjob (start) starting
myjob (start) pre-start
myjob (start) spawned, process 6064
myjob (start) post-start, (main) process 6064
myjob (start) running, process 6064
myjob (stop) running
myjob (stop) stopping
myjob (stop) killed
myjob (stop) post-stop
myjob (stop) waiting

$ cat /tmp/myjob.out
Hi there, here I am!
Sat Jul 7 20:19:13 PDT 2007

$ sudo initctl list myjob
myjob (stop) waiting

在上面的例子里,cat 展示了 myjob 产生的输出,initctl 展示了工作的状态。同样也可以用 initctl start myjob(或直接用 start myjob)来运行它。initctl start 十个非常有用的命令,这样你就可以在没有事件的情况下启动一个工作。比如,你可以用 initctl start mudat 来直接运行前面例子中的 mudat 工作而不会触发 runlevel 2 事件。

指定带参数的事件

telinit 和 shutdown 工具发送带有参数的 runlevel 事件。比如,shutdown 发送 runlevel 0,telinit 2 会发送 runlevel 2 事件。你可以在工作定义中用如下格式匹配这些事件:
start | stop on event [arg]

其中 event 是一个事件,而 arg 是一个可选参数。要在系统进入 runlevel 2 的时候停止一个工作,可以指定 stop on runlevle 2,也可以指定 runlevel [235] 来匹配运行级 2, 3 和 5,或用 runlevel [!2] 来匹配 2 之外的运行级。
尽管 Upstart 会忽略掉多余的事件参数,但工作定义文件中的事件名称里的参数必须在事件中存在。比如,没有参数的 runlevel 可以匹配所有的 runlevel 事件,不论是否有参数,但 runlevel S arg2 将不会匹配任何事件,因为 runlevel 事件只会带有一个参数。

/etc/event.d 中的工作定义文件

随着 Ubuntu 从 SysVinit 向 Upstart 的迁移,更多地工作会在 /etc/event.d 文件中定义。本节介绍一些 Upstart 包放在这个目录中的工作定义文件。

/etc/event.d/rc2 工作定义文件定义了 rc2 任务,这和其他的 rc? 任务没什么区别。rc2 任务在系统进入到多用户模式的时候会被触发(事件名称是 runlevel 2);当系统进入到其它任意运行级的时候(runlevel [!2])会结束。脚本的第一个部分调用 runlevel 工具,它会让系统显示自己在运行级2 (当然,实际上已经没有运行级这个玩意儿了)并给两个变量赋值。接下来的工作由 exec 命令完成,它会使用参数 2 运行 /etc/init.d/rc 脚本。这个脚本使用相应的参数调用 /etc/rc?.d 目录中的那些链接。这里 rc2 任务会运行 /etc/rc2.d 下的符号链接对应的 init 脚本。

$ cat /etc/event.d/rc2 
# rc2 - runlevel 2 compatibility
#
# This task runs the old sysv-rc runlevel 2 (”multi-user”) scripts. It
# is usually started by the telinit compatibility wrapper.

start on runlevel 2

stop on runlevel [!2]

console output
script
set $(runlevel –set 2 || true)
if [ “$1″ != “unknown” ]; then
PREVLEVEL=$1
RUNLEVEL=$2
export PREVLEVEL RUNLEVEL
fi

exec /etc/init.d/rc 2
end script

tty 服务

如下是一个在 tty1 上启动并监视 getty 进程的服务的工作定义文件:

$ cat /etc/event.d/tty1 
# tty1 – getty
#
# This service maintains a getty on tty1 from the point when
# the system is started until it is shut down again.

start on runlevel 2
start on runlevel 3
start on runlevel 4
start on runlevel 5

stop on runlevel 0
stop on runlevel 1
stop on runlevel 6

respawn
exec /sbin/getty 38400 tty1

这个服务由 runlevel 2 到 5 (多用户模式)来触发,启动 getty 进程,并在系统关闭、重启或进入单用户模式,即运行级 0,1 和 6 时触发来关闭该服务。respawn关键字告诉 init 在服务终止后重启服务,而 exec 命令是让 getty 进程以 38400 波特率运行在 tty1。如下,initctl 工具显示该服务处于启动状态,进程ID 4747,ps 命令显示该服务的进程:

$ sudo initctl list tty1 
tty1 (start) running, process 4747

$ ps -ef | grep 4747
root 4747 1 0 Jul02 tty1 00:00:00 /sbin/getty 38400 tty1

rc-default 任务和 inittab

在 SysVinit 中,/etc/inittab 文件通过 initdefault 项告诉 init 在系统启动的时候进入哪个运行级,而 Ubuntu 没有 inittab 文件,缺省的,Upstart init daemon (使用 rc-default 任务)引导系统进入多用户模式(缺省运行级为2)。如果希望系统启动进入其他运行级别,那么就创建一个 inittab 文件。如下会让系统缺省进入单用户模式 (runlevel S):

$ cat /etc/inittab 
:id:S:initdefault:

当系统进入到单用户(修复)模式,如果系统的root帐号没有被锁定,init 会在显示 root 提示符之前要求输入 root 密码。否则,它会不要求输入密码而直接显示 root 提示符。

注意:不要将系统设置启动到运行级别 0 或 6,这样系统将永远无法正常启动。要直接进入多用户模式(运行级 2),如果有 inittab 删除这个文件,或者用上述的例子,将里面的 S 替换成 2.

Upstart的未来

从 SysVinit 到 Upstart 的迁移涉及到了 Linux 系统的很多部分。要让这个转换尽量平滑并且引入尽量少的问题,Upstart 团队决定通过多个 release 来完成这个迁移。

Ubuntu 从 Feisty 开始使用 Upstart init daemon。在 Feisty 和 Gutsy+2 之间,Ubuntu 将完成 SysVinit 到更加干净、更加灵活的 Upstart 的迁移。随着越来越多的服务被放到 Upstart 的控制之下,/etc/event.d 目录下的内容将会替代 /etc/init.d 和 /etc/rc?.d 目录下的内容。运行级将不再作为 Ubuntu 正式支持的特征,虽然它们可能为了保持与第三方软件的兼容性而继续保留。最终 Upstart 将会替换掉 crond。

阅读(907) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2011-05-04 15:59:37

让他如果如果方法