launchd 在 El Capitan 中没有 'keep alive' 进程

launchd does not 'keep alive' processes in El Capitan

我试图确保进程始终处于 运行ning 状态,即使在它退出、崩溃或停止之后也是如此。它是一个读取串行线并写入数据库的小型二进制文件——没有什么太复杂的。如果读取失败,它会以退出代码 70 退出,并捕获任何 SIGKILL 或 SIGTERM 事件并在实际退出之前优雅地关闭它的数据库连接。

但是,该进程不会在加载时启动(即使设置了此标志),如果它被终止也不会重新启动。这是 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>Disabled</key>
    <false/>
    <key>KeepAlive</key>
    <true/>
    <key>Label</key>
    <string>blah.bloop.tag05</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/blah/Desktop/rfid</string>
        <string>-f/dev/tty.usbserial-FT32X30YBXB</string>
        <string>-n5</string>
        <string>-ctcp://127.0.01</string>
        <string>-v</string>
        <string>-x100000</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>StandardErrorPath</key>
    <string>/var/log/rfid.log</string>
    <key>StandardOutPath</key>
    <string>/var/log/rfid.log</string>
    <key>WorkingDirectory</key>
    <string>/Users/blah/Desktop</string>
</dict>
</plist>

这个 plist 位于 ~/Library/LaunchAgents(并且有问题的用户可以很容易地停止和启动这个过程)。

有什么想法吗?我知道还有其他进程正在重新启动,但我终究无法弄清楚这个进程。我认为权限可能是它,但这些看起来都很好:/

我决定尝试另一个 plist,看看是不是我的守护程序出了问题。事实证明,它已启动:

所以我决定 运行 使用程序 tail 进行快速测试。我想看看这是我的守护进程本身还是与 launchd 有关。似乎 launchd 是问题所在。这是一个替代的简单 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>KeepAlive</key>
        <true/>
        <key>Label</key>
        <string>test.test</string>
        <key>ProgramArguments</key>
        <array>
                <string>/usr/bin/tail</string>
                <string>-f</string>
                <string>/var/log/system.log</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>StandardErrorPath</key>
        <string>/tmp/test.test.err</string>
        <key>StandardOutPath</key>
        <string>/tmp/test.test.out</string>
</dict>
</plist>

我使用以下命令启动此过程

launchctl load test.plist
launchctl start test.test

然后我通过使用 kill 命令向进程发送 SIGKILL 或 SIGTERM 来从另一个终端终止进程。 Launchd 无法重新启动进程。

我怀疑 El-Capitan 中一定有我错过的新内容?

进一步的实验揭示了答案。似乎只有 'Global Daemons' 等守护进程遵守重启和 RunAtLaunch 指令。我注意到 /Library/LaunchDaemons 中有几个 plist,例如 TeamViewer 和其他第三方程序。

有趣的是,可以将 SIGKILL 发送到属于 Apple 的进程,例如 ImageCaptureAgent,并且不遵守 KeepAlive 指令。这是一个 Apple 定义的代理 plist 文件,明确指出进程在被终止时应该重新启动,但事实并非如此。

我想知道 Apple 是否在较新版本中更改了此功能?