OS X: LaunchDaemon не работает: служба не может инициализироваться

Я использовал на первый взгляд простые документы Apple для создания 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--принадлежит рут)
  • Я прочитал документы для xpc, но это не сильно помогло.
  • Я позаботился о том, чтобы скрипт Node.js был адекватно разрешающим (777) и запускался из командной строки (это так).
  • Пробовал абсолютный путь к файлу (/Users/nickcox/projects/eod_email/eod) и убедился, что я побежал launchctl unload (daemonname) а также launchctl load (daemon name)

По словам тех Apple, это кажется намного сложнее, чем cron, который явно устарел. Что мне нужно сделать, чтобы запустить этот скрипт по расписанию?

2 ответа

Начало работы с launchctl определенно может быть разочаровывающим опытом. Я нашел много статей, объясняющих, что вы должны делать, но мало маленьких загружаемых примеров. Вот простой LaunchDaemon, который, будем надеяться, станет хорошей отправной точкой. Вы можете просто скачать файлы здесь, если не хотите копировать и вставлять.

Примечание. Вам нужно заменить MY_USER_NAME своим именем пользователя. Плист должен найти ваш сценарий.

// 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"

Наконец, я всегда пишу небольшой скрипт для установки 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\""

Было бы полезно, если бы вы могли вставить вывод launchctl list | grep 'com.wintr.eodemail',

Кроме того, оформить заказ /var/log/eod-email.log файл. Это может дать вам точные ошибки.

Я рекомендую установить brew cask install launchcontrol, который является графическим инструментом для launchctl, он может помочь обнаружить ошибки и устранить неполадки.

Другие вопросы по тегам