I have been writing Windows services in C/C++ and then in C## since 1999. Now that I am writing server based software in Go for the Linux OS I am completely lost. What is even more frustrating, is that for the first time the OS I am developing on (Mac OSX) is not the operating system I will be deploying my code on. That will be for another blog post.

I want to run my code as a background process (daemon) on my Mac. My only problem is, I have no idea how that works on the Mac OS.

I was lucky to find an open source project called service on Bitbucket by Daniel Theophanes. This code taught me how to create, install, start and stop daemons on the Mac OS. The code also supports daemons for the Linux OS and Windows.

Background Processes on the Mac OS

The Mac OS has two types of background processes, Daemons and Agents. Here is a definition for each:

daemon is a program that runs in the background as part of the overall system (that is, it is not tied to a particular user). A daemon cannot display any GUI; more specifically, it is not allowed to connect to the window server. A web server is the perfect example of a daemon.

An agent is a process that runs in the background on behalf of a particular user. Agents are useful because they can do things that daemons can’t, like reliably access the user’s home directory or connect to the window server.

For More Information:

http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/Introduction.html

Let’s start with how to configure a daemon in the Mac OS.

Screen Shot

If you open up finder you will see the following folders. The LaunchDaemons folder under Library is where we we need to add a launchd .plist file. There is also a Library/LaunchDaemons folder under /System for the OS daemons.

The launchd program is the service management framework for starting, stopping and managing daemons, applications, processes, and scripts in the Mac OS. Once the kernel starts launchd, the program scans several directories including /etc for scripts and the LaunchAgents and LaunchDaemons folders in both /Library and /System/Library. Programs found in the LaunchDaemons directories are run as the root user.

Here is the version of the launchd .plist file with all the basic configuration we need:

<?xml version=‘1.0’ encoding=‘UTF-8’?>
<!DOCTYPE plist PUBLIC \“-//Apple Computer//DTD PLIST 1.0//EN\” \”http://www.apple.com/DTDs/PropertyList-1.0.dtd\” >
<plist version=‘1.0’>
<dict>
<key>Label</key><string>My Service</string>
<key>ProgramArguments</key>
<array>
<string>/Users/bill/MyService/MyService</string>
</array>
<key>WorkingDirectory</key><string>/Users/bill/MyService</string>
<key>StandardOutPath</key><string>/Users/bill/MyService/My.log</string>
<key>KeepAlive</key><true/>
<key>Disabled</key><false/>
</dict>
</plist>

You can find all the different options for the .plist file here:

https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man5/launchd.plist.5.html

The ProgramArguments key is an important tag:

<key>ProgramArguments</key>
<array>
  <string>/Users/bill/MyService/MyService</string>
</array>

Here you specify the name of the program to run and any other arguments to be passed into main.

These other two tags, WorkingDirectory and StandardOutPath are real helpful too:

<key>WorkingDirectory</key><string>/Users/bill/MyService</string>
<key>StandardOutPath</key><string>/Users/bill/MyService/My.log</string>

Once we have a launchd .plist file we can use a special program called launchctl to start our program as a background process (daemon).

launchctl load /Library/LaunchDaemons/MyService.plist

#go

Running Go Programs as a Background Process
2.55 GEEK