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

Launch Daemon Creation

  1. Launch Xcode, and create a command line application namedWebTwainService.
#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 SampleService to/Applications/TONLABS/SampleService.

3. Referring to Create Launch Daemons and Agents, create a configuration file com.tonylabs.SampleService.plist.

  • StandardErrorPath & StandardOutPath: service log file path
  • KeepAlive. Set it true. When SampleService crashes unexpectedly, 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.tonylabs.SampleService.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.tonylabs.SampleService.plist.

7. Type in sudo launchctl to run launchd:

8. Register plist with command load -D system /Library/LaunchDaemons/com.tonylabs.SampleService.plist. Then we can see our service has been loaded.

9. Type in list to check whether the service is running.

10. Now, reboot system to verify whether the SampleService can work. Open /var/log/sample.log