We are building a 'server' application that can either run as a daemon or can run in background without showing any GUI. Basically, the end user can either configure this to run as a daemon so that it can be tied to the user's session or will launch the process which user will start and quit as needed.
I wanted to understand what is the recommended mechanism for such an application from Apple -
- Should this application be built as a macOS Bundle ? Apple documentation also says that we should not daemonize the process by calling fork. Hence if we create a unix-style executable, will I not need to fork to make it run in a detached state when I launch the executable via double-click ? [Reference Link]
- Is it fine to have an application on macOS which is a bundle but does not show any UI when launched by double click on the app-icon or via 'open'? While we have been able to achieve this by using NSApplicationMain and not showing the UI, was wondering if using CFRunLoop is best for this case as it is a non-gui application.
If we can get the right documentation link or recommendations on how we should build such an application which can run in a non-gui mode and also in a daemonized manner, it will help us.
Should the application be always built as a macos bundle or should it be a unix-style executable to support both the cases - by the same application/product and how should we look at the distribution of such applications.
First up, terminology. On Apple platforms an application, or app for short, is a GUI program that the user launches. I’m going to use the term server program for what you’re calling an “application”.
The best way to handle this is to create a standard macOS app — with a GUI that you can launch in the Finder — and then embed your server program within that. See Placing Content in a Bundle for advice on how to structure this.
How you proceed from there depends on the specific details of your product. My preferred option would be:
-
Add a status and control UI in the GUI app.
-
In that UI, use
SMAppService
to install your server program as either a daemon or an agent. -
And similarly for uninstall.
However, other approaches might make sense. For more specific advice I need to know what you mean by:
If by “end user” you mean a normal user installing your product on their own Mac then the above approach is definitely the best option. OTOH, if the “end user” is a site admin in a managed environment, who configures your product for all members of their organisation, other options might make sense.
As to whether your server program needs to be in a bundle structure, in many cases that’s not necessary. The one case where it’s absolutely necessary is if it uses restricted entitlements. See Signing a daemon with a restricted entitlement. In that case, the nesting looks like this:
MyApp.app/
Contents/
MacOS/
MyApp
MyServer.app/
Contents/
MacOS/
MyServer
… other stuff …
… other stuff …
Coming back to your specific questions:
No, you’re way off in the weeds here. If you want your server program to run in the background, set things up so that it’s started by launchd
. You can choose to have it run as either a daemon (in the global context) or an agent (in a user context).
SMAppService
makes this easy. There are other options that are older and less pleasant, but more flexible.
At a technical level, yes. The issue is with the user experience. Mac users do not expect apps to just ‘disappear’ in the background when you launch them. That’s a horrible UE.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"