OS X:LaunchDaemon 未运行:服务无法初始化

OS X:LaunchDaemon 未运行:服务无法初始化

我用了苹果的文档看似简单创建一个 LaunchDaemon 来运行我编写的 Node.js 脚本。

这是plist文件。它基本上就是从 Apple 文档中复制粘贴的,设置为每 300 秒运行一次:

<?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.wintr.eodemail</string>
    <key>ProgramArguments</key>
    <array>
        <string>~/projects/eod_email/eod</string>
    </array>
    <key>StartInterval</key>
    <integer>300</integer>
<key>StandardOutPath</key>
    <string>/var/log/eod-email.log</string>
    <key>StandardErrorPath</key>
    <string>/var/log/eod-email.log</string>
    <key>Debug</key>
    <true/>
</dict>
</plist>

这是我遇到的错误/var/log/system.log

Jul 22 10:55:52 Nick-Cox com.apple.xpc.launchd[1] (com.wintr.eodemail[7097]): Service could not initialize: 14E46: xpcproxy + 13421 [1402][7D917364-B96E-3F93-B923-A89B5BF5736D]: 0x2

我做了什么:

  • 它具有与 /Library/LaunchDaemons 中的其他文件相同的权限(-rw-r--r--,由 root 拥有)
  • 我读过xpc 文档,但这并没有什么帮助。
  • 我确保 Node.js 脚本具有足够的权限(777),并且可以从命令行运行(确实如此)。
  • 尝试了文件的绝对路径(/Users/nickcox/projects/eod_email/eod)并确保我运行launchctl unload (daemonname)launchctl load (daemon name)

根据 Apple 文档,这似乎比 cron 复杂得多,而 cron 显然已被弃用。我需要做什么才能让此脚本按计划运行?

答案1

开始使用 launchctl 绝对是一种令人沮丧的体验。我发现很多文章都解释了你应该做什么,但很少有可下载的示例。这里有一个简单的 LaunchDaemon,希望可以作为一个很好的起点。你可以点击此处下载文件如果您不想复制和粘贴。

注意:您需要用您的用户名替换MY_USER_NAME。plist 需要找到您的脚本。

// at ~/Desktop/testdaemon/com.wintr.eodemail.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.wintr.eodemail</string>
    <key>Program</key>
    <string>/Users/MY_USER_NAME/Desktop/testdaemon/testdaemon.sh</string>
    <key>StandardErrorPath</key>
    <string>/var/log/eod-email.log</string>
    <key>StandardOutPath</key>
    <string>/var/log/eod-email.log</string>
    <key>RunAtLoad</key>
    <true/>
    <key>StartInterval</key>
    <integer>15</integer>
</dict>
</plist>

这是一个简单的守护进程脚本,它会将日期时间附加到桌面上的文件中。注意:由于脚本以 root 身份运行,波浪号 (~) 不会是您期望的主目录。

// at ~/Desktop/testdaemon/testdaemon.sh
#!/bin/sh
home="/Users/MYUSERNAME" ## note -- this will be run as root, ~ is not your normal user
now=$(date "+%Y-%m-%d %H.%M.%S")
echo $now >> "$home/Desktop/TestFile.txt"

最后,我总是编写一个小 shell 脚本来安装 LaunchDaemons,因为很容易犯错误。由于 launchctl 以 root 身份运行您的脚本,因此它要求该脚本的权限不能由其他人写入,因为这实际上会赋予他们 root 权限。

// ~/Desktop/testdaemon/install.sh
#!/bin/sh -e
plist_path="com.wintr.eodemail.plist"
plist_filename=$(basename "$plist_path")
install_path="/Library/LaunchDaemons/$plist_filename"

echo "installing launchctl plist: $plist_path --> $install_path"
sudo cp -f "$plist_path" "$install_path"
sudo chown root "$install_path"
sudo chmod 644 "$install_path"

sudo launchctl unload "$install_path"
sudo launchctl load "$install_path"

echo "to check if it's running, run this command: sudo launchctl list | grep wintr"
echo "to uninstall, run this command: sudo launchctl unload \"$install_path\""

答案2

如果您能粘贴 的输出,那将会很有帮助launchctl list | grep 'com.wintr.eodemail'

另外,检查你的/var/log/eod-email.log文件。它可能会给出确切的错误信息。

我建议安装brew cask install launchcontrol,它是 launchctl 的 GUI 工具,它可以帮助检测错误和排除故障。

相关内容