OS X: LaunchDaemon not running: Service could not initialize

16,028

Getting started with launchctl can definitely be a frustrating experience. I found a lot of articles explaining what you should do but few little downloadable samples. Here is a simple LaunchDaemon that will hopefully be a good starting point. You can just download the files here if you don't feel like copying and pasting.

Note: you need to replace MY_USER_NAME with your username. The plist needs to find your script.

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

This is a simple daemon script that will append the datetime to a file on your desktop. Note: since the script is run as root, tilde (~) won't be the home directory you expect.

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

Finally, I always write a little shell script to install the LaunchDaemons since it's easy to make a mistake. Since launchctl runs your script as root it requires that script's permissions not be writeable by others, since that would essentially give them root privileges.

// ~/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\""
Share:
16,028

Related videos on Youtube

nickcoxdotme
Author by

nickcoxdotme

Updated on September 18, 2022

Comments

  • nickcoxdotme
    nickcoxdotme almost 2 years

    I used Apple's seemingly straightforward docs to create a LaunchDaemon to run a Node.js script I wrote.

    Here's the plist file. It's basically exactly a copy-paste from Apple's docs, set to run every 300 seconds:

    <?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>
    

    Here's the error I get in /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
    

    What I've done:

    • It has the same permissions as the rest of the files in /Library/LaunchDaemons (-rw-r--r--, owned by root)
    • I read the docs for xpc, but that didn't help much.
    • I made sure that the Node.js script was adequately permissive (777), and runnable from the command line (it is).
    • Tried the absolute path to the file (/Users/nickcox/projects/eod_email/eod) and made sure I ran launchctl unload (daemonname) and launchctl load (daemon name)

    This seems much more complicated than cron, which is apparently deprecated, according to those Apple docs. What do I need to do to get this script to run on a schedule?

    • fd0
      fd0 almost 9 years
      tilde expansion is not going to work in 10.10 and above( at least that I know of). Use the absolute path. Your script perms should be 755. And I think that JavaScriptCore is not daemon safe.
    • nickcoxdotme
      nickcoxdotme almost 9 years
      See comment about absolute path in "What I've done." And it shouldn't matter if the script perms are overly permissive, right? It would only not work if it was not permissive enough, right? But to your last point, if that's the case, am I out of luck?
    • fd0
      fd0 almost 9 years
      I recommend that you read technical note- TN2083. Documentation does lags behind the ever changing launchd.
    • nickcoxdotme
      nickcoxdotme almost 9 years
      For anyone that finds this, @fd0 is referring to this document
  • Chris Conover
    Chris Conover over 8 years
    Thanks! I had a different problem, but through this example, and filtering logs in console on "launchd", I was able to identify my problem as one of permissions: I make sure that the plist and script were owned by root and not writable by others, and make sure I ran launchctl via sudo.
  • Abdel Karim Mateos Sanchez
    Abdel Karim Mateos Sanchez over 5 years
    A privative program into homebrew? Spam.