I've searched around the internet and could not find a clear answer.
I have a swift command line tool that needs to run automatically when the Mac mini M4 is started up without a user login and continue running forever. However, the command line tool and the data it uses are located on an external disk due to the size of the data.
The service specified by a launchd plist located in /Library/LaunchDaemons tries to start up but fails because it cannot immediately find the command line tool. Which is because the external disk is not mounted when launchd tries to start the service when the Mac is booting. The service runs fine when bootstrapped after the disk is mounted.
The first error is "No such file or directory, error 0x6f - Invalid or missing Program/ProgramArguments" and the service is put in the "penalty box".
- Is there any way for the service to get out of the "penalty box"?
- What is the best approach to make the launchd service wait for a specific external disk to mount?
Some options for waiting seem to be:
- Use "WatchPaths" in the launchd plist, but the man page says this is unreliable. This makes one wonder what is the purpose of this option?
- Use "StartOnMount in the launchd plist", but this will run the command line tool every time any disk is mounted. This is not desired.
- Of course, I could move the command line tool to the startup disk, but then the tool would fail because the data is not available. This could be remedied by modifying the command line tool to wait for the external disk, but it would be polling, which seems inefficient. I could also add a delay, but that seems error prone because there is no assurance that the delay is long enough.
- When looking at the system plists, there seem to be a lot of options that are not directly mentioned in the man page for launchd.plist and have little to no documentation that I could find. Maybe there is something I am missing here?
In the end, I would just like to make sure the launchd service waits for the specific disk to be available before starting the service. Any ideas how best to do that?
I recommend that you use option 2, with a small launchd
daemon that monitors the mounted volumes and uses that information to decide whether to start your real program or not.
but this will run the command line tool every time any disk is mounted.
Yes and no. launchd
uses an on-demand architecture, and if you set StartOnMount
then a disk mount becomes a form of demand. However, once you’re running you can stay running and monitor the mounted volumes using some other API (FileManager
or, as kthchew suggested, Disk Arbitration).
And you don’t have to worry about this daemon eating into the user’s resources. The system will stop the daemon if it runs short on resources. And if that happens, a future disk mount is considered demand, and that’ll start your daemon again.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"