试图了解 launchd 守护进程状态

Trying to understand launchd daemon state

我正在尝试在 macOS 10.13 High Sierra 上为 Zabbix 代理设置启动守护进程。

首先我安装 Zabbix 代理:

brew install zabbix --without-server-proxy

然后我创建一个名为 com.zabbix.zabbix_agentd.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>AbandonProcessGroup</key>
        <true/>
        <key>GroupName</key>
        <string>zabbix</string>
        <key>KeepAlive</key>
        <dict>
                <key>SuccessfulExit</key>
                <false/>
        </dict>
        <key>Label</key>
        <string>com.zabbix.zabbix_agentd</string>
        <key>ProgramArguments</key>
        <array>
                <string>/usr/local/sbin/zabbix_agentd</string>
                <string>-c</string>
                <string>/opt/zabbix/zabbix_agentd.conf</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>StandardErrorPath</key>
        <string>/var/log/zabbix/zabbix_agentd.error.log</string>
        <key>StandardOutPath</key>
        <string>/var/log/zabbix/zabbix_agentd.stdout.log</string>
        <key>UserName</key>
        <string>zabbix</string>
</dict>
</plist>

我加载它:

sudo launchctl load ./com.zabbix.zabbix_agentd.plist

现在我可以看到守护进程已经完成了我预期的工作:

ps ax | grep zabbix_agentd | grep -v grep

我看到 6 个 zabbix 进程。 1 个收集器、3 个侦听器、1 个主动检查和启动守护进程启动的进程:

8931   ??  S      0:00.01 /usr/local/sbin/zabbix_agentd -c /opt/zabbix_agentd.conf

但是当我 运行 这个命令时:

launchctl print system/com.zabbix.zabbix_agentd | grep state

我得到这个输出:

state = waiting

我希望看到 state = 运行ning... 为什么该命令告诉我守护进程在等待时有 6 个 运行ning 进程?

这是"works as designed"还是我做错了什么?

这有点 "works as designed",但我真的想说这是 zabbix 和 launchd 之间关于守护进程应该如何工作的哲学冲突的结果。

当你 运行 zabbix_agentd 时,它 "daemonizes" 本身,意味着它作为后台子进程触发实际的守护进程,然后父进程退出;从那时起,守护进程(以及它启动的任何子进程)运行 几乎独立于启动它们的任何东西。这几乎是 unix 守护进程运行的传统方式。

launchd,另一方面,被编写为期望它管理的守护进程留在前台并直接在其下执行;与远离 launchd 时相比,这使 launchd 有更多的能力来监视和控制它的守护进程。

这是传统unix daemons和launchd的常见冲突,解决方法有两种:要么让daemon到前台运行(即符合launchd的做事方式) ,或者告诉 launchd 不要担心守护进程似乎已经退出。 zabbix_agentd 似乎没有 --nodaemon 选项(根据 these docs),所以你必须适应 launchd(更新:更新版本有,见下文)。执行此操作的标准方法(这几乎是您在 .plist 中所拥有的)是添加 AbandonProcessGroupKeepAlive 键以告诉 launchd 在(据它所知)守护程序退出。这行得通,但这意味着 launchd 无法判断守护进程实际发生了什么,从而导致您看到看起来很奇怪的结果。

更新:我在看 zabbix_agentd 的旧版本。 Stefan 发现 -f(或 --foreground)选项被添加到 version 3.0 中的 zabbix_agentd。有了这个,我建议将 --foreground 添加到 ProgramArguments 数组,用简单的 <true/> 替换 KeepAlive 字典(这告诉 launchd 如果它自动重启守护进程出于任何原因退出),并删除 <key>AbandonProcessGroup</key><true/>(如果主守护进程 exits/crashes,此选项控制 launchd 是否清理剩余的子进程)。结果应如下所示:

<?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>GroupName</key>
        <string>zabbix</string>
        <key>Label</key>
        <string>com.zabbix.zabbix_agentd</string>
        <key>ProgramArguments</key>
        <array>
                <string>/usr/local/sbin/zabbix_agentd</string>
                <string>-c</string>
                <string>/opt/zabbix/zabbix_agentd.conf</string>
                <string>--foreground</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>KeepAlive</key>
        <true/>
        <key>StandardErrorPath</key>
        <string>/var/log/zabbix/zabbix_agentd.error.log</string>
        <key>StandardOutPath</key>
        <string>/var/log/zabbix/zabbix_agentd.stdout.log</string>
        <key>UserName</key>
        <string>zabbix</string>
</dict>
</plist>