OS X - 如何让简单的 launchd 守护进程在 Yosemite 和 El Capitan 上运行

OS X - 如何让简单的 launchd 守护进程在 Yosemite 和 El Capitan 上运行

我对 OS X 上的 launchd 并不陌生。过去我创建过几个守护进程,最近一次是与 Mountain Lion Mavericks 一起创建的。

但是,我似乎很难让最简单的 plist 在 Mavericks 和 El Capitan 上运行。最初,我复制了运行 Tomcat 的 plist,并对其进行了修改,以使 WebSphere Liberty Profile 在启动时运行。看到一些错误后,我决定尝试 Apple 自己的 [site][1] 中的以下示例 plist。以下内容甚至无法运行:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

<dict>

    <key>Label</key>
    <string>com.example.hello</string>

    <key>ProgramArguments</key>
    <array>
        <string>hello</string>
        <string>world</string>
    </array>

    <key>KeepAlive</key>
    <true/>

</dict>

每当我将 plist 文件放在 /Library/LaunchDaemons 然后加载 plist 时,我都会在控制台中看到以下错误:

2015 年 10 月 5 日 上午 11:52:44.868 com.apple.xpc.launchd[1]: (com.example.hello) 此服务被定义为持续运行,本质上效率低下。

2015 年 10 月 5 日 上午 11:52:44.869 com.apple.xpc.launchd[1]:(com.example.hello[66956])服务无法初始化:15A284:xpcproxy + 12644 [1472][19011403-4854-3CCD-9FCF-49C36302EB40]:0x2

2015 年 10 月 5 日 上午 11:52:44.870 com.apple.xpc.launchd[1]: (com.example.hello) 服务仅运行了 0 秒。重生时间推迟了 10 秒。

就输出而言就是这样。我尝试写入 StandardOutput 和 StandardError 日志,但日志文件是空的。

当我看到这种情况发生在优胜美地和酋长岩上时,我认为这一定是与权限有关的事情:

-rw-r--r-- 1 根轮 418 十月 5 11:52 helloworld.plist

但是,我尝试将权限设置为 644 和 755 来运行守护进程,但仍然看到相同的控制台错误。

我是否忽略了什么?

答案1

正如我所看到的,<key>KeepAlive</key>正在输出com.apple.xpc.launchd[1]: (com.example.hello) This service is defined to be constantly running and is inherently inefficient.然后它告诉自己在 10 秒后重新启动该过程<key>

我不能 100% 确定它com.apple.xpc.launchd[1]: (com.example.hello[66956]) Service could not initialize: 15A284: xpcproxy + 12644 [1472][19011403-4854-3CCD-9FCF-49C36302EB40]: 0x2在说什么,因为我没有该事件的日志,但它似乎在抗议原始事件,<key>因为它没有执行任何其他操作。也许尝试删除<key>或将其更改为其他内容?可能:

<key>Label</key>
<string>com.example.hello</string>

<key>ProgramArguments</key>
<array>
    <string>hello</string>
    <string>world</string>
</array>

<key>KeepAlive</key>
<false/>

或者

<key>Label</key>
<string>com.example.hello</string>

<key>ProgramArguments</key>
<array>
    <string>hello</string>
    <string>world</string>
</array>

再次强调,我对此不是 100% 确定,但我建议尝试类似的东西。操作系统抗议不需要 keepAlive 节点,所以祝你好运。

答案2

我能够在@Dooley_labs 和@Spiff 的帮助下创建一个工作示例(谢谢)。

以下示例将每 10 秒将 Hello World 回显到指定的日志文件。控制台不显示任何输出,但当我查看日志文件的内容时,我看到 Hello World 被重复写入其中。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>

        <key>Label</key>
        <string>com.example.hello</string>

        <key>ProgramArguments</key>
        <array>
            <string>echo</string>
            <string>Hello World</string>
        </array>

        <key>KeepAlive</key>
        <true/>

        <key>StandardOutPath</key>
        <string>/var/log/helloworld.log</string>

    </dict>

</plist>

答案3

当您读到这篇文章时,您会打自己一巴掌,但是,您并没有告诉 launchctl 要运行什么可执行文件!

第一个答案正确地将“echo”作为第一个“ProgramArguments”,但并没有说这就是问题所在。

我相信您也可以使用“Program”键来完成此操作,但我不确定您是否必须在“ProgramArguments”键中重复此操作,我相信这是传递给可执行文件的 arg[] 数组。

要注意的另一件事是始终列出可执行文件的完整路径。launchd/launchctl 非常严格,但是,Bad Guy™ 仍然可以将恶意的“echo”可执行文件放在默认 $PATH 的某个地方,然后等待 launchctl 重新解析 LaunchDaemon plist。

相关内容