Mac服务管理-Launchd(转)

背景:

在Mac下没有像Linux那样有很多的关于init方面的工具,从init的发展历史https://en.wikipedia.org/wiki/Init上可以知道,Mac使用的是Launchd作为init管理工具,对应的命令工具为launchctl。

如果在Linux下创建一个自启动服务可以使用Upstart、Systemd、Sysvinit,其中最简单和最古老的方式应该是Sysvinit,毕竟其支持Shell脚本,非常方便。而在Mac下,与Linux的做法不太一样,采用Launchd进行管理,其设置服务采用了plist文件进行对服务来描述,并通过配置好后放在/System/Library/LaunchDaemons或者/Library/LaunchDaemons,最后通过launchctl命令行使其生效,期间也可以直接通过launchctl来对服务进行操作,比如启动、停止等。

详细的plist编写规范及介绍,参考:https://en.wikipedia.org/wiki/Launchd

以下是关于Launchd的详细解释:

Launchd是什么?

Mac OS X从10.4开始,采用Launchd来管理整个作业系统的Services及Processes 。传统的UNIX会使用/etc/rc.*或其他的机制来管理开机时要启动的Startup Services,而现在的Mac OS X使用launchd来管理,它的Startup Service叫做Launch Daemon和Launch Agents 。而视为Service的程序,就该是Background Process,不应该提供GUI,也不应该跳到(Console的)Foreground 。当然有些例外,例如听快速键之后跳出视窗的程序。

Launchd管理的Background Process有四种:

  1. Launch Daemon:在开机时加载(Load)。
  2. Launch Agent:在使用者登录时加载。
  3. XPC Service:好像是10.7才有的。
  4. Login Items:在User登录时执行。有两种方法可以用程序新增项目到Login Item:(Shared File List:会出现在Account偏好设定的Login Item清单。Service Management Framework:这个就不会出现在Login Item清单。)

(以下把重点放在Launch Daemon/Agent 。至于XPC和Login Item先不做解释。)

Launch Daemon & Launch Agent

Launch Daemon和Launch Agent是同一种东西在不同Scopes的异名。Launch Daemon是System-Wide(系统级别)的Service,称为Daemon,Launch Agent是Per-User(用户级别)的Service ,称为Agent,前者在开机时会加载(Load),后者在使用者登录时(才)会加载。

如果你打开Activity Monitor,并切换到Hierarchy View,你会发现有个Launchd会在最上层,跟它同层的只有kernel_task,它下面有很多Child Processes的User都是root,其中还有一个Launchd,启动的User是你自己,它底下的Child Processes的User也几乎都是你自己。当这些Processes是由Launchd加载Launchd Property List File来执行的时候,前者由root执行的称为Launch Daemons,后者由使用者执行的称为Launch Agents 。

Launchd Property List File就是你会在LaunchDaemon或LaunchAgents目录中看到的*.plist档案(以下统称plist档)。它是XML格式。

launchd Service Process Lifecycle

由Launchd所管理的Services(Launch Daemon、Launch Agent)是要先由Launchd加载(load)以后才会执行(run),但加载之后并不一定马上执行。在苹果的官方文件说明了kernel加载完成后会发生的事,用来说明Launch Daemons、Launch Agents及其Processes的生命周期。

开机时,会先加载OS Kernel,加载完成后就执行Launchd,用来加载System-Wide Services(Daemons)。这个System-Wide Launchd在开机时会做这些事:

  1. 加载(load)存放在这些目录下的plist:(/System/Library/LaunchDaemons,/Library/LaunchDaemons)
  2. 注册那些plist里面设定的sockets(port)和file descriptors
  3. 执行(run)KeepAlive = true的Daemons,当然RunAtLoad = true的也会启动。

Run好后,Loginwindow就出现了,提示使用者登录。有设定自动登录的话,就会跳过这关。

在使用者登录以后,会执行属于该使用者的Launchd,负责处理Launch Agent,做的事跟上面加载Launch Daemon很像,差别在于它从以下的目录加载plist:

  • /System/Library/LaunchAgents
  • /Library/LaunchAgents
  • ~/Library/LaunchAgents

由使用者执行的任何程序也都是Launchd来执行的,所以Launchd也是该使用者的所有Processes之母。

在使用者登出、关机或重新开机时,会触发Termination Event。接受登出、关机、重新开机使用者指令的Process是Loginwindow。它会先向使用者确认,一但确认,就会对每个由该使用者的Launchd所启动的Processes送出Termination Signal,如果是Cocoa则送出Cocoa API的Event,其他的就送出SIGTERM要他们自我了断,45秒之后,除了Cocoa的应用程式可以丢出某个Error来取消这整个Termination Process,其他还没结束的都会被kill掉。

这就是为什么Loginwindow这个Process会一直存在,它要负责把该使用者执行起来的Processes统统清掉。而Per-User Services都关掉以后,就回到Loginwindow,或是执行关机、重新开机的流程,后两者就是照着差不多的流程去关掉所有System-Wide Services。

Launchd-Compatible Daemon Programming Guide

以下是该文件中提及关于配合Launchd开发Daemon时应注意的事,提到关于plist的key就请参考man 5 launchd.plist。以下的Daemon指的是Launch Daemon所要运行的Process,所以Launch Agent也一并适用。

Listen to SIGTERM

如上文所提及的,由于Loginwindow这个Process在要关掉你的Daemon时会先送SIGTERM,要你自我了断,等太久没关掉才会SIGKILL。如果你的程式需要在结束之前做什么事,一定要听SIGTERM这个Signal。

On-Demand Daemon

Launch Daemon/Agent默认不会让某个Process一直执行,当它的设定没有KeepAlive = true时,它会根据被执行的Process的CPU Usage和Requests(如TCP/IP Service)来决定要不要送出SIGTERM叫他自尽。

当该Service需要被使用时,而相对应的Program没有跑成Process时,会自动把该Service给跑起来。例如某个TCP/IP Service听某个Port,当这个Port有封包进来时,Launchd会把相对应的Service给启动,这种行为叫做on-demand 。

当然,也有non-on-demand daemon,其实也就是keep-alive daemon,这也是传统意义上的Daemon ,比如一直躲在墙角默默执行,直到有人找他,他才跳出来回一下话,回完了以后又继续躲在墙角。只要把KeepAlive这个key设成true,它就会在plist被Launchd加载(load)时执行(run)起来。要是那个Process死掉,Launchd会知道,马上再把它开起来。所以如果你试着去Activity Monitor砍掉这种Daemon,它就马上会复活。

No fork or exec

传统的System Programming会教你用exec、fork等等的POSIX API来做Daemon,但配合Launchd时,由于Daemon的生命周期是由Launchd来控制的,除非强制要求Kepp-Alive,否则要生要死是Launchd决定,更何况Keep-Alive还要考虑Daemon Process在结束以后自动重新执行,所以在配合Launchd写Daemon时,苹果建议你不要用传统的fork和exec*。当然,plist文件中的ProgramArguments就是exec*系列subroutine的参数。

当一个Process跑起来10秒内就死掉,Launchd会判定为Crash,然后试着重新执行。要是你用传统的fork-exec style,就可能会造成无限循环。

No setuid / setgid / chroot / chdir etc

为了安全性的考虑,苹果强烈建议你不要自己调用setupd、setgid、chroot、chdir等等System Subroutines,而是透过plist文件的设定值来让Launchd帮你完成,参考UserName、GroupName、RootDirectory、WorkingDirectory的keys 。

No pipe redirection hell for fd 0, 1 or 2

在写Log或输出信息时可以设定StandardOutPath、StandardErrorPath,只管输出到stdout或stderr就好了。而StandardInPath也可以让你的Process一执行就从stdin指定path的内容。也就是说,Launchd帮你把fd = 0, 1, 2的东西都传了一遍。

其他应用

定时任务

Launch Daemon/Agent的设置项可以指定该Service的执行周期及执行时间,也就是说,它可以替代传统的at、periodic和cron。这些设定值的key请参考StartInterval和StartCalendarInterval。

搭配LaunchOnlyOnce的话可以模拟at,但如果要用Launchd只临时做一件事,还不如直接at方便。

监视文件或目录异动

Launch Daemon/Agent可以监视某个path的异动,设定在WatchPaths这个key。这里所说的path可以是Directory或是某个特定的文件,只要该path有异动,就会执行你的Job。

也可以用来清Queue,只要Directory里面有东西,就会执行Job直到空为止,可以用来做Mail Server或Notification。设定在QueueDirectories这个key。

参考:

https://en.wikipedia.org/wiki/Init

https://en.wikipedia.org/wiki/Launchd

https://stackoverflow.com/questions/15735320/osx-s-etc-init-d-equivalent

https://nathangrigg.com/2012/07/schedule-jobs-using-launchd#launchctl

https://blog.yorkxin.org/2011/08/04/osx-launch-daemon-agent(以上内容转自此篇博客,由于繁体翻译成简体,有些地方可能语义存在问题)

https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man5/launchd.plist.5.html

https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/launchctl.1.html

https://developer.apple.com/library/content/technotes/tn2083/_index.html

时间: 2024-10-18 14:05:42

Mac服务管理-Launchd(转)的相关文章

Linux/MAC服务管理

(一)端口占用查询 常用命令: lsof netstat 实例: lsof -i:80 netstat -an | grep 80 netstat -an | grep LISTEN 查询本机监听的端口 (二)crontab定时任务 常用命令: crontab 常用选项 crontab -l  查看所有的定时任务 crontab -e 新增编辑定时执行的策略 时间格式 分- 时-日-月-周 task 每分钟执行一次   * * * * * 每五分钟执行一次  */5 * * * * 每天l8:0

linux服务管理

xinetd 超级服务管理 ,常驻在内存,起到中间作用,管理服务,根据客户端的请求,xinted通知相应的服务启动进程 . 基于 xinetd的服务,例如telnet xinetd的自启动方式      chkconfig  telnet on    一般是指下次开启,会自动启动 查看属于xinted的服务   cd /etc/xinetd.d vim /etc/rc.d/rc.local service服务支持源码包安装  ,链接 ln -s /usr/local/apache/bin/apa

安全类工具制作第006篇:服务管理器

一.前言 服务是一种在操作系统启动的时候就会启动的进程.在操作系统启动时会有两种程序随着系统启动,一种是普通的Win32程序,另一种则是驱动程序.正是基于服务的这种特性,恶意程序往往也会将自身伪装成正常的服务来实现自启动.因此在反病毒的过程中,还是很有必要对服务项进行查看并管理的. 服务管理器的开发原理与之前所讨论的注册表管理器和进程管理器是类似的,主要也是枚举服务并将其显示在"List Control"控件中.而对于服务的管理,是通过服务相关的API函数来实现的.有了本系列之前几篇文

linux系统管理之服务管理,ipv6,tcp_wrappers练习

服务管理 ipv6 tcp_wrappers

linux系统管理之服务管理,ipv6,tcp_wrappers

服务管理 1.查看所有unit file单个文件的服务状态 systemctl list-unit-files systemctl list-unit-files --type serbice( 类型筛选) 2.配置yum仓库的小知识点 file:// 本地文件 /mnt 根下面的mnt 3.服务状态 查看状态 systemctl status 服务名字 开启服务 systemctl start 服务名字 关闭服务 systemctl stop 服务名字 下次打开仍然生效 systemctl e

进程管理、服务管理、远程

1.什么是进程 进程就是系统正在做的事情 2.进程状态 运行 休眠 停止 继续 结束 僵尸进程 3.图形中如何查看进程 gnome-system-monitor 4.如何用命令查看进程 ps      进程查看工具 -a  shell中运行的进程 -x  不在shell重运行的进程 -u  查看进程用户 -l  显示进程的详细信息 -f  完全信息full的缩写 -e  显示系统中的所有进程 ps  -aux    |grep   进程关键字 ps ax   -o%cpu,%mem,user,p

服务管理/磁盘引导区恢复 笔记

Linux运行级别: 单人模式:提供系统维护.找回root密码: 纯文字的多人网络模式: 图形界面模式: ? 系统服务:提供某些常驻性功能的运行程式.这些程式运行时常驻在内存.服务名称后都有一个d字母. 独立服务和非独立服务? 独立服务:服务是独立启动的,并常驻于内存,运行速度快. 非独立服务:xinted管理程序提供的socket或port对应的管理.它会根据用户要求启动相应的服务程序,请求结束就会关闭此程序. ? 早期的服务启动: SysV的init脚本程序管理特点. 所有服务的启动脚本都在

Windows Server 2012的服务管理自动化 -启动类型设置,手动启动还是自动启动

Windows Server 2012的服务管理自动化 标签:Windows 服务器 IDC机房 Windows Server 2012 一.场景描述: 运行着关键业务的windows服务器或托管在IDC机房,或宿主在自家公司的机房(DC),无论哪一种服务器管理方式,都会面临这样的情境:当运行的关键业务的服务停掉后,即使离数据中心很近,也无法及时处理,更何况出差在外或是旅行当中呢?! 基于以上,那,有没有一种方式可以自动化的管理服务呢,当服务当掉后,可以自动的无人工参于的情况下第一时间侦测到服务

[Linux]服务管理:rpm包, 源码包

--------------------------------------------------------------------------------------------------- |--- 1. 独立的服务  |---- rpm包默认安装的服务 |--- 2. 基于xinetd服务 linux服务分类: | |---- 源码包安装的服务 查询已安装的服务: rpm包安装的服务:chkconfig --list( 查看服务自启动状态,可以看到所有rpm包安装的服务 ) ( 7个