Cannot launch service

I would like to run an executable as service on macOS.

The executable is a Node JS application packaged using pkg https://www.npmjs.com/package/pkg

I have copied it to a local folder under /opt/caligo/ninja/server and created a .plist file to launch it as service.


ls -lt
total 92584
-rwxr-xr-x  1 eriknorman  wheel  47399568 Feb 13 13:15 caligo-ninja-server-0.6.1-darwin


If I run the application it starts without problems, it starts a socket listening on a port and outputs "hey" to console.


eriknorman@Eriks-Mac-mini server ./caligo-ninja-server-0.6.1-darwin 
hey


I have created the plist file and saved it under /Library/LaunchDaemons/

eriknorman@Eriks-Mac-mini server % cd /Library/LaunchDaemons 
eriknorman@Eriks-Mac-mini LaunchDaemons % ls
com.caligo.caligo-ninja.server.plist 
eriknorman@Eriks-Mac-mini LaunchDaemons % cat com.caligo.caligo-ninja.server.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.caligo.caligo-ninja.server</string>
    <key>Program</key>
    <string>/opt/caligo/ninja/server/caligo-ninja-server-0.6.1-darwin</string>
    <key>KeepAlive</key>         <true/>
    <key>RunAtLoad</key>         <true/>
    <key>Disabled</key>          <false/>
    <key>UserName</key> <string>root</string>
</dict>
</plist>


I have loaded it with the appropriate launchctl commands, but to no avail


eriknorman@Eriks-Mac-mini LaunchDaemons % sudo launchctl load /Library/LaunchDaemons/com.caligo.caligo-ninja.server.plist 
eriknorman@Eriks-Mac-mini LaunchDaemons % sudo launchctl start com.caligo.caligo-ninja.server  
eriknorman@Eriks-Mac-mini LaunchDaemons % sudo launchctl print system/com.caligo.caligo-ninja.server
system/com.caligo.caligo-ninja.server = {
	active count = 0
	path = /Library/LaunchDaemons/com.caligo.caligo-ninja.server.plist
	state = spawn scheduled


	program = /opt/caligo/ninja/server/caligo-ninja-server-0.6.1-darwin
	default environment = {
		PATH => /usr/bin:/bin:/usr/sbin:/sbin
	}


	environment = {
		XPC_SERVICE_NAME => com.caligo.caligo-ninja.server
	}


	domain = system
	minimum runtime = 10
	exit timeout = 5
	runs = 3
	last exit code = 1


	spawn type = daemon (3)
	jetsam priority = 4
	jetsam memory limit (active) = (unlimited)
	jetsam memory limit (inactive) = (unlimited)
	jetsamproperties category = daemon
	submitted job. ignore execute allowed
	jetsam thread limit = 32
	cpumon = default


	properties = keepalive | runatload
}


The executable also creates a local file when started, but nothing appears.

I have tried to check system logs and error logs, nothing so far.

What am I missing?


You can download the executable here:

https://s3.eu-west-1.amazonaws.com/caligo-ninja-deliverables/eeb8896c-0646-4151-a7aa-5d79bbd01253/caligo-ninja-server-0.6.1-darwin

Mac mini, macOS 12.2

Posted on Feb 13, 2022 5:24 AM

Reply
Question marked as Top-ranking reply

Posted on Feb 14, 2022 8:35 AM

Found it.


I needed to add the working directory, since the service creates a local file upon start.

If the working directory isn't specified it defaults to a read-only folder (or at least one my user didn't have access to).

Similar questions

10 replies

Feb 14, 2022 9:32 AM in response to etresoft

As I mentioned above, checking the logs is way, way, way more complicated this. Console can drive people insane. And I'm not exaggerating for effect here.

That is correct.


I found the following plist entries very helpful in solving this problem:

<key>StandardErrorPath</key>
<string>/tmp/error.log</string>
<key>StandardOutPath</key>
<string>/tmp/out.log</string>


That made it super easy to find what the problem was, resulting in adding the WorkingDirectory node, as already mentioned above.


Is it supposed to do that? Daemons are normally supposed to continuously run in the background. You specifically told launchd that it would behave that way with "KeepAlive". If your "KeepAlive" task is repeatedly quitting with an error code, then Launchd is going to stop running it because obviously there is a problem with it.

No, the application crashed due to missing access rights to write to the default working directory. Adding the specific node in the xml fixed that.


Maybe put away the shovel and take a higher-level point of view. What are you actually trying to accomplish? Are you writing a tool that runs 24x7 in the background? Or are you trying to do something else? Whatever you are trying to do, your configuration parameters should match the expected, and realized, behaviour. If not, launchd is going to assume there is a problem and stop the task.

Currently, I'm creating an installer application which will download the latest available version and run the required commands to install it. I already had that working on Linux and Windows, and now also on macOS.

The server application itself is just a dummy application - for now. I just wanted to get the installer baked into the CI/CD cycle right from the start, so it will be tried and tested once the actual server and client applications are ready to be release into the wild.


Thanks for your pointers above. Once you mentioned that checking logs on Mac was difficult, I began researching on how to do that, and that lead me to the solution of my problems.


Feb 14, 2022 8:37 AM in response to caligo-erik

caligo-erik wrote:

There is the app called Console which shows the launchd logs which are the ones I was looking for.

As I mentioned above, checking the logs is way, way, way more complicated this. Console can drive people insane. And I'm not exaggerating for effect here.

The log shows that the process exits with 1, and then is marked as inactive (because exiting within 10 seconds of launch).

Is it supposed to do that? Daemons are normally supposed to continuously run in the background. You specifically told launchd that it would behave that way with "KeepAlive". If your "KeepAlive" task is repeatedly quitting with an error code, then Launchd is going to stop running it because obviously there is a problem with it.

I'll continue digging

Maybe put away the shovel and take a higher-level point of view. What are you actually trying to accomplish? Are you writing a tool that runs 24x7 in the background? Or are you trying to do something else? Whatever you are trying to do, your configuration parameters should match the expected, and realized, behaviour. If not, launchd is going to assume there is a problem and stop the task.

Feb 14, 2022 7:54 AM in response to etresoft

etresoft wrote:

OK. The forum's automatic colour scheme and your unusual shell prompt made me think you were running a "server" tool to run the script. I guess "server" is just part of your prompt. Normally there is a "$" there to help prevent such confusion.

Otherwise, all of my other points still stand.

server is the current directory showing up in the Terminal. I must have accidentally deleted the % sign.

Also, launch daemons run in a significantly different environment from your user account.
How are you checking system and error logs? On a Mac, that alone is an order of magnitude more difficult than anything else you've mentioned so far.

It would be nice to know how they are different. I tried checking the logs and couldn't see anything that seemed helpful.


While Googling I found references to increasing the log level of the launchctl service management, but that didn't work on my Mac mini.






Feb 13, 2022 11:46 AM in response to caligo-erik

When you run it from the command line, you are using some "server" command. Is that from node or something? You aren't doing that in the launchd config file.


Also, launch daemons run in a significantly different environment from your user account.


How are you checking system and error logs? On a Mac, that alone is an order of magnitude more difficult than anything else you've mentioned so far.


And finally, you don't have public access turned on for that download file.

Feb 13, 2022 11:14 PM in response to etresoft

The application is built from Node JS, but it is a packaged standalone executable containing the Node executable.


I can run it from console simply with ./

eriknorman@Eriks-Mac-mini server ./caligo-ninja-server-0.6.1-darwin 
hey


The file was not downloaded via browser. I run an installer (again, an executable Node JS application) which fetches the file and writes it to disk using fs.write(). As mentioned above, I can run the executable without problems in the console and I didn't have to confirm anything.

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

Cannot launch service

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.