试图了解 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 中所拥有的)是添加 AbandonProcessGroup
和 KeepAlive
键以告诉 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>
我正在尝试在 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 中所拥有的)是添加 AbandonProcessGroup
和 KeepAlive
键以告诉 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>