如何在 OSX Yosemite 10.10.3+ 中守护非特权脚本

How to daemonize non-privileged script in OSX Yosemite 10.10.3+

多年来,我们的应用程序中一直有一个 process-monitoring/control 脚本。脚本的默认行为是守护进程本身。通常脚本由非特权用户启动,必要时。由于我不会详细说明的原因,我们需要保留脚本和此行为。

OSX 系统上,我们传统上通过 /usr/libexec/StartupItemContext[=46= 让脚本在后台自行重启] 苹果提供的启动脚本。这将我们的进程置于 Mach StartupItem bootstrap 上下文中,而不是登录 bootstrap 上下文中。这是必要的,因为如果没有上下文切换,当用户注销时(这通常也是必要的),脚本将失去对目录服务、getpwuid()、DNS 服务等的访问权限。守护脚本的原始内部行本质上看起来像这样(在 perl 中):

my $cmd = "/usr/libexec/StartupItemContext myscript @Commandline > logs/startup 2>&1" ;         
system( "$cmd &") ;
exit 0 ;

OSXYosemite出来的时候,那个StartupItemContext脚本就没有了,所以改成直接调用的 launchctl:

my $cmd = "/usr/launchctl bsexec / myscript @Commandline > logs/startup 2>&1" ;         
system( "$cmd &") ;
exit 0 ;

随着最近的OSX10.10.3升级,然而,bsexec子命令launchctl 突然需要root权限:

% launchctl bsexec
This subcommand requires root privileges: bsexec
% 

这给我们带来了一个棘手的问题,即非特权用户无法再让我们的 monitoring/control 脚本自行守护进程。

似乎 Glassfish has encountered this problem and addressed it with a patch 取代了

/bin/launchctl bsexec /

nohup

这可能适用于 Glassfish 实施,但我认为不适合我们。尽管我不明白这一事实——即为什么简单地阻止 SIGHUP 会阻止退役登录 bootstrap 上下文中的进程丢失服务——它似乎在我们对所有人的测试中也不起作用我们需要的系统服务。

OSX 上从非特权 Mach "login" bootstrap 开始守护进程的新规范方法是什么上下文,而不会在用户注销时失去对关键系统服务(如 DNS 等)的访问权限?

"from a non-privileged, Mach "login" bootstrap context" 不幸的是不太可能有 "canonical way." 唯一规范的方法是通过 launchd 按需启动服务。甚至 "bsexec" 也几乎不受支持,也几乎没有记录。根据我的经验,不可能跟上 OS X 变化并且从不重新设计您的发射系统。我重新设计了每个其他版本的守护程序系统,因为 Apple 破坏了它,而且他们将继续破坏它。唯一的答案是继续努力使您的需求更简单。但是几乎任何想要一直 运行 而不是按需执行的进程都直接违反了 Apple 的既定意图,因此它很可能会中断。

Apple 给出的解决方案是创建一个 LaunchDaemon 并在您的 launchd plist 中为其分配一个 UserName。您必须启动特权,然后切换到用户(它需要是固定用户,而不是 "the logged in user",因为那将是一个 LaunchAgent)。您无法通过这种方式升级您的访问权限。您不能将自己守护进程(同样,规范的答案是:不要那样做。请参阅 launchd.plist 手册页。)

我怀疑 Glassfish nohup 解决方案只是一种逃避,实际上并未将它们置于 Mach 上下文中。他们只是想避免在父 shell 退出时被杀死。那可能对你没有帮助。

根据我的经验,最可靠的解决方案是多部分的。您最终得到一个 运行 作为系统 LaunchDaemon(带有 KeepAlive)的部分,另一部分是用户 LaunchAgent,您让它们通过 IPC 进行通信,以便您可以访问每个 activity你需要做的。是的,这通常实施起来要复杂得多。更简单的解决方案往往行不通。

当然你必须不断地问自己 "is there any way I could achieve this by doing things the way Apple wants me to." 这意味着 XPC 是强烈首选,其次是按需 LaunchDaemons 和 LaunchAgents。如果您构建系统以使用 XPC 组件,您可能会在更多 OS X 升级后幸存下来。您发现不使用这些部分的任何工作都可能必须在 10.11 中再次修复。