[译文]Upstart: Ubuntu 的基于事件的启动进程
By Mark Sobell on February 08, 2008 (9:00:00 AM)
原文链接:http://www.linux.com/feature/125977
翻译时间:2008年3月7日
译者:王旭(gnawux at gmail.com)
译注:尽管译者是一位铁杆的Debian粉丝,但也注意 upstart 很久了,就译者本人观点,upstart 应该说是 Ubuntu 所做的众多工作中最为杰出的一个,它将可以极大地加快 Linux 系统启动的过程。尽管它不是惟一的下一代 init 程序,但它已经作为 Ubuntu 的缺省 init 进程工作了相当长的时间,这点将极大有助于程序的成熟;而且,upstart 使用了基于事件的模型,而不是简单的将各个 daemon 并行化,这个架构上的突破也是具有革命性的,下面我们来看这篇文章吧。
因为传统的System V 的 init daemon (Sysvinit)无法很好地处理现代硬件,如热插拔设备、USB硬盘或山村、网络文件系统等,Ubuntu 使用了Upstart init daemon。
本文抽取自最近出版的 A Practical Guide to Ubuntu Linux.
目前已经有多种 sysvinit 的替代产品了,这其中最为著名的一个就是 initng,它已经可以用于 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。
分享到:
相关推荐
通过QProcess类的start()方法我们可以在基于Qt的应用程序中启动外部Shell脚本,本demo的基本功能包含新增脚本、执行脚本、终止执行、删除脚本、打印输出以及保存脚本记录等。下载该demo后使用Qt Creator打开后可以...
1.4.2 应用程序 ............................................. 17 1.5 本课小结 ..................................................... 21 1.6 复习题 .....................................................
该存储库包含基于node.js的多应用程序/多服务环境的基本框架。 Nginx在node.js应用程序的前面,并充当反向代理。 Ansible剧本将安装程序部署到Ubuntu主机。 此设置可用于通过Vagrant开发。 通过Vagrant,也可以...
2.3 应用程序菜单 27 2.3.1 办公 28 2.3.2 附件 29 2.3.3 互联网 31 2.3.4 图形 33 2.3.5 影音 34 2.3.6 游戏 36 2.3.7 添加/删除软件 36 2.4 位置菜单 36 2.4.1 主文件夹 38 2.4.2 桌面、文档等 39 2.4.3 计算机 39...
也部署您的Web应用程序。 Instant Start对于以最小的努力来设置整个服务器很有用。 只需几分钟即可快速安装服务器的所有组件:全面的OS配置以及Web服务器的可选配置,电子邮件发送功能,脚本语言和数据库。 该信息...
-通过运行一个命令来设置现代的ReactJS Web应用程序 -ReactJS框架 -依赖管理 开发本机应用程序的框架 建议-根据历史记录和完成情况,在您键入命令时建议使用命令 -具有编程连字的等宽字体 消息传递服务组合到一个
角电子应用 使用Windows操作系统的基于Web技术的多平台桌面应用程序。内容表使用这些工具的好处可以使用Electron统一桌面和Web开发人员,该框架使使用Web技术构建本地多平台桌面应用程序成为可能。 通过做这个小项目...
该应用程序是免费的,您可以在Ubuntu商店中找到它 贡献 如果你想与发展论坛的帮助,或者你有一个建议,写了给里卡多或ping rpadovani在Freenode上#Ubuntu的APP-devel的:-) 谢谢 没有这些开发人员的帮助,该游戏将...
2.3 应用程序菜单 27 2.3.1 办公 28 2.3.2 附件 29 2.3.3 互联网 31 2.3.4 图形 33 2.3.5 影音 34 2.3.6 游戏 36 2.3.7 添加/删除软件 36 2.4 位置菜单 36 2.4.1 主文件夹 38 2.4.2 桌面、文档等 39 2.4.3 计算机 39...
appimage 可能是最容易安装的,但通常不会导致菜单集成安装,这意味着必须执行 appimage 文件才能启动应用程序。 只需使用文件资源管理器并打开应用程序图像,应用程序就会运行。 DEB 安装 deb 文件适用于所有基于 ...
BriteCam2 是基于 WebRTC 的视频录制网络应用程序,构建在 Tornado 和 Kurento 媒体服务器上。 Kurento 媒体服务器必须安装在 Ubuntu 14.04 LTS(32 或 64 位)上。 ##安装KMS的说明 sudo apt-get install ...
mpvQC 基于libmpv的应用程序,用于快速轻松地创建视频文件的质量控制报告依存关系Python 3.6或更高版本PyQt5 (AGPLv3)(已包含在此存储库中) (0.29.0或更高版本) 用于开发安装视窗对于便携式Windows二进制文件...
树莓派系统镜像文件包含了完整的操作系统核心、文件系统、驱动程序、应用程序等,可以直接在树莓派上运行,而无需手动安装和配置操作系统。这使得树莓派的部署和使用变得非常方便,尤其对于初学者来说,可以节省大量...
驱动开发的领域本文不涉及,而顶层应用程序开发的一个重要环节就是面向客户的图形界面开发,而图形界面开发嵌入式领域用的比较多的是QT。 Qt是诺基亚开发的一个跨平台的C++图形用户界面应用程序框架。它提供给应用...
该应用程序部分基于UmdBrowser( ),该应用程序列出并导航到UMD图像。 该代码使用最新的Swing Layout库用Java编写,因此此桌面应用程序可以使用OS本机界面(在Mac OS X,Windows和Linux / Ubuntu上经过测试)并在...
一款基于主机入侵防御系统的沙盘工具。允许你在沙盘环境中运行浏览器或其他程序,因此运行所产生的变化...此软件在系统托盘中运行,如果想启动一个沙盘进程,请通过托盘图标(而不要用原方式)启动浏览器或相应程序。
PM2是开源的基于Nodejs的进程管理器,包括守护进程,监控,日志的一整套完整的功能,基本是Nodejs应用程序不二的守护进程选择,事实上它并不仅仅可以启动Nodejs的程序,只要是一般的脚本的程序它同样可以胜任。...
1.4.2 应用程序 ............................................. 17 1.5 本课小结 ..................................................... 21 1.6 复习题 .....................................................
一个简单的程序,可以在Debian / Ubuntu或任何基于Debian的发行版中轻松,专业地为我们的应用程序和程序创建启动器。 只需运行该程序,输入启动器的名称,要运行的命令或程序,启动器图标以及其他选项,例如添加到...