How to Create a Background Service on Mac OS X

As a Windows developer, I spent some time looking for an efficient way to create a service, as a counterpart of Windows service, on Mac OS X. Referring to the online documentation – Designing Daemons and Services, there are four types of background processes. The type Launch Daemon satisfies my requirements: running in the background with no access to the window server. In this article, let’s go through the process of creating a Launch Daemon on Mac OS X.

Mac Background Service: Launch Daemon

  1. Launch Xcode, and create a command line application named WebTwainService.

     #import <Foundation/Foundation.h>
     int main(int argc, const char * argv[])
         @autoreleasepool {
             // insert code here...
             NSLog(@"Hello, World!");
         while (1)
         return 0;
  2. Build the project, and move the executable file WebTwainService to /Applications/Dynamsoft/WebTwainService.
  3. Referring to Create Launch Daemons and Agents, create a configuration file com.dynamsoft.WebTwainService.plist.service_plist
    • StandardErrorPath & StandardOutPath: service log file path
    • KeepAlive. Set it true. When WebTwainService crashes unexpectedly, the system will automatically re-launch the service.
    • Label: unique value.
    • ProgramArguments: executable file path.
  4. These folders are where the plist should be placed:
    • ~/Library/LaunchAgents: Per-user agents provided by the user.
    • /Library/LaunchAgents: Per-user agents provided by the administrator.
    • /Library/LaunchDaemons: System-wide daemons provided by the administrator.
    • /System/Library/LaunchAgents: Per-user agents provided by Mac OS X.
    • /System/Library/LaunchDaemons: System-wide daemons provided by Mac OS X.
  5. Move com.dynamsoft.WebTwainService.plist to /Library/LaunchDaemons.
  6. To register service successfully, we have to modify the file permissions. Otherwise, we’ll receive the error message: launchctl: Dubious ownership on file (skipping). Launch terminal and type in the command sudo chown root  /Library/LaunchDaemons/com.dynamsoft.WebTwainService.plist.service_permission
  7. Type in sudo launchctl to run launchd:service_launchd
  8. Register plist with command load -D system /Library/LaunchDaemons/com.dynamsoft.WebTwainService.plist. Then we can see our service has been loaded. service_loaded
  9. Type in the list to check whether the service is running.service_run
  10. Now, reboot the system to verify whether the WebTwainService can work. Open /var/log/webtwain.log service_log

Source Code