背景:

在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

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

  1. linux的服务管理(centos6和Centos7)和网络管理(网卡配置),计划服务cron

    服务和网络 管理 init  ifcfg ens33 1.服务: Linux系统中提供的功能,统称为服务,如:at服务.cron服务.web服务.FTP服务.sshd服务等. 服务是由已经在运行的进程 ...

  2. 第11章 Linux服务管理

    1. 服务分类 (1)Linux的服务 ①Linux中绝大多数的服务都是独立的,直接运行于内存中.当用户访问时,该服务直接响应用户,其好处是服务访问响应速度快.但不利之处是系统中服务越多,消耗的资源越 ...

  3. CentOS 7 (RHEL 7)服务管理命令的变化

    CentOS 7 (RHEL 7)带来了新的服务管理命令,为了保持兼容原有的命令仍可以使用,以下是新旧命令的对照. 启动.停止.重启.重载.检查服务:6: service httpd start|st ...

  4. PC管理端与评委云打分配合步骤及疑难问题汇编,即如何使用PC管理端的云服务管理功能

    一.前期环境及数据准备 A.PC管理端主要流程 1.进入菜单 编辑/选项/服务器 界面,如下图所示,采用我官方所提供的云服务,不采用自己假设的AppWeb服务. 切记:AppWeb服务和云服务只能二选 ...

  5. Ubuntu 和 Redhat / Fedora 服务管理命令对比表(附Fedora16新的服务管理工具systemctl )

    以 apache/httpd 服务作为例子 任务 Red Hat / Fedora Ubuntu Ubuntu (with sysv-rc-conf or sysvconfig) 立即启动/停止某服务 ...

  6. Centos6.5 设置Tomcat8 service服务实现自启动和服务管理

    Centos6.5 设置Tomcat8 service服务实现自启动和服务管理 将tomcat设置成像apache,nginx一样. 用serviec xxxx start/stop/restart ...

  7. linux 学习 12 服务管理

      第十二讲 Linux服务管理 12.1 Linux服务管理-服务分类 ——Linux服务 ----RPM包默认安装的服务 ————独立的服务 ————基于xinetd服务 ----源码包安装的服务 ...

  8. [MySQL Reference Manual] 5 MySQL 服务管理

    5. MySQL 服务管理 5. MySQL 服务管理 5.1 The Mysql Server 5.2 Mysql 服务日志 5.2.1 选择General query log和slow query ...

  9. Powershell实例小结(服务管理)

    有关服务管理的具体实例脚本如下: #$lists="1.1.1.1","2.2.2.2" #远程ip列表 foreach ($list in $lists){ ...

随机推荐

  1. SpringMVC源码解析 - HandlerAdapter - @SessionAttributes注解处理

    使用SpringMVC开发时,可以使用@SessionAttributes注解缓存信息.这样业务开发时,就不需要一次次手动操作session保存,读数据. @Controller @RequestMa ...

  2. JS+MySQL获取 京东 省市区 地区

    采集了一下JD的省市区地区 (非常简单,只是做个记录) 1.建表:account_area   2.进入页面: https://reg.jd.com/reg/company 在浏览器(Firefox) ...

  3. php CI框架输出空行问题排查

    今天在使用 curl 命令行工具调试一个功能时,发现输出的内容总是会在最开始莫名其妙的多一行空行: 项目框架是 php 的 CodeIgniter,感觉这种问题在网上不好查找,因为可以确定这个是业务出 ...

  4. Concurrent Request:Inactive phase,No Manager status

    Symptom 随便submit一个request,发现几乎所有的Concurrent Manager都为No Manager状态,Phase为Inactive. Solution 一个Concurr ...

  5. Android-HttpUtil工具类

    Http(Java 版 HttpURLConnection)请求的相关工具类 public class HttpUtil { private static final int TIMEOUT_IN_M ...

  6. [Erlang36]kerl轻松管理安装各种OTP版本

    kerl只有一个目标:让我们在不同的OTP版本间随意切换.他是一个纯Bash项目.简单实用的工作利器! Readme里面用法已说明得非常清楚了.建议按流程来一次. 1.下载 安装(一个bash脚本,根 ...

  7. 10-11Linux用户管理规则及用户管理函数

    用户管理: useradd, userdel, usermod, passwd, chsh, chfn, finger, id, chage 组管理: groupadd, groupdel, grou ...

  8. JavaSe 之三目运算符应用

    刚学习Java基本知识,对于三目运算符的应用,尝试了做出求某年份中月份的天数. /*自己随意定义一个年份和月份,使用三目运算符 取得当前月份具体天数.并且输出在控制台. 注意哦:大月31天,小月30天 ...

  9. 升级到Sharepoint 2013后页面打开速度慢

    这个问题现在有了一些新的发现. 首先,我找到了重现客户那里出现的那个复杂SQL语句的方法.这个现象其实是这样的: 当WebApplication的“List View Threshold” 数量大于 ...

  10. CentOS6.3上部署Ceph

    一.背景知识 搭建ceph的机器分为两种:client和非client(mds.monitor.osd). 配置时client只需要在内核编译时选上ceph就行,而其它三种则还需要编译ceph用户态源 ...