2024年2月24日发(作者:)
原文地址:The Boot Process
翻译:
yuelang85@
目录● 1. 启动过程•1.1. BootROM•1.2. BootX,,系统初始化•1.3. 用户认证•1.4. 配置用户会话•1.5. 注销(Logout Rrsponsibilities)•1.5.1. 应用程序(Application Responsibilities)•1.5.2. 终止进程•1.6. 进程作用域(Identifying the Scope of Processes)•1.7. 关机(The Shutdown Process)●2. 守候进程•2.1. 与守候进程通信•2.2. 查看正在运行的守候进程•2.3. 在一个时间表(Schedule)中运行进程•2.3.1. 使用Periodic实现的定时任务•2.3.2. 使用cron实现定时任务•2.3.3. 使用launchd实现定时任务•2.3.4.
使用at实现定时任务● 3. 如何创建及运行守候进程•3.1. When Is a Custom Daemon Appropriate?•3.2. 什么时候需要自定的守候进程?•3.3. Launching Daemons•3.4. 启动守候进程•3.4.1. Launching Custom Daemons Using launchd•3.4.2. 使用launchd启动自定的守候进程•3.4.3. Launching Daemons with Startup Items•3.4.4. 使用startup item方式启动守候进程●4. 建立一个Startup Iterm•••••••4.1. Anatomy of a Startup Item4.2. Startup Item剖析4.3. Creating the Startup Item Executable4.4. 建立Startup Item内的可执行程序4.5. Specifying the Startup Item Properties4.6. Startup Item特性表的说明4.7. Managing Startup Items
•••••4.8. 管理Startup Item4.9. Displaying and Localizing a Startup Message4.10. 显示及记录Startup Item的信息4.11. Startup Item Permissions4.12. Startup Item的权限● 5. 登录错误和警告•5.1. Log Levels and Log Files•5.2. 日志级别和日志文件•5.3. Logging Errors Using the syslog API•5.4. 使用syslog API记录错误日志•5.5. Logging Errors Using the asl API•5.6. 使用asl API记录错误日志●6. 订制登录和注销•6.1. Login Items•6.2. 登录项•6.2.1. Adding Login Items with Shared File Lists•6.2.2. 使用Shared File Lists添加登录项•6.2.3. Adding Login Items with Apple Events•6.2.4. 使用Apple Events添加登录项•6.2.5. Adding Login Items with CFPreferences•6.2.6. 使用CFPreferences添加登录项•6.2.7. Adding Login Items Manually•6.2.8. 手动添加登录项•6.3. Loginwindow Scripts•6.4. Loginwindow脚本•6.4.1. Installing Scripts Using Defaults•6.4.2. 使用Defaults安装脚本•6.4.3. Installing Scripts Using Loginwindow Hooks•6.4.4. 使用Loginwindow钩子(hook)安装脚本•6.5. Bootstrap Daemons•6.6. Bootstrap守候进程•6.7. Launchd User Agents•6.8. 启动用户代理程序
●1. 启动过程•1.1. BootROM•1.2. BootX,,系统初始化•1.3. 用户认证•1.4. 配置用户会话•1.5. 注销(Logout Rrsponsibilities)•1.5.1. 应用程序(Application Responsibilities)•1.5.2. 终止进程•1.6. 进程作用域(Identifying the Scope of Processes)•1.7. 关机(The Shutdown Process)1. 启动过程从用户启动Mac OS X系统到出现登录窗口,Mac OS X执行了一套启动流程来使系统可被使用。如果你想为所有用户提供系统服务,你需要在系统启动的过程中运行一些代码。下面的章节介绍了基本启动流程和应该把你提供服务的代码放到何处。1.1. BootROM当一台Macintosh被启动时,BootROM固件同时也被激活。BootROM(也是电脑的一个硬件)拥有两个主要职责:初始化(译者注,其实就是启动各个硬件,让其准备好被使用)系统的硬件和选择一个操作系统来启动。BootROM拥有两个部分来帮助它实现这两个职责:••POST(Power-On Self Test,开机自检)初始化硬件接口,验证是否有足够可用RAM以支持系统运行,并检查可用RAM是否处于正常状态。在PowerPC架构的Macintosh电脑上,Open Firmware初始化剩下的硬件,建立最初的设备树(译者注,原文device tree)(类似目录树,一个用层级关系的方式来表示各硬件与主机间的逻辑关系),并且选择操作系统来启动。在Intel架构的Macintosh电脑上,EFI来处理基本的硬件初始化,并且选择一个操作系统来启动。如果安装有多个可启动的Mac OS X系统,BootROM会选择那个最后被系统预置中启动磁盘设置项选择的操作系统。用户可以在电脑启动时按住Option键来自行选择启动的系统,这个做法会让Open Firmware或者EFI显示一个选择启动宗卷的界面。注意,在一些遗留机型(译者注,老机型)上,有些版本的BootROM既可以启动Mac OS 9系统也可以启动Mac OS X。而大多数现在的机型只能启动Mac OS X。1.2. BootX,,系统初始化一旦BootROM的工作完成,并且选择了个Mac OS X分区被选择用其启动,控制权就被传递给BootX(PowerPC平台)或者(Intel平台)启动引导器。启动引导器的主要工作就是加载内核环境(译者注,原文kernel
environment),作此工作时,启动引导器会在屏幕上显示一个启动画面。我们可以在根分区的/System/Library/CoreServices目录下找到BootX和。而且,可以找到/usr/standalone/i386/这个的拷贝。
在“exotic”(译者注,字面意思是“外来的,外国的”,但显然这里不是只外接硬盘的意思。)模式下启动的时候,比如说从一个软RAID宗卷上启动的时候,一个启动引导器会保存在一个叫做独立的HFS+的”辅助“(译者注,原文“helper”)宗卷上来启动系统。在一些版本的Mac OS X上,内核和mkext缓存的拷贝亦会保存在辅助宗卷里。也就是,这种情况下,根分区下面的引导器和其他一些部件不起作用。注意:不推荐用UFS格式做Mac OS X v10.5的引导宗卷。启动过程最开始,启动引导器尝试加载一个包含了所有设备驱动程序的预链接(译者注,原文prelink,这个词的意思是,为了节省时间而预先把一些动态链接库的连接方式记录在执行档中)的内核版本,其位置在:/System/Library/Caches/caches。预链接这些设备驱动程序可以缩短系统启动时间。如果预链接版本的内核丢失,已经过期,或者已损坏,启动引导器会加载一个包含了与预连接内核所列相同驱动的单独压缩包,此包被称作mkext缓存。如果mkext缓存包过期,丢失,或者已损坏,启动引导器会搜索/System/Library/Extensions,寻找OSBundleRequired属性根据启动类型(例如本地启动或者网络启动)所列的驱动列表来加载驱动。查看 I/O Kit Fundamentals ( I/O 工具纲要) 可以获得更多加载驱动的信息。一旦内核和所有为启动而必需的驱动加载成功,启动引导器就启动内核的初始化进程。此时应该有足够的驱动被加载,以找到根设备(译者注,原文root device)来加载内核。也是在此时开始,PowerPC架构的Macintosh电脑上,Open Firmware不再被访问(静默状态)。内核初始化Mach和BSD数据结构(译者注,原文data structure,我也不知道他这里到底指什么意思,应该就是指BSD那一层的东西。)以及I/O Kit。I/O Kit使用设备树(译者注,device tree)作为根据来连接那些已经加载进内核的驱动。一旦内核找到根设备(译者注,原文root device),BSD将把此为根*(译者注,原文Once the kernel
finds the root device, it roots(*) BSD off of it.)(来启动)。注意:作为一个术语,“启动”(boot)这个词传统上讲是指加载启动引导器和启动硬盘或者分区上的内核。而最近几年,这个词的含义被扩展了第二层意义:指启动系统可以被最终用户使用的整个启动过程。在这里,“启动”这个词是指第一种含义。在这里,“根”(root)这个词是指把一个分区作为根分区加载,或者是第一层,或者是文件系统(译者注,原文mounting a partition as the root, or top-level, filesystem,不知道是不是指这个逻辑关系。)。因此,系统在根分区上启动的时候,内核将会在运行启动脚本之前,把这个分区认为根分区(译者注,原文Thus, while the OS boots off of the root partition, the kernel roots the OS off of the
partition before executing startup scripts from it.)。Mac OS X v10.4以前,系统初始化一直是交给mach_init和init来处理。初始化过程中,这两个处理进程调用不同的系统脚本(在/ect/rc目录下),启动程序,为用户准备系统。Mac OSX v10.4以后,这些系统脚本和守候进程的调用交由launchd来处理。也就是说,目前,launchd是系统根进程。除了初始化系统已外,launchd进程还协调系统守候进程秩序地调用。就像inetd进程一样,launchd按需启动守候进程(译者注,原文launchd launches daemons on-demand,其实就是指那种launch-on-demand方式。)。以这种方式调用的守候进程可以在不活动期间被关闭或者按需要重启。(当一个服务的请求发送过来的时候,launchd会自动重新启动守候进程去处理请求。)这种方式可以释放守候进程占用的内存和其他相关资源,当守候进程在一段很长的时间闲置的时候,这样做非常值得。但更重要的,这样做相对于人工方式能更有效的处理守候进程间的依赖关系。然后,launchd 启动SystemStarter,后者用来启动那些非按需启动(译者注,原文non-launch-on-demand)的守候进程。
注意,launchd也支持非按需启动的守候进程,但是这种用法并不推荐。launchd守候进程被设计用来消除守候进程之间的依赖关系。如果你不把你的守候进程设置成按需启动(译者注,原文launch-on-demand),你就需要用其他办法处理依赖问题,比如用那种遗留下来的Startup Item机制。查看Daemons 可以获得更多关于按需启动(原文launch-on-demand)和SystemStarter守候进程的信息。系统初始化的最后阶段,launchd启动loginwindow。loginwindow程序控制了用户会话(原文user session)各自的外观(原文aspect)和登录窗口的调整以及用户登录认证。注意,默认情况下,Mac OS X随着一个图形化的启动屏幕启动。为了调试启动进程,我们也可以禁用它,而显示文字操作台信息。这种模式被称作verbose启动模式。要想使用verbose启动模式,只需要在启动的时候按住command-v键。1.3. 用户认证Mac OS X要求用户在进入系统前进行验证。loginwindow程序分为登录部分(显示为用户输入用户名和密码的窗口)以及安全部分(处理用户的认证信息)。一旦通过安全系统的认证,loginwindow程序开始配置用户环境。有两种情况loginwindow会忽略通常的登录方式而直接开始用户会话。第一种是当系统管理员设定计算机自动以一个指定的用户登录的时候。另一种是安装软件时,如果installer程序在电脑重启后立即运行的时候。1.4. 配置用户会话用户成功认证后,loginwindow会马上配置用户环境并且记录这次登录信息。此时会进行如下任务:•对未经授权的远程登录会话采取安全措施。未经注册(译者注,原文reigstered,就是指前面说的未经授权)的应用程序不能使用粘贴板服务(Clipboard)端口。再此情况下,一些标准的功能不能使用,包括复制,剪切,粘贴,Apple events,窗口最小化,还有其他服务。•••••••••••••把登录记录在系统的utmp数据库中。为控制台终端配置拥有者(译者注,原文owner)和权限。重置用户偏好,从而加入全局系统默认值。通过bootstap端口和启动pbs注册粘贴板服务(pbs)。根据用户偏好设置鼠标,键盘,系统声音。设置用户组权限(gid)从目录服务(Directory Services)中检索用户记录,并且将信息加入到此会话中。加载用户环境(包括偏好设置,环境变量,设备和文件权限,钥匙串访问(keychain access)等等)。启动Dock,Finder和SystemUIServer。启动用户在 偏好设置 中的 帐户设置 中 登录项目项 中设置的应用程序。一旦用户会话启动并开始运行,loginwindow通过一下方式监视会话和用户的应用程序。管理用户登出,重启和关闭过程。查看“Logout Responsibilities“以获得更多信息。管理强制退出窗口,包括监视当前活动的应用程序,并且响应用户对强制退出某应用程序或者重启Finder的请求(用户可以从苹果菜单或者按下Command-Option-Escape键来启动强制退出窗口)。将标准错误输出(stderr)写入日志文件。日志文件储存在/资源库(Library)/Logs/Console/
1.5. 注销(Logout Rrsponsibilities)注销,系统重启,关机,这些过程都有着相似语义。前端进程往往因用户在苹果菜单中选择上述一项而启动这些过程。然而,一个进程也可以以编程的方法向loginwindow发送一个响应的Apple event来启动这些过程。loginwindow程序执行这个过程(译者注,指注销,系统重启,关机这些中的一项),发送报警(alert)以及通知应用程序,让他们有机会在关闭前做调整。以下是一个典型的注销/系统重启/关机过程:1.用户在苹果菜单中选择注销,重新启动,或者关机项。2.前端程序根据用户请求向loginwindow发送一个Apple event。indow程序向用户显示一个警示对话框向用户求证是否要执行此操作。4.如果用户确定执行此操作,则loginwindow向每一个前端和后端的用户进程发送一个“Quit Application
Apple event“(kAEQuitApplication)。5.一旦所有进程退出,loginwindow关闭用户会话,并继续执行:•对于注销操作,loginwindow将事件队列中的所有事件出列,启动logout-hook程序(如果有定义),记录注销操作,将设备权限和用户偏好重设为默认值,并退出。随后launchd会启动一个新的登录。(查看“Customizing Login and Logout“以获得更多关于loginwindow hook的信息。)••息。对于重新启动操作,longinwindow将设备权限和用户偏好设置为默认值并重启系统。对于关机操作,loginwindow将系统关闭。前端进程在接收到Quit Application event的时候可以选择不终止程序。查看“Terminating Processes“以得到更多信1.5.1. 应用程序(Application Responsibilities)要想以程序的方式启动一个注销,重新启动,或者关机过程,前端应用程序必须向loginwindow发送一个相应的Apple event。接收到event后,loginwindow开始关闭用户会话。根据发送过来的Apple event,loginwindow会选择是否展示一个警示对话框并给用户一个取消此过程的机会。下表显示了注销,重新启动,关闭过程对应的Apple event。这些event不需要参数。•••kAELogOutkAEShowRestartDialogkAEShowSutdownDialog接收到这些event后,loginwindow显示一个警示对话框通知用户计算机即将执行的操作。此时,用户可以选择继续此操作或者终止它。如果用户继续此操作,loginwindow向每个应用程序发送一个要求其退出的Apple event。查看 “ T erminating Processes.“ 以获得更多信息。这里还有两个event用来通知loginwindow立即重新启动或是关闭:••kAERestartkAEShutDown这些event被处理时不会向用户展示警示对话框。因此,如果你这些event给loginwindow,用户没有机会去取消操作,所以这些event要被谨慎地使用。重要信息:注意,如果一个注销,重新启动或者关机event是被一个Classic环境中的应用程序发送的,这些event只会对Classic环境和其中的应用程序起作用。剩下的用户会话将会继续运行。
1.5.2. 终止进程作为注销,重新启动,关机过程中的一部分,loginwindow尝试终止所有的前台和后台的用户进程。它向每个进程发送Quit Application Apple event(kAEQuitApplication),并且出于礼貌(译者注,原文as a courtesy,看着有点搞笑,但确实是这个意思)它会给每个进程优雅的关闭的机会。对于前端进程,loginwindow发送event并且等待回复。对于后端进程,loginwindow发送event,而不等待回复。它会用kill命令终止拖延的后端进程。当一个前端进程接收到loginwindow发送过来的Quit Application Apple event时,它会立即终止自己,或者在用户需要时显示一个警示对话框(例如此时正有一个未保存的文档),等问题解决后再终止自己。如果用户决定取消终止(例如在保存对话框中点取消按钮)应用程序会给发送过来的event返回一个userCancelledErr错误。注意:Cocoa应用程序不支持kAEQuitApplication event,取而代之的,Application Kit通过调用delegate方法applicationShouldTerminalte来实现终止程序。要想取消此操作,可以实现这个方法并返回NSTerminateCancel;不然,应用程序的终止操作将会继续执行。如果一个前端应用程序响应失败或者超过45秒钟仍未终止,loginwindow自动取消终止操作。这个保护措施可以在很多情况下保护数据,例如当一个应用程序正在保存一个大文件到磁盘中并且此时不能在要求的时间内终止程序的时候。如果一个前端应用程序反应迟钝或者没有做任何事情,用户必须使用“强制退出”来强制退出(kill)该程序。对于使用了(link with)Carbon,Cocoa,Java的后端进程,操作方式将会有一点不一样。loginwindow程序通过发送Quit Application Apple event(kAEQuitApplication)通知进程将被终止。不同于对待前端进程那样,loginwindow不等待后端进程回应,它直接终止开放的后端进程,不管任何被返回的错误信息。用户注销的过程中,loginwindow不会终止root层的进程。这些进程不属于用户会话,他们只会在重新启动或者关机的时候被终止。loginwindow程序也不会杀死(kill)不依赖Carbon,Cocoa,Java的后端进程,尽管他们是用户层进程。(尽管在用户层面被启动,这些进程在用户登出的时候被系统接管。)Mac OS X在终止系统进程的时候不会向其发送任何通知。1.6. 进程作用域(Identifying the Scope of Processes)尽管launchd进程是所有其他系统进程的拥有者,用户和系统进程间仍然会被区分。“startup item“,守候进程,以及其它在loginwindow之前运行的进程一般是运行于root层。这一层次的进程为系统的所有用户提供服务。运行于已认证的用户会话中的进程被称作“用户进程”(user processes)。用户进程往往附属于用户会话,往往也是WindowServer和loginwindow进程的子进程。注意:不是所有的用户进程都是WindowServer进程的子进程。那些root层启动的进程,特殊的系统进程,这些进程拥有者是用户,但他们是launchd的子进程。你可以通过活动监视器来判断系统中一个进程的拥有者和父进程。1.7. 关机(The Shutdown Process)关机时,Mac OS X首先关闭SystemStarter启动的项目,比如在“Creating a Startup Item“中描述的项目。然后,就像大多数基于UNIX或者类UNIX操作系统那样,Mac OS X在关机前发送一个SIGTTERM信号给所有在运行的进程。一旦接收到这个信号,你的守候进程会迅速合理地关闭自己。允许合理的尝试等待进程退出,不过你的守候进程的最终责任是把未保存的信息在分配的时间内保存在磁盘上。几秒钟后,你的守候进程会接收到一个SIGKILL信号,并被终止。
●1. 守候进程•••1.1. 与守候进程通信1.2. 查看正在运行的守候进程1.3. 在一个时间表(Schedule)中运行进程••••1.3.1. 使用Periodic实现的定时任务1.3.2. 使用cron实现定时任务1.3.3. 使用launchd实现定时任务1.3.4. 使用at实现定时任务1. 守候进程当用户登录Mac OS X系统的时候,会运行大量进程。这其中很多是守候进程。守候进程是系统为用户提供服务的一种后台进程。例如,cupsd这个守候进程用来调度打印请求,而httpd守候进程用来响应web页面请求。大多数的守候进程运行于系统的根级别,他们在最底层运行,向所有的用户会话提供服务。这个层面运行的守候进程可以持续运行,甚至没有用户登录。因此守候进程不需要确切的知道某个用户,他们需要等用户程序去请求他,通常用户程序请求的时候也会告诉守候进程如何返回结果。注意:要想获得更多的关于根级别和用户会话的知识,请看多用户环境。1.1. 与守候进程通信显然,程序要经常和系统的守候进程通信。比如说,当你用CFNetwork API打开一个网络联接的时候,API自己就会和几个守候进程通信,来处理你的请求。大多数情况下,你的程序不需要关心通信的细节问题。注意:和许多系统守候进程通信是可行的。大多数系统守候进程是位于Mac OS X系统结构的Darwin层并且拥有良好的文档的通信协议。然而大多数情况下,让Mac OS X的库和框架来为你实现这种通信更简单,现实,可靠。如果要创建一个自设的守候进程,你需要定义一个协议来接受请求和返回结果。为了给使用你的进程的客户端简化操作,你需要自行定义库来常规性的生成请求和处理获得的结果。例如,如果你创建一个用来管理数据库的守候进程,你需要创立一个包含了处理与守候进程通信的函数的库。客户端在链接你的库的时候,应该清晰的知道该如何通信,而不需要理解通信过程中的具体细节(译者注,原文中这里是指通信架构)。这里有三种主要的用于守候进程和客户端的通信架构类:传统的客户伺服器通信(包括了Apple
events,TCP/IP,UDP,和其他的socket及管道架构,还有Mach IPC),远程过程通知(译者注,原文:remote
procedure calls,RPC)(包括了Mach RPC,Sun RPC,还有分布式对象(译者注,原文 Distributed
Objects)),还有储存器映像(译者注,原文memory mapping)(典型的有底层的Core Graphics API们)。通常的,你应该使用传统的客户伺服器通信API。基于这些API的代码相对于RPC和内存交换方式通信更易于理解和维护,也更容易移植到其他平台。如果你的客户端和守候进程都是用Cocoa写的,而且你的大多数通信是发送一个消息并等待返回,你应该考虑使用分布式对象方式,这是一种RPC架构的通信方式。因为储存器映像需要复杂的控制(如果你不关心你所共享的内存页到底是什么,这将会变成一个安全隐患),只有在你的客户端和守候进程需要大量的低延迟数据交换的时候,才使用储存器映像,比如说实时操作音频或图片。
至于如何使用这些通信方式的细节,这个超出了本文的讨论范畴,不过你可以在ADC Reference Library中找到相关文档。相关的文档有:••••••Apple Events Programming Guide Distributed Objects Programming Topics
SharedMemory
CFSocket Reference
NSSocketPort Class Reference
UNIX Socket FAQ
1.2. 查看正在运行的守候进程如果你想查看系统在目前正在运行的守候进程,可以使用活动监视器程序(在/Applitcation/Utilities下)。这个程序可以让你查看到所有的进程的信息,包括使用了多少资源。图1显示了活动监视器的窗口和进程信息。注意:如果你想知道更多一个守候进程提供的服务的信息,可以查看这个守候进程的man手册。你也可以查看在线手册:Mac OS X Man Pages图1 活动监视器中显示的进程1.3. 在一个时间表(Schedule)中运行进程有时你需要在让一个守候进程或者其他后台进程按照一个时间表来运行。在Mac OS X中,你可以有四种方法实现:cron任务,at任务,launchd定时任务,还有periodic任务。这章将简单解释这四种方法并给出阐述了他们详细细节的手册的链接。
1.3.1. 使用Periodic实现的定时任务如果你的定时任务需要周期性的执行,最简单的方法就是创建一个periodic任务。要想创建一个periodic任务,你只需创建一个通过指定标记来运行你的程序的shell脚本,并将其放入到/etc/periodic下面的daily,weekly,monthly目录下。不同的Mac OS X版本系统通过不同的方法执行这些任务。Mac OS X v10.3以及更早的版本中,cron被用来执行periodic任务。在v10.4以后的版本中,launchd被用来执行任务。因此,如果你的电脑在应该运行任务的时间休眠了,在Mac OS X v10.3及更早的版本中,该任务就不会运行。而在Mac OS X v10.4及以后的版本中,该任务会在电脑唤醒后自动运行。所以,一个任务不一定是在指定的天指定的时间运行。注意:如果电脑在应该运行任务的时间处于关闭状态,则任务就根本不会被运行(译者注,即使启动后也不会运行),不管你所使用的是哪个版本的Mac OS X。你可以通过修改/etc/defaults/来配置periodic。查看 可以得到更多相关信息。1.3.2. 使用cron实现定时任务cron守候进程是被应用得最广的用来在特定的时间执行任务的工具。尽管所有的Mac OS X版本的系统都支持cron,但是从v10.4开始,cron的大多数应用都被launchd所替代,甚至所有的periodic任务都被launchd来实现。一个cron任务并不会一定被执行,如果在应该执行任务的时候电脑正处于关闭或者睡眠状态,任务就不会被执行,直到下一次符合条件的时间点出现。通过修改/etc/crontab来设置系统级别的cron任务。用户级别的cron任务通过使用crontab来设定。crontab的文件格式的详细信息可以在crontab的man手册中查到。因为设置cron任务需要修改一个共享资源(crontab文件),所以你无法通过编程的方式来添加一个cron任务(译者注,这句话没有彻底明白,原文是:Because installing cron jobs requires modifying a shared resource (the
crontab file), you should not programmatically add a cron job.)。然而,cron仍然是一个为系统管理员或者高级用户准备的重要工具。1.3.3. 使用launchd实现定时任务从Mac OS X v10.4开始,设置定时任务的最好方法就是使用launchd定时任务。一个launchd定时任务很像cron任务,不过有两个不同:••每个launchd任务都在一个独立的文件中定义。这就表示你可以仅仅通过添加和删除文件来建立或去掉launchd定时任务。如果电脑在应该执行任务的时候是睡眠状态,则launchd任务会在电脑被唤醒时执行。这点很像anacron或者其他cron替代者。要想建立一个launchd定时任务,你需要创建一个包含了配置信息的特性表(译者注,property list,就是我们经常见到的.plist文件。),这个特性表和 ”Creating a Launchd Property List File“中描述的一样,只不过OnDemand=true这个键值对要被替换成一个叫”StartCalendarInterval”的键值对,其值是一个包括了时间设定的字典。例如,下面的特性表设定了要在每个七月十一日星期六的午夜运行程序happybirthday的定时任务。
/DTDs/ >
要想获得关于键值对定义的详细信息,请查看手册 1.3.4. 使用at实现定时任务为了节约资源,at守候进程在Mac OS X中默认是被禁用的。如果你想启用他,你可以通过查阅手册来获得详细信息:at●1. Guidelines for Creating and Launching Daemons●2. 如何创建及运行守候进程•2.1. When Is a Custom Daemon Appropriate?•2.2. 什么时候需要自定的守候进程?•2.3. Launching Daemons•2.4. 启动守候进程•2.4.1. Launching Custom Daemons Using launchd•2.4.2. 使用launchd启动自定的守候进程•2.4.3. Launching Daemons with Startup Items•2.4.4. «»使用startup item方式启动守候进程
1. Guidelines for Creating and Launching Daemons2. 如何创建及运行守候进程Mac OS X comes with several daemons that provide most of the basic system services. Examples of
these services include handling network lookup requests, serving web pages, monitoring hardware
devices, and gathering metadata from the file system. The clients of these services may be the
operating system, client applications, or both. An example of a daemon used by the system is the mds
daemon, which monitors the file system and initiates the gathering of metadata. The system gathers the
metadata and puts it in a central repository, which client applications can then access.«»Mac OS X自带的一些守候进程提供了大多数的基础系统服务。例如这些服务:提交查找网络请求,网页服务,硬件设备监视,从文件系统搜集metadata。这些服务的客户端可能为操作系统,客户端应用程序,或者两者都是。比如mds 守候进程的客户端就是操作系统,mds用于监视文件系统以及启动metadata的搜集。操作系统搜集metadata,并将其放入一个中央容器内,这个中央容器可以被客户端应用程序访问。Although the general steps for how to create a new daemon are beyond the scope of this document,
there are some things that daemon writers need to understand before writing daemons for Mac OS X.«»尽管介绍如何创建一个新的守候进程的一般步骤超出了该文档的范围,但是在写一个新Mac OS X的守候进程前,这里还是有一些东西需要程序员了解。2.1. When Is a Custom Daemon Appropriate?2.2. 什么时候需要自定的守候进程?Most application developers will never need to create a daemon directly. Even those developers that
need some sort of background server may not find a daemon to be the best choice in all cases.«»大多数开发者不会需要建立一个守候进程,甚至有时看似最好的选择就是建立一个后台守候进程。Daemons run in the root context, which means they are unaware of the users logged on to the system. A
daemon cannot initiate contact with a user process directly, although it can respond to requests made
by user processes. Because they have no knowledge of users, daemons also have no access to the
window server, and thus no ability to post a visual interface. Daemons are strictly background processes
that respond to low-level requests.«»守候进程运行于root层,这就意味着它们不关心用户是否登录系统。一个守候进程不能发动与用户进程的联系,尽管它可以回复用户进程的请求。因为它们对用户一无所知,守候进程亦不能访问窗口服务,因此也不能建立一个虚拟虚拟界面。守候进程是严格的后台进程,它回应底层的请求。If you need to provide user-specific services, you should create an agent instead of a daemon. An agent
is essentially the same thing as a daemon, except that it runs in the context of a user session. Agents
can communicate with other processes in the same user session and with system-wide daemons in the
root context. Because they have access to the window server, agents can also post a user interface,
although they should do so sparingly, if at all. Like daemons, agents should be launched automatically.«»如果你需要向指定的用户提供服务,你需要创建一个代理程序(agent)来取代守候进程。代理程序本质上和守候进程没有什么不同,区别是,代理程序运行于用户会话中。代理程序可以和用户界面下的其他进程通信,同时也可以和
root层的系统级的守候进程通信。因为代理程序可以访问窗口服务,所以它可以建立一个用户界面,尽管这么做需要谨慎。和守候进程一样,代理程序可以被自动启动。The only difference between a daemon and an agent is location: daemons are installed in
/Library/LaunchDaemons, while agents are installed in /Library/LaunchAgents or in the LaunchAgents
subdirectory of an individual user’s Library directory.«»守候进程和代理程序唯一的不同是处于不同的路径:守候进程被设置在/Library/LaunchDaemons下,而代理程序被设置在/Library/LaunchAgents/或者用户目录的资源库中的LaunchAgents中。If you find that your code provides both user-specific and user-independent services, you might want to
create both a daemon and an agent. Your daemon would run in the root context and provide the user-independent services while a copy of your agent would run in each user session. The agents would then
coordinate with the daemon to provide the services to each user.«»如果你的代码既向指定用户又向非指定用户提供服务,你可能希望建立一个守候进程和一个代理程序。你的守候进程运行于root层以为非指定的用户提供服务,而且每个用户会话中都有一个你的代理程序的拷贝。这些代理程序和守候进程共同为每个用户提供服务。For more information about the root context and user sessions, see Multiple User Environments.«»查看Multiple User Environments 可以获得更多关于root层和用户会话的信息。2.3. Launching Daemons2.4. 启动守候进程Mac OS X provides two methods for launching daemons: startup items and launchd daemons. Which one
you use depends largely on the versions of Mac OS X that the daemon must support.«»Mac OS X提供了两种方法启动守候进程:“startup items“和“launchd 守候进程“。具体使用哪一个取决于守候进程要运行于哪个版本的Mac OS X:•••Mac OS X v10.3 and earlier: You must use startup items. The launchd service is not supported
prior to OS X v10.3及之前的版本:你必须使用“startup items”。v10.4以前的系统不提供launchd服务。Mac OS X v10.4 and later: You can either use startup items or launchd daemons. Using launchd
daemons is preferred unless you also require backwards compatibility with versions of Mac OS X
prior to v10.4.•Mac OS X v10.4及之后的版本:你既可以使用“startup items”也可以使用launchd守候进程。如果不需要考虑对v10.4以前的系统的支持,使用launchd守候进程是最好的。Of course, you do not necessarily have to choose one or the other. For optimal compatibility and
performance, you could use both. The key is to add a command-line argument or arguments to enable
or disable launchd-compliant behavior, such as launch-on-demand support.«»当然,你没有必要二选一。为了最好的兼容性和性能,你可以两者都使用。重要的是,你应该利用注释来控制是否使用launchd的方式启动守候进程,例如launch-on-demand类型的守候进程的支持。Once you have the ability to launch your daemon in either form, you can install both a launchd property
list and a startup item. To avoid launching your daemon twice, be sure to add code to the startup item to
disable it in Mac OS X v10.4 or later. For example, the following will print “10.3 or earlier” if it is running
on a version of Mac OS X prior to v10.4:«»如果你的程序支持在两个平台上启动,你可以同时安装launchd特性表(property list)和startup item。为了不同时启动两个守候进程,应该在startup item中添加一些代码,用于确保其在v10.4及以后的版本系统中不运行。例如,下面的代码在v10.4以前的系统上运行的时候会显示“10.3 or earlier”。Listing 1 Conditional Startup Item Execution表 1 Startup Item运行时判断系统版本#!/bin/sh
OSVERSION="$(sw_vers -productVersion)"MAJOR="$(echo $OSVERSION | sed 's/..*//')"MINOR="$(echo $OSVERSION | sed -E 's/[0-9]+.([0-9]+)..*/1/')"PATCH="$(echo $OSVERSION | sed -E 's/[0-9]+.[0-9]+.([0-9]+).*/1/')"
echo "MAJOR: $MAJOR"echo "MINOR: $MINOR"echo "PATCH: $PATCH"
if [ $MAJOR -eq 10 ] ; then
if [ $MINOR -le 3 ] ; then
echo "10.3 or earlier";
fifiFor more information about shell scripting, read Shell Scripting Primer.查看“Shell Scripting Primer“可获得更多关于shell脚本的信息。2.4.1. Launching Custom Daemons Using launchd2.4.2. 使用launchd启动自定的守候进程With the introduction of launchd in Mac OS X v10.4, an effort was made to improve the steps needed to
launch and maintain daemons. Prior to 10.4, if you wanted to launch a custom daemon, you had to
create a startup item to do so. During boot up, the system would execute your startup item, allowing
you to run a script that launched your daemon. Once launched, your daemon would continue running
(and continue holding on to memory and resources) until the computer was shut down or restarted, the
daemon was manually shut down, or the daemon itself crashed.«»launchd是在Mac OS X v10.4中被加入的一种提高启动和维持守候进程的方法。10.4以前的版本,如果你想启动一个守候进程,你必须建立一个Startup Item来做这件事情。在系统启动的过程中,系统会运行你的Startup Item,允许你执行你的脚本来启动守候进程。一旦启动,你的守候进程会一直运行(也会一直占用内存和其他资源),直到电脑关闭或者重启,或者守候进程被手动关闭,或者它自己crash掉。What launchd does is provide a harness for launching and relaunching your daemon as needed. To
client programs, the port representing your daemon’s service is always available and ready to handle
requests. In reality, the daemon may or may not be running. So, when a client sends a request to the
port, launchd may have to launch the daemon so that it can handle the request. Once launched, the
daemon can continue running or shut itself down to free up the memory and resources it holds. If a
daemon shuts itself down, launchd once again relaunches it as needed to process requests.«»launchd提供了启动和重启守候进程的方法。对于客户端程序来说,守候进程的接口始终是打开并且可以处理请求的。而实际上,守候也许并没有在运行。当一个客户端向端口发送请求的时候,launchd会启动守候进程,让其处理请求。守候进程一旦启动,它会持续运行,或者自行关闭以释放占用的内存和其它资源。如果守候进程将自己关闭,launchd会在需要的时候再次启动它。In addition to the launch-on-demand feature, launchd provides the following benefits to daemon
developers:launchd的launch-on-demand(按需启动)功能对于守候进程开发者来说有以下好处:••Simplifies the daemonization process by handling many of the standard housekeeping chores
normally associated with launching a daemon.通过启动守候进程来处理事务(译者注,而不是让守候进程一直保持运行状态来等待任务)这个机制,简化了创建守候进程的过程(译者注,这样就不需要通过代码来实现守候进程了,只需要把普通进程作为守候进程用launchd启动即可)•••••••Provides system administrators with a central place to manage daemons on the system.为系统管理员提供一个统一管理守候进程的地方。Supports inetd-style daemons.支持inetd方式(译者注,inetd-style,Internet超级服务器,inetd是监视一些网络请求的守护进程,其根据网络请求来调用相应的服务进程来处理连接请求)的守候进程。Eliminates the primary reason for running daemons as root. Because launchd runs as root, it can
create low-numbered TCP/IP listen sockets and hand them off to the daemon.因为launchd运行于root层,所以他可以把低号码段的TCP/IP监听端口分配给守候进程。因为此原因,不再需要用root启动守候进程(这也是必须用root启动守候进程的主要原因)。Simplifies error handling and dependency management for inter-daemon communication.
Because daemons launch on demand, communication requests do not fail if the daemon is not
launched. They are simply delayed until the daemon can launch and process them.•简化了错误的提交和守候进程间通信。因为守候进程是按需启动的(译者注,即launch-on-demand方式),所以通信请求在守候进程没有启动的时候不会失效。这些请求只会等待守候进程启动并将他们处理掉。For more information on how to create a launch-on-demand daemon, see “Creating launchd Daemons
and Agents.”查看“Creating launchd Daemons and Agents“可获得更多关于如何创建launch-on-demand类型守候进程的信息。2.4.3. Launching Daemons with Startup Items2.4.4. 使用startup item方式启动守候进程If your software includes a custom daemon and must support versions of Mac OS X prior to 10.4, use a
startup item to launch the daemon. A startup item is a bundled shell script or executable binary that
runs once when the computer first boots (see “The Boot Process”).
«»如果你的软件包括一个自定义的守候进程,并且该软件必须支持Mac OS X 10.4以前版本的系统,那么你就需要使用startup item启动守候进程。startup item是一个束,其打包了shell脚本或者二进制可执行程序,这个shell脚本或二进制执行程序会在计算机启动的时候运行一次(详细请看“The Boot Process”)。If you have custom startup items, you should install them in the /Library/StartupItems directory. Apple
startup items are located in the /System/Library/StartupItems directory, although most of them have
been stubbed out in Mac OS X v10.4 and later and replaced by launchd-compliant versions. The stubbed
out versions remain for the benefit of other startup items that have dependencies on them.你应该把自定义的startup item放置在 /Library/StartupItems目录下。尽管其中的大部分在v10.4以后被launchd方式取代,Apple startup item仍被放置在/System/library/StartupItems目录下,因为还有其他的一些startup
item会依赖与这些被取代的版本。For information on how to create a startup item, see “Creating a Startup Item.”查看“Creating a Startup Item”可以获得更多关于如何创建startup item的信息。●1. Creating a Startup Item●2. 建立一个Startup Iterm•2.1. Anatomy of a Startup Item•2.2. Startup Item剖析•2.3. Creating the Startup Item Executable•2.4. 建立Startup Item内的可执行程序•2.5. Specifying the Startup Item Properties•2.6. Startup Item特性表的说明•2.7. Managing Startup Items•2.8. 管理Startup Item•2.9. Displaying and Localizing a Startup Message•2.10. 显示及记录Startup Item的信息•2.11. Startup Item Permissions•2.12. Startup Item的权限1. Creating a Startup Item2. 建立一个Startup ItermA startup item is a specialized bundle whose code is executed during the final phase of the boot process,
and at other predetermined times (see “Managing Startup Items”). The startup item typically contains a
shell script or other executable file along with configuration information used by the system to determine
the execution order for all startup items.«»Startup Item是一个特殊的束,它会在系统启动过程的最后时候或者其他预定的时间(具体查看“Managing
Startup Items”)运行。Startup Item通常包含一个shell脚本或者其他可执行程序,以及用于让系统决定启动各个Startup Item的启动顺序的配置信息。The /System/Library/StartupItems directory is reserved for startup items that ship with Mac OS X. All
other startup items should be placed in the /Library/StartupItems directory. Note that this directory does
not exist by default and may need to be created during installation of the startup item.«»/System/Library/StartupItems目录是存放Mac OS X自带的Startup Item的地方。而其他的Startup Item存放于/Library/StartupItems目录下。注意/Library/StartupItems默认情况下不一定存在,必要时需要创建。Note: The launchd facility is he preferred mechanism for launching daemons in Mac OS X
v10.4 and higher. Unless your software requires compatibility with Mac OS X v10.3 or earlier,
you should use the launchd facility instead of writing a startup item. For more information,
see “Guidelines for Creating and Launching Daemons.”«»注意:launchd是在Mac OS X v10.4既更高版本中使用守候进程的首选机制。除非你的软件需要兼容于Mac OS X v10.3以及更早版本,你都应该使用launchd机制,而不是Startup Item。查看 “ Guidelines for Creating and Launching Daemons.” 以获得更多信息。Important: A startup item is not an application. You cannot display windows or
do anything else that you can’t do while logged in via ssh. If you want to launch
an application after login, you should install a login item instead. For more
information, see “Customizing Login and Logout.”«»重要提示:Startup Item不是应用程序。你不能使用它显示窗口或者其他东西,就像你不能在用ssh登录系统时显示他们一样。如果你想在登录后启动一个应用程序,你需要设置一个登录项(译者注,原文login item)。查看 “ Customizing Login and Logout.” 以获得更多信息。2.1. Anatomy of a Startup Item2.2. Startup Item剖析Unlike many other bundled structures, a startup item does not appear as an opaque file in the Finder. A
startup item is a directory whose executable and configuration property list reside in the top-level
directory. The name of the startup item executable must match the name of the startup item itself. The
name of the configuration property list is always . Depending on your needs, you
may also include other files in your startup item bundle directory.«»与很多其他束结构的包不同,Startup Item在finder中不会被显示成一个单独的文件。Startup Item是可执行的,并且包含了设置信息的特性表就在束的最上一层目录里。Startup Item束中的可执行程序的名字必须和Startup Item束的名字相匹配(译者注,其实就是相同)包含了设置信息的特性表的名字总是“”。如果需要,你的Startup Item束目录中还应该包含所需的其他文件。MyStartupItem/
MyStartupItem
To create your startup item:要想建立一个Startup Item,你需要做以下步骤: the startup item directory. The directory name should correspond to the behavior you’re
providing.
Example: your executable to the directory. The name of your executable should be exactly the same
as the directory name. For more information, see “Creating the Startup Item Executable.” a property list with the name and add it to the directory. For
information on the keys to include in this property list, see “Specifying the Startup Item
Properties .”
Example: MyDBServer/ an installer to place your startup item in the /Library/StartupItems directory of the target
system. (Your installer may need to create this directory first.)
Your installer script should set the permissions of the startup item directory to prevent non-root
users from modifying the startup item or its contents. For more information, see “Startup Item
Permissions.”1.建立Startup Item目录。这个目录的名字应该和你想实现的功能相符。例如:MyDBServer。2.在目录中加入可执行程序。可执行程序的名字应该和目录名一致。查看 “ Creating the Startup Item
Executable”以获得更多信息。3.在目录中建立一个名叫的特性表。查看 “ Specifying the Startup Item
Properties”可以获得更多关于写入该特性表内的key的信息。例如:MyDBServer/4.建立一个安装器,该安装器用于把你的Startup Item放入/Library/StartupItems目录。(当然,你的安装器应该先建立这个目录。)你的安装器应该设定Startup Item的权限,以防非root用于随意修改Startup Item及其内容。查看 “ Startup Item Permissions” 以获得更多信息。2.3. Creating the Startup Item Executable2.4. 建立Startup Item内的可执行程序The startup item executable can be a binary executable file or an executable shell script. Shell scripts
are more commonly used because they are easier to create and modify.«»Startup Item内的可执行程序可以是一个二进制可执行文件,也可以是一个可执行的shell脚本。Shell脚本被更普遍的使用,因其创建起来更方便。If you are implementing your startup-item executable as a shell script, Mac OS X provides some code to
simplify the process of creating your script. The file /etc/ defines routines for processing
command-line arguments and for gathering system settings. In your shell script, source the
file and call the RunService routine, passing it the first command-line argument, as shown in the
following example:
«»如果你使用shell脚本来作为Startup Item的可执行程序,Mac OS X提供了一些代码以简化创建shell脚本的过程。/etc/文件定义了对命令行参数的定义,以及搜集了系统设置。在你的shell脚本里,引用文件,调用RunService函数(译者注,该函数在中定义,需要输入的参数为“start”,“stop”,“restart”,分别对应调用StartService,StopService,RestartService函数),将第一个命令行参数传递给RunService,例如:#!/bin/sh. /etc/
# The start subroutineStartService() {
# Insert your start command below. For example:
mydaemon -e -i -e -i -o
# End example.}
# The stop subroutineStopService() {
# Insert your stop command(s) below. For example:
killall -TERM mydaemon
sleep 10
killall -9 mydaemon
# End example.}
# The restart subroutineRestartService() {
# Insert your start command below. For example:
killall -HUP mydaemon
# End example.}RunService "$1"The RunService routine looks for StartService, StopService, and RestartService functions in your shell
script and calls them to start, stop, or restart your services as needed. You must provide
implementations for all three routines, although the implementations can be empty for routines whose
commands your service does not support.«»RunService函数用于寻找你在shell脚本中定义的StartService,StopService,RestartService函数,并且在需要时调用他们以开始,停止,重启你的服务。你必须实现这三个函数,尽管有可能你的服务不支持其中某项命令,也要将其留空。
If your startup-item executable contains code that might take a long time to finish, consider spawning
off a background process to run that code. Performing lengthy startup tasks directly from your scripts
delays system startup. Your startup item script should execute as quickly as possible and then exit.«»如果你的Startup Item中的可执行程序需要运行很长时间,建议启动一个后台进程来运行这些代码。运行冗长的启动任务会直接让你的脚本拖延系统的启动。你的启动脚本应该尽可能快速的运行完毕。For more information about writing shell scripts, see Shell Scripting Primer.«»阅读Shell Scripting Primer 以获得更多关于编写shell脚本的信息。Note: Most apple-provided startup items have a test in the script to check to see if a
particular variable is set to prevent automatic starting of daemons unless they are enabled
(usually in the System Preference sharing pane).To enable or disable a daemon that does not have a GUI checkbox, you must add or modify
these variables directly by editing the file /etc/hostconfig.«»注意:大多数apple提供的Startup Item都在脚本中有一个测试,用于检查是否被设定了一个特殊的作为开关的变量,当此开关关闭时,守候进程不会被自动启动(该开关的设置往往是在“系统偏好设置”的“共享”项目中)。«»要想启用或者禁用一个没有GUI选框的守候进程,你需要在/etc/hostconfig中天骄或者修改对应的变量。2.5. Specifying the Startup Item Properties2.6. Startup Item特性表的说明The configuration property list of a startup item provides descriptive information about the startup item,
lists the services it provides, and lists its dependencies on other services. MacOS X uses the service and
dependency information to determine the launch order for startup items. This property list is stored
in ASCII format (as opposed to XML) and can be created using the Property List Editor application.«»一个Startup Item的特性表描述了该Startup Item的信息,列举了其提供的服务,也列举了其对其他服务的依赖。Mac OS X根据这些服务和依赖来决定Startup Item的启动顺序。该特性表使用ASCII编码存储(这一点和XML完全不同),其可以用Property List Editor这个程序来创建。Note: In Mac OS X v10.4 and later, the dependency information for many stubbed-out
system startup items is still present in case other startup items depend on it.«»注意:在Mac OS X v10.4既以后版本中,因为其他的Startup Item对其的依赖,许多不再被使用的Starup Item仍然存在。Table 1 lists the key-value pairs you can include in your startup item’s file. Each
of the listed arrays contains string values. You can use the Property List Editor application that comes
with the Xcode Tools to create this property list. When saving your property-list file, be sure to save it as
an ASCII property-list file.«» 表 1 罗列了你的Startup Item的中可以用到的 键-值 对。每一个array都包含了多个string类型的值。你可以使用Xcode附带的Property List Editor程序来创建这个特性表。保存你的特性表的时候,注意将其保存成ASCII property-list文件。Table 1 key-value pairs«»表1 中的 键-值
KeyTypeDescriptionStringProvidesArrayRequiresArrayUsesArrayvalueA short description of the startup item, used by
administrative names of the services provided by this startup item.
Although a startup item can potentially provide multiple
services, it is recommended that you limit your startup
items to only one service services provided by other startup items that must
be running before this startup item can be started. If the
required services are not available, this startup item is
not services provided by other startup items that should
be started before this startup item, but which are not
required. The startup item should be able to start
without the availability of these services.类型值«»键«»DescriptionString对Startup Item的简短的描述,用于系统管理工具。该Startup Item提供的服务的名字。尽管一个Startup Item可以«»ProvidesArray提供多个服务,但还是建议你每个Startup Item只用于提供一个服务。描述了那些必须在该Startup Item启动前启动的Startup Item提«»RequiresArray供的服务(译者注,即前文所指的该服务依赖的那些服务)。如果那些依赖的服务不可用,则该Startup Item不会运行。描述了那些应该在该Startup Item启动前启动的Startup Item提«»UsesArray供的服务,但这些服务并不是必须启动。那些服务是否可用对该Startup Item的运行并无影响。For example, here is an old-style plist:«»下面是一个老形式的plist的例子:{
Description = "Software Update service";
Provides = ("SoftwareUpdateServer");
Requires = ("Network");
Uses = ("Network");
OrderPreference = "Late";
Messages =
{
start = "Starting Software Update service";
stop = "Stopping Software Update service";
};}And here is an XML plist example:下面是一个XML形式的plist的例子:
The service names you specify in the Requires and Uses arrays may not always correspond directly to
the name of the startup item that provides that service. The Provides property specifies the actual name
of the service provided by a startup item, and while this name usually matches the name of the startup
item, it is not required to do so. For example, if the startup item launches multiple services, only one of
those services can have the same name as the startup item.«»在Requires和Users中指定的服务不一定要和提供该服务的Startup Item名称相一致。Provides属性指定了Startup Item提供的服务的真实名字,往往这个名字与Startup Item的名字相匹配,不过这也不是必须的。例如,如果Startup Item启动了多个服务,只会有一个服务的名字可以和该Startup Item名字相一致。If two startup items provide a service with the same name, the system runs only the first startup item it
finds with that name. This is one of the reasons why your own startup items should launch only one
service. If the name of only one of the services matches the name of another service, the entire startup
item might not be executed and neither service would be launched.«»如果两个Startup Item提供的服务的名字一样,系统只会运行它找到的一个该名字的服务。这是为什么你的Startup Item应该只启动一个服务的原因之一。如果你的Startup Item启动的唯一一个服务的名字和其他服务的名字一样,则该Startup Item就不会被启动,其包含的服务也不会被运行。The values of the Requires and Uses keys do not guarantee a particular launch order.«»Requires和Uses键没有启动顺序之分。In Mac OS X v10.4 and later, most low-level services are started with launchd. By the time your startup
item starts executing, launchd is running, and any attempt to access any of the services provided by a
launchd daemon will result in that daemon starting. Thus, you can safely assume (or at least pretend)
that any of these services are running by the time your startup item is called.«»在Mac OS X v10.4及以后的版本中,大多数底层的服务使用launchd 启动。当你的Startup Item开始运行,或者launchd在运行,或者任何尝试访问launchd守候进程提供的服务都会导致守候进程的开始。因此,你可以安全的认为(至少可以假设)当你的Startup Item被调用的时候,其提供的服务就会运行。
For this reason, with few exceptions, the Requires and Uses keys are largely irrelevant after Mac OS X
v10.3 except to support service dependencies between two or more third-party startup items.«»因为这个原因,只在很少情况下,Requires和Users键在Mac OS X v10.3以后的版本中被使用都是很不合适的,除非Startup Item提供的服务依赖于两个或更多第三方Startup Item。2.7. Managing Startup Items2.8. 管理Startup ItemDuring the boot process, the system launches the available startup items, passing a start argument to
the startup item executable. After the boot process, the system may run the startup item executable
again, this time passing it a restart or stop argument. Your startup item executable should check the
supplied argument and act accordingly to start, restart, or stop the corresponding services.«»在启动过程中,系统启动可用的Startup Item,将start参数传递给Startup Item的可执行程序。在启动之后,系统会再次运行Startup Item的可执行程序,这次将传递restart参数或者stop参数。你的可执行程序应该可以支持start,restart,stop这三个参数,并将其与你的服务的行为对应。Note: In general, with the exception of daemons provided with Mac OS X, the system will
only run your startup script with start or stop arguments (at boot and shutdown,
respectively). Users, however, may elect to use the restart should not make any assumptions about the order in which daemons will be shut down.«»注意:一般情况下,除了Mac OS X提供的守候进程,系统应该只会给你的Startup Item的执行程序传递start和stop参数(分别在系统启动和关闭时)。当然,用户可以手动的使用restart参数。«»你不必考虑守候进程被关闭的顺序。If you want to start, restart, or stop startup items from your own scripts, you can do so using the
SystemStarter program. To use SystemStarter, you must execute it with two parameters: the desired
action and the name of the service provided by the startup item. For example, to restart the Apache
Web server, you would execute the following command:«»如果你想使用你自己的脚本start,restart,stop你的Startup Item,你可以使用SystemStarter程序。要使用SystemStarter,你必须给他传递两个参数:需要执行的动作和Startup Item提供的服务。例如,要想重启Apache
web服务,你需要使用下面的命令:/sbin/SystemStarter restart "Web Server"Important: You must have root authority to start, restart, or stop startup items.重要信息:要想start,restart,stop一个Startup Item,你必须使用root帐户。Startup items should always respect the arguments passed in by SystemStarter. However, the response
to those arguments is dependent on the startup item. The stop and restart options may not make sense
in all cases. Your startup item could also support the restart option using the existing code for stopping
and starting its service.«»Startup Item应该始终重视由SystemStarter传递过来的变量。而针对这些变量的回应还由Startup Item决定。stop和restart选项并不一定是有意义的,你的Startup Item可以使用停止和启动服务的代码来实现restart选项。
2.9. Displaying and Localizing a Startup Message2.10. 显示及记录Startup Item的信息When your startup item starts at boot time, you may (if desired) display a message to the user. To do
this, use the ConsoleMessage command. (You can use this command even if the computer is not starting
up, but the user will not see it unless the Console application is running.)Startup Item在系统启动过程中启动的时候,你可以使用ConsoleMessage命令来显示信息。(你甚至可以在系统未完全启动的时候使用这个命令,用户可以使用控制台程序来查看信息。)For example:例如:ConsoleMessage "MyDaemon is running. Better go catch it."If you want to localize the message displayed when a startup item starts, you must create a series of
property list files with localized versions of the strings. Each of these files must be named
s, and must be in a localized project directory whose name is based on the name of a
language or locale code for the desired language. These folders, in turn, must be in a folder called
Resources in the startup item folder.«»如果你想把Startup Item运行时显示的信息记录下来,你必需创建一个包含了本地化信息的特性表文件。每个这样的文件都必须命名为s,而且必须放在一个本地化项目目录中,其目录名为语言名或者相应编码名。而这些目录,必须放在Startup Item目录中的一个叫Resources的文件夹中。For example, you might create a tree structure that looks like this:例如,你可以创建的Startup Item目录可能是这种结构:MyDaemon
|
|- MyDaemon
|-
|- Resources
|
|-
|-
|-
|- zh_ithin each of these localizable strings files, you must include a dictionary whose keys map an English
string to a string in another language. For example, the French version of the PrintingServices
localization file looks like this:
«»在每个本地化文件中,都包含了一个字典,该字典的键名是英文字符串,而值是用其他语言描述的字符串。例如,法语版本的PrintingServices的本地化文件是这个样子的:
"/DTDs/">
Whenever the ConsoleMessage command is passed the string “Starting printing services”, if the user’s
language preference is French, the user will instead see “Démarrage des services d’impression” at
startup. C’est très bien!无论何时,都会将“Starting printing services“传递给ConsoleMessage命令,如果用户的语言设置是法语,用户会更愿意在启动的时候看到“Démarrage des services d’impression“。C’est très bien!(译者注,That's great!)The value of the key field must precisely match the english string printed by your startup item using
字段的字符串必须用英语清晰的表达你想让Startup Item通过ConsoleMessage打印的信息。See the manual page for locale for more information about locale codes.查看locale 的man手册以获得更多关于locale code信息。2.11. Startup Item Permissions2.12. Startup Item的权限Because startup items run with root authority, you must make sure your startup item directory
permissions are set correctly. For security reasons, your startup item directory should be owned by root,
the group should be set to wheel, and the permissions for the directory should be 755 (rwxr-xr-x). This
means that only the root user can modify the directory contents; other users can examine the directory
view its contents but not modify them. The files inside the directory should have similar permissions and
ownership. Thus, the file listing for the Apache startup item directory is as follows:因为Startup Item运行于root权限,你必须确定你的Startup Item目录的权限是正确的。因为安全原因,你的Startup Item目录的拥有者应该是root,用户组应该是wheel,目录权限应该是755(rwxr-xr-x)。这就意味着只有root用户可以更改目录内容,而其他用户可以查看目录的内容但不能更改。目录中的文件应该具有相同的权限和拥有者关系。因此Apache的Startup Item目录内的权限是这样的:./Apache:total 16
drwxr-xr-x 4 root wheel 136 Feb 14 14:33 .drwxr-xr-x 21 root wheel 714 Feb 14 15:03 ..-rwxr-xr-x 1 root wheel 1253 Feb 10 19:31 Apache-rw-r--r-- 1 root wheel 152 Feb 10 19:31 mportant: In Mac OS X version 10.4 and later, the system asks the user what
to do about startup items with incorrect permissions. At this point, the user
may choose to disable the startup item, which could have unexpected results
for your software. To avoid this, be sure to set the permissions during
installation.«»重要信息:Mac OS X 10.4及以后版本的系统中,当Startup Item的权限不正确时,系统会询问用户该怎么办。此时,用户可能会选择将该Startup Item禁用掉,这样就会让你的软件产生不可意料的错误。为了避免这个情况,请在安装时正确设置权限。●1. Logging Errors and Warnings●2. 登录错误和警告•2.1. Log Levels and Log Files•2.2. 日志级别和日志文件•2.3. Logging Errors Using the syslog API•2.4. 使用syslog API记录错误日志•2.5. Logging Errors Using the asl API•2.6. 使用asl API记录错误日志1. Logging Errors and Warnings2. 登录错误和警告You can use two major APIs in Mac OS X to log errors: syslog and asl. In addition, you can use a number
of higher-level APIs built on top of these such as NSLog. However, because most daemons are written in
C, you probably want to use the low-level APIs when writing code that executes at startup.«»在Mac OS X中,你可以使用两个主要的API来记录错误日志:syslog 和asl。你也可以使用很多基于这两个API的更高级的API,例如NSLog。然而,因为大多数的守候进程都是用C编写的,所以你可能更希望使用低级的API来编程,以在系统启动时使用。The syslog API is the most commonly used logging API on UNIX and Linux systems. For this reason, you
should consider using it when writing cross-platform software. For software specific to Mac OS X, you
should use the asl API because it provides more functionality.«»syslog API在UNIX和Linux系统中被广泛的使用。因此,你如果要开发跨平台程序,最好使用它。而对于Mac OS X专有的程序,你可以使用asl API,因为它可以提供更多的功能。
If your daemon uses standard output or standard error to notify users of problems during startup, those
error messages are not generally visible to a user. You can, of course, boot in verbose mode (by holding
down Command-v at startup), but you may have a hard time reading the errors as they scroll by. To solve
this problem, you should use system logging to record error conditions for later analysis by the user or
system administrator.如果你的守候进程使用标准输出和标准错误来通知用户启动错误信息,这些错误信息一般是不会被用户看到的。当然,你可以让系统用verbose模式(系统启动的时候按住CMD+V),不过由于屏幕滚动很快,你可能很难看清楚具体信息。要想解决这个问题,你需要使用系统日志来记录错误信息,让用户或者系统管理员来对其分析。2.1. Log Levels and Log Files2.2. 日志级别和日志文件In Mac OS X (and other UNIX-based and UNIX-like operating systems), the system logger supports
logging at a number of priority levels. The priority levels (and suggested uses for these levels) are:在Mac OS X(以及其他UNIX或类UNIX系统)下,系统日志会被以多个优先级别记录。这些优先级是(推荐使用的优先级):••••••••••••••••Emergency (level 0): The highest priority, usually reserved for catastrophic failures and reboot
(level 1): A serious failure in a key al (level 2): A failure in a key (level 3): Something has g (level 4): Something is amiss and might fail if not (level 5): Things of moderate interest to the user or (level 6): The lowest priority that you would normally log, and purely informational in (level 7): The lowest priority, and normally not logged except for messages from the
ncy(level 0):最高优先级,通常为灾难性的错误或者重新启动通知所预留。Alert(level 1):需要认真对待的系统错误。Critical(level 2):系统错误。Error (level 3):错误。Warning (level 4):一些不正常现象,如果不及时处理可能会引发某种功能失败。Notice (level 5):一些可能会使用户或者系统管理员感兴趣的比较缓和的错误。Info (level 6):最低级别的普通日志,纯粹是一些信息。Debug (level 7):最低级别,如果不是来自内核的信息,甚至都不会被记录。The system logger in Mac OS X determines where to log messages at any given priority level based on
the file /etc/./etc/文件中的配置设定了Mac OS X将会在何处保存日志文件,以及日志文件的优先级。Note: A daemon or application may mask low-priority messages before they even get to the
system logger using the setlogmask function call. Thus, if you want to see these debugging
messages in the system log, you may have to pass certain debugging flags to the daemon,
regardless of how you have configured the system logger in /etc/.
注意:一个守候进程或者应用程序调用setlogmask 函数的时候,可以掩盖之前的低优先级的信息。因此,如果你想在系统日志中查看debug信息,你必须向守候进程发送某个确定的debug标记,不论你曾经在/etc/文件中做过任何配置。2.3. Logging Errors Using the syslog API2.4. 使用syslog API记录错误日志The syslog API is relatively straightforward. It consists of five main functions:syslog API相对比较简单,它包含了五个主要的函数:void syslog(int priority, const char *message, ...);void vsyslog(int priority, const char *message,
va_list args);void openlog(const char *ident, int logopt, int facility);void closelog(void);int setlogmask(int maskpri);The first function you should call is openlog. This function associates future calls to syslog with a
particular facility. You can find a list of facilities in the man page for syslog.第一个函数是openlog。这个函数通过一个特殊的设备调用syslog。你可以通过查看syslog 的man手册来了解都有那些设备。Note: Technically, you can call syslog without calling openlog, but as a rule, you should
always call openlog to specify a facility and logging options. If you do not call openlog
before you call syslog, the API will use the default facility:LOG_USER.注意:技术上,你可以不通过openlog来调用syslog,但是,作为一条原则,你必须调用openlog来指定设备和日志选项。如果你在调用syslog前没有调用openlog,API会自动选择使用默认的设备,LOG_USER。Next, you should call syslog. This function actually logs your message at a specified priority level. The
priority levels for log messages are LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR, LOG_WARNING,
LOG_NOTICE, LOG_INFO, or LOG_DEBUG, in decreasing order of importance. These correspond with the
levels described in “Log Levels and Log Files.”然后,你需要调用syslog。这个函数会自动以指定的优先级记录你的日志。这些优先级为(以优先级的重要性排序):LOG_EMERG,LOG_ALERT,LOG_CRIT,LOG_ERR,LOG_WARNING,LOG_NOTICE,LOG_INFO,LOG_DEBUG。这些优先级在“Log Levels and Log File“中有描述。Warning: It is very important to choose an appropriate priority level for log messages. The
system logger discards most low-priority messages, depending on the facility specified. To
find out how the system logger decides which facilities and priority levels to log in a given
log file, look in the file /etc/.警告:为日志信息选择一个合适的优先级是非常重要的。系统会根据设备的要求放弃大多数低级别的消息。要想找出系统对一个日志的设备和优先级如何定义,请查看/etc/文件。
If you need to write a wrapper function for the syslog function, you should use the function vsyslog
instead. This function is identical to syslog except that it takes a variable argument list parameter
instead of a series of individual parameters.如果你想对syslog函数进行封装,你需要使用vsyslog函数来取代syslog。这个函数和syslog函数是一样的,不同点在于,vsyslog函数的参量是一个包含了变量的list,取代syslog函数的一系列独立参数。Finally, when your program exits (or when you need to specify a different facility), you should call
closelog. This function resets the facility and logging options to the default settings as though you had
never called openlog.最后,当你的程序退出(或者你想换一个设备),你需要调用closelog函数。这个函数将设备和日志选项重置为默认值,就像从来没有调用过openlog一样。The following code example shows how to log a simple error message:以下的代码展示了如何记录一个错误消息的日志:#include
main(){
int cause_an_error = open("/fictitious_file", O_RDONLY, 0); // sets errno to ENOENT
openlog("LogIt", (LOG_CONS|LOG_PERROR|LOG_PID), LOG_DAEMON);
syslog(LOG_EMERG, "This is a silly test: Error %m: %d", 42);
closelog();}The flags passed to openlog specify the following: «»以下是关于传递给openlog的标签的描述:••••••LOG_CONS: If the syslogd daemon is not running, the syslog function should print the message
to the _PERROR: in addition to normal logging, the syslog function should also print the message to
standard _PID: The syslog function should append the process ID after the process name at the
beginning of the log _CONS:如果syslog守候进程不在运行,syslog函数将向控制台输出此消息。LOG_PERROR:除标准日志以外,syslog函数还会向标准错误输出此消息。LOG_PID:syslog函数会在日志消息的开始处,进程名的后面添加进程的ID(译者注:PID)。These and other flags are described in more detail in the syslog manual page.查看syslog 的man手册可以获得更多以上标记及更多标记的详细信息。
In addition to the usual printf format flags, this command supports an additional flag, %m. If this flag
appears in the log string, it is replaced by a string representation of the last error stored in errno. This is
equivalent to what would be reported if you called perror or strerror directly.除了一般的printf格式的标记,该命令还支持一个标记:%m。如果这个标记在日志中出现,这表示将该日志信息记录为errno中的最后一个。等同于直接调用perror 和strerror。(译者注,其实就是给拥有这个标记的日志信息打上编号,具体可以点击上面的连接“perror”)Thus, the code sample above prints the following message to standard output:因此,下面的代码演示了将消息输出给标准输出:LogIt[165]: This is a silly test: Error No such file or directory: 42Then, the code sample tells the system logger to log that message. As a result, assuming you have not
changed /etc/, the system logger broadcasts this message to all users:示例代码通知系统将消息计入日志。如果你没有改动过/etc/,则系统将这条日志通知给所有用户:Broadcast Message from user@
(no tty) at 13:Jul 24 13:28:46 My-Machine-Name LogIt[601]: This is a silly test: Error No such file or directory: 42In this example, the process ID was 601, and the process name was LogIt.在这个例子中,进程的ID为601,进程名字为“LogIt”。For additional control over what gets logged, you can use the function setlogmask to quickly enable or
disable logging at various levels. For example, the following code disables logging of any messages
below the LOG_EMERG level (which is one higher than the LOG_ALERT level):你也可以使用setlogmask函数控制是否记录日志。下面的代码就是演示如何禁止所有LOG_EMERG级别以下的日志(即LOG_ALERT及以下级别都屏蔽):setlogmask(LOG_UPTO(LOG_ALERT));You might, for example, use this function to disable logging of debug messages without recompiling your
code or adding conditional statements.你也可以利用该函数在不重新编译代码或者在代码中添加标记的情况下禁用debug模式的消息。2.5. Logging Errors Using the asl API2.6. 使用asl API记录错误日志The asl API is short for Apple System Logger. The Apple System Logger API is very similar to syslog but
provides additional 是Apple System Logger的缩写。Apple System Logger API和syslog有些相似但是提供了更丰富的功能。There are a few key differences, though; the asl logging API:这里是一些不同点。asl API:
••••••Uses a text string for the facility identifier for more precise filtering of log messagesProvides functions for querying the log filesIs safe for use in a multithreaded environment because it provides functions for obtaining a
separate communication handle for each thread使用字符串标记设备以更好的处理日志信息。提供了查找日志文件的函数。多线程安全,提供了使线程通讯隔离的函数。The following sample code is equivalent to the code in “Logging Errors Using the syslog API,” except that
it uses asl for logging:下面的代码与 “ Logging Errors Using the syslog API,” 中的作用相同,只不过其使用了asl 来记录日志。#include
main(){
aslclient log_client;
int cause_an_error = open("/fictitious_file", O_RDONLY, 0);
log_client = asl_open("LogIt", "The LogIt Facility", ASL_OPT_STDERR);
asl_log(log_client, NULL, ASL_LEVEL_EMERG, "This is a silly test: Error %m: %d", 42);
asl_close(log_client);}A complete explanation of the additional features of the asl API is beyond the scope of this document.
For more information, see the asl manual page.关于asl API的更详细的介绍超出了本文的讨论范围。更多信息请查看asl 的man手册。●
Customizing Login and Logout●6. 订制登录和注销•6.1. Login Items•6.2. 登录项•6.2.1. Adding Login Items with Shared File Lists•6.2.2. 使用Shared File Lists添加登录项•6.2.3. Adding Login Items with Apple Events•6.2.4. 使用Apple Events添加登录项•6.2.5. Adding Login Items with CFPreferences•6.2.6. 使用CFPreferences添加登录项•6.2.7. Adding Login Items Manually•6.2.8. 手动添加登录项
••6.3. Loginwindow Scripts6.4. Loginwindow脚本••••••••6.4.1. Installing Scripts Using Defaults6.4.2. 使用Defaults安装脚本6.4.3. Installing Scripts Using Loginwindow Hooks6.4.4. 使用Loginwindow钩子(hook)安装脚本6.5. Bootstrap Daemons6.6. Bootstrap守候进程6.7. Launchd User Agents6.8. 启动用户代理程序1. Customizing Login and Logout2. 订制登录和注销If you want to run custom scripts or applications when the user logs in, there are several ways to do it.
You might use this feature to perform maintenance tasks or set up the operating environment for your
own applications when the user first logs in.有很多方法可以在登录的时候运行用户自订的脚本或者应用程序。你可以使用此方法设定维护任务,或者在用户第一次登录的时候为你的应用程序配置运行环境。2.1. Login Items2.2. 登录项To launch an application each time the user logs in, use the Login items found in the Accounts system
preference. Login items are appropriate for user-level applications, as opposed to applications that
operate on behalf of the system. When you configure an application to be launched as a login item, you
must remember that the user can disable the launching of your application via the Accounts system
preference. Dependent applications must be able to respond appropriately if they detect the login-item
application is not running.要想在每次用户登录的时候启动某个应用程序,可以使用系统预置中帐户设置中的登录项标签。登录项适合于那些用户层的应用程序,而那些系统级别的程序在这里不可用。一旦你将一个程序作为启动项启动,你必须认识到用户可以通过更改用户预置中的设置来取消这个程序的启动。所以依赖于此的相关程序必须能够察觉到登录项中的程序没有启动,并对此做出相应反应。Note: Beginning with Mac OS X v10.5, the recommended method for adding a login item
programmatically is with the Shared File Lists API. If your application needs to be compatible
with earlier versions of Mac OS X, you should instead add login items with Apple Events.
The two additional methods listed here are deprecated and may cease to function with
future updates to Mac OS X.注意:从Mac OS X v10.5开始,推荐的以编程方法向登录项添加项目的方法是使用Shared File Lists
API。如果你的应用程序需要兼容更早版本的Mac OS X,可以使用Apple Events方法来添加登录项。这里列出的另外两个方法是不被推荐的,因为他们可能因Mac OS X的升级而产生问题。
2.2.1. Adding Login Items with Shared File Lists2.2.2. 使用Shared File Lists添加登录项Available in Mac OS X v10.5 and later, the Shared File Lists API can be found in LSSharedFileList.h in
/System/Library/Frameworks/ork/Frameworks/ork/Headers/.v10.5及以后版本的Mac OS X中,在/System/Library/Frameworks/ork/Frameworks/ork/Headers/中的LSSharedFileList.h中找到Shared File Lists API。2.2.3. Adding Login Items with Apple Events2.2.4. 使用Apple Events添加登录项You can easily manipulate the list of login items for the currently logged-in user using Apple events. This
technique is described in the sample code LoginItemsAE.你可以使用Apple Events方便的为当前登录的用户更改登录项列表。关于此方法的详细描述参见LoginItemsAE 中的代码样例。2.2.5. Adding Login Items with CFPreferences2.2.6. 使用CFPreferences添加登录项Another technique for working with property lists is through the CFPreferences API in Core Foundation.
Like the Apple Events technique, this only works for the current user. Unlike the Apple Events technique,
however, that user does not need to be logged in on the console. Thus, this technique can be used to
modify preferences for a different user by running this piece of code as that user using a setuid
Foundation中的CFPreferences API是又一个操作特性表的技术。和Apple Events技术一样,它的工作只能针对当前用户。而与Apple Events不同的是,用户不需要在控制台中登录。所以,这项技术可以通过运行setuid权限(译者注,让执行该程序的用户拥有文件属主的权限)的代码修为另一个用户修改预置。The following code snippet shows the basics:下面这段代码片段展示了基本操作:CFArrayRef prefCFArrayRef =
CFPreferencesCopyAppValue(CFSTR("AutoLaunchedApplicationDictionary"), CFSTR("loginwindow"));CFMutableArrayRef tCFMutableArrayRef = CFArrayCreateMutableCopy(NULL, 0, prefCFArrayRef);/* Modify tCFMutableArrayRef here */CFPreferencesSetAppValue(CFSTR("AutoLaunchedApplicationDictionary"), tCFMutableArrayRef,
CFSTR("loginwindow"));For a more complete example, see the CFPreferences sample code. For additional documentation about
the API itself, see Core Foundation Framework Reference.查看CFPreferences 可以看到上面代码片段的完整版本。查看Core Foundation Framework Reference 可以获得此API的详细文档。
2.2.7. Adding Login Items Manually2.2.8. 手动添加登录项If you need to add applications manually to your list of Login items, you can modify the
~/Library/Preferences/ property-list file of the desired user using the Property List
Editor. Inside this file, add the desired application to the array of applications listed under the
AutoLaunchedApplicationDictionary key.«»如果想手动将应用程序添加至启动项列表,你可以使用Property List Editor工具修改~/Library/Preferences/文件来实现。在这个文件中,将应用程序加入到AutoLaunchedApplicationDictionary键下的应用程序列中。For example:例如:
"/DTDs/">
the default (for example, by adding a login item using System Preferences).注意:默认情况下这个文件是不存在的。只有在你修改了默认值后才会被创建(例如,通过系统预置加入一个预置项)。
2.3. Loginwindow Scripts2.4. Loginwindow脚本Another way to run applications at login time is to launch them using a custom shell script. Mac OS X
provides two options for launching scripts when the user logs in. When creating your script file, keep the
following in mind:还有一种方法是在登录时运行制定的shell脚本来启动应用程序。在用户登录时,Mac OS X提供两个选项来启动应用程序。当你创建这个脚本的时候,请遵从以下几条:••••••••The permissions for your script file should include execute privileges for the appropriate s launched by loginwindow are run as root. Therefore, you should thoroughly test your
scripts before deploying them to make sure they do not adversely affect the user's your script, the variable $1 returns the short name of the user who is logging login actions wait until your hook finishes executing. Therefore, have your script do what it
needs to do quickly and then exit.相应的用户应该具有对该脚本的可执行权限。脚本以root层被loginwindow启动。所以该脚本应该进行严格的测试,以保证在运行时不会把用户的系统搞坏。在脚本中,$1返回正在登录的用户的短名称。其他的在登录时应进行的操作会在你的钩子(hook)运行完毕后运行,所以你的脚本的运行应该尽可能缩短时间并尽快结束。Warning: Only one of these hooks can be installed at a time. For this reason, login scripts
are not recommended for deployment. This information is provided as an aid to system
administrators and should not be deployed in released software.重要提示:同一个时间里只能有一个钩子(hook)被装载。因此,登录脚本必须避免依赖。此信息对系统管理员和软件的部署很有用处。2.4.1. Installing Scripts Using Defaults2.4.2. 使用Defaults安装脚本In Mac OS X v10.3 and later, you can use the defaults tool to install your login script. This is the
preferred technique for installing a login script.在Mac OS X v10.3以及以后版本的系统中,你可以使用defaults 工具来安装你的登录脚本。这是安装登录脚本的最好方法。Create the script file and put it in a directory that is accessible to all users. In Terminal, use the following
command to install the script (where /path/to/script is the full path to your script file):创建脚本文件并将其放入到一个能被所有用户访问的目录里,在终端下,使用以下命令来安装该脚本(/path/to/script表示脚本文件的完整路径)。sudo defaults write indow LoginHook /path/to/scriptTo remove this hook, you simply delete the property as follows:要想去除该钩子(hook),你只需要删除这个特性表:sudo defaults delete indow LoginHook
When using the sudo command, you must be an administrator of the current system. When you run the
preceding command, sudo prompts you to enter your password. You must provide a valid password
before the hook can be installed.要想使用sudo命令,你必须是当前系统的管理员。在这条命令运行之前,sudo会要求你输入密码,你必须在钩子(hook)运行之前输入正确的密码。Note: If no plist file exists for indow, this method will not work. This file
(/var/root/Library/Preferences/) does not exist on a fresh
installation until the user changes a login window setting (such as turning on fast user
switching).注意:如果没有一个叫indow的plist文件,这个方法就不能奏效。如果用户没有在安装新的系统后没有修改过“登录选项”(例如“启用快速用户切换“),这个文件(/var/root/Library/Preferences/)就不会存在。If you must install startup scripts programmatically, you should consider providing a copy
of this file containing the default configuration options. Then, if the file does not exist, copy
that default configuration file into place before running defaults. Again, however, this
technique is not recommended for use in applications because these hooks cannot coexist.如果你一定要使用编程方法安装启动脚本,那么你就应该准备好一个该文件的默认设置的拷贝。一旦该文件在系统中不存在,就可以使用defaults工具把这个默认设置的拷贝安装进系统里。当然,这个方法还是不被推荐,因为钩子(hook)不能同时存在多个。2.4.3. Installing Scripts Using Loginwindow Hooks2.4.4. 使用Loginwindow钩子(hook)安装脚本In Mac OS X v10.2 and v10.3, you can run your startup script by modifying the /etc/ttys file. In this file is
the following line:在Mac OS X v10.2和v10.3中,你可以通过修改/etc/ttys文件来运行启动脚本。在这个文件中有这么一行:console "/System/Library/CoreServices//Contents/
MacOS/loginwindow" vt100 on secure onoption="/usr/libexec/getty
std.9600"This line tells the init program to launch loginwindow on the console terminal. Into this line, you can
insert additional parameters for loginwindow to process. Table 1 lists the parameters that are supported
by loginwindow.这一行告诉init程序在控制台终端中启动loginwindow。在这行中,你可以为loginwindow加入运行参数。表格1列举了loginwindow的参数:Table 1 loginwindow parametersParameter-LoginHook-LogoutHookDescription of valueThe full path to a script or tool to run when a user
successfully logs full path to a script or tool to run when a user
successfully logs out.
If “YES,” the Shut Down and Restart buttons in the login
window are disabled; also, pressing the computer’s
power button quits the Finder and Dock applications but
does not turn off the system. This feature prevents users
-PowerOffDisabledfrom casually powering down a system that provides
some shared service, such as a print server or file server.
(This feature can also be controlled from the Accounts
system preference.)表格1 loginwindow的参数«»参数-LoginHook-LogoutHook-PowerOffDisabled参数值描述当用户成功登录时运行的脚本或者程序的完整路径当用户成功注销时运行的脚本或程序的完整路径如果值为“YES”,则登录窗口中的关机和重启按钮不可用;而且,按下计算机的开关键会退出Finder和Dock而不会关闭系统。这个功能就是为了提供某些共享服务(比如打印服务或者文件服务)时不会被误关机(这个功能也可以在帐户预置中设定)。The -LoginHook and -LogoutHook parameters were particularly useful because they permit custom
administrative, accounting, or security programs to run as part of the login and logout procedures. For
example, your modified console definition in /etc/ttys might look similar to the following:-LoginHook和-LogoutHook参数对行政管理,记账,安全程序很有用处,因为他们可以让这些程序作为登录或者注销流程中的一部分运行。例如,你对/etc/ttys中设定console部分的修改可以像这样:console "/System/Library/CoreServices//Contents/
MacOS/loginwindow -PowerOffDisabled YES
-LoginHook /Users/Administrator/Scripts/mailLoginToAdmin"
vt100 on secure onoption="/usr/libexec/getty std.9600"You should avoid using this technique to run your script in Mac OS X v10.4 and later. Instead, run your
script using the defaults tool, as described in “Installing Scripts Using Defaults.”在Mac OS X v10.4及以后版本的系统中,你应该避免使用这个方法去运行你的脚本。你应该使用defaults工具去运行它,就像“Installing Scripts Using Defaults”中描述的那样。2.5. Bootstrap Daemons2.6. Bootstrap守候进程In Mac OS X v10.3, a mechanism similar to launchd was introduced to allow the launching of programs
either at system startup or on a per-user basis. The process involved placing a specially formatted
property list file in either the /etc/mach_init.d or the /etc/mach_init_per_user.d OS X v10.3中,有一种和launchd类似的在系统启动或者用户登录时候运行程序的机制:把一个特殊格式的特性表放入到/ect/mach_init.d或者/etc/mach_init_per_user.d目录下。Important: The use of bootstrap daemons is deprecated and should be avoided entirely.
Launching of daemons through this process is currently limited to some Apple-specific
programs and may be removed or eliminated in a future release of Mac OS X. If you need to
launch daemons, use launchd. If you need to launch daemons on versions of Mac OSX prior
to 10.4, use a startup item.重要提示:不推荐使用bootstrap守候进程,甚至我们应该避免使用它。使用该进程启动守候进程受到一些苹果程序的限制,而且这个方法在将来的版本更新中受到更多限制,甚至不再支持该方法。如果你想启动守候进程,就使用launchd。如果你想在10.4之前的系统上启动守候进程,就使用Startup Item。2.7. Launchd User Agents2.8. 启动用户代理程序In Mac OS X v10.4, launchd was added. This is the preferred means of adding background agents on a
per-user basis. These are described in more detail in “The launchd Startup Process.”在Mac OS X v10.4中加入了launchd机制,该机制被推荐用来添加用户的后台代理程序。查看“The launchd
Startup Process”本文档由杨小邪搜集整理。^_^
发布者:admin,转转请注明出处:http://www.yc00.com/web/1708726977a1582429.html
评论列表(0条)