Starting a Perforce Server on Mac OS X with Launchd
Image: Jason Corneveaux via Flickr
A few years ago I switched from a laptop running Windows 7 to a MacBook Pro with OS X. One of the few things that bothered me was that my many Perforce Servers (P4D) I have running on my machine (to be able to quickly demonstrate different configurations such as replication) did not start automatically.
On Windows I simply installed a service for each Perforce Server I needed using srvinst.exe that Perforce provides with the standard installer. On Linux I can use initd and p4dctl, but initd is deprecated on Mac OS X. Instead, you are supposed to use Launchd.
To use Launchd you need to create an XML file called a plist file that defines the service you want to start automatically and its parameters. There are several locations where a plist file is stored, but the definitions for your private files are in your home directory under “~/Library/LaunchAgents/”. Here is an example for a plist file I use to start my main Perforce Server:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.perforce.main</string> <key>OnDemand</key> <false/> <key>Program</key> <string>/usr/local/bin/p4d</string> <key>ProgramArguments</key> <array> <string>p4d </string> <string>--pid-file</string> </array> <key>EnvironmentVariables</key> <dict> <key>P4ROOT</key><string>/Perforce/main</string> <key>P4LOG</key><string>/Perforce/main/log</string> <key>P4PORT</key><string>1666</string> </dict> <key>RunAtLoad</key> <true/> <key>ServiceDescriptor</key> <string>Launches main Perforce Server</string> </dict> </plist>
There are several noteworthy aspects to this file:
- The service starts automatically at boot time (RunAtLoad)
- I can specify which executable to run (here: /usr/local/bin/p4d)
- I can define environment variables (e.g., P4ROOT)
- I can pass in any program arguments
The first program argument is especially interesting. This is the name that is listed in the process list (shown with the standard Unix “ps” command). Normally, this is just the executable name (here “p4d”), but you can easily add additional information like the port the server is listening on to it. When I try to find out which Perforce Servers are currently active I simply run
$ ps –aef | grep p4d 501 27542 276 0 Tue09am ?? 0:00.03 p4d  --pid-file 501 46982 276 0 9:44am ?? 0:00.02 p4d [ssl:20101] --pid-file 501 47120 276 0 9:46am ?? 0:00.02 p4d-main-g  --pid-file 501 47554 276 0 9:50am ?? 0:00.01 p4d replica  --pid-file 501 47560 47554 0 9:50am ?? 0:00.50 p4d replica  --pid-file 501 47561 47554 0 9:50am ?? 0:00.38 p4d replica  --pid-file 501 47562 47554 0 9:50am ?? 0:00.37 p4d replica  --pid-file 501 47563 47554 0 9:50am ?? 0:00.38 p4d replica  --pid-file 501 47568 27542 0 9:50am ?? 0:01.98 p4d  --pid-file 501 47660 276 0 9:54am ?? 0:00.01 p4d unicode  --pid-file
The –pid-file argument is worth mentioning as well. This is a new feature in Perforce Server 2014.2 that writes the process id of a started P4D service to a file called server.pid in the server root directory. You can also specify a file name with the –pid-file argument to change the name or location. This feature makes it easier for administrators to identify what P4D process corresponds to what process id.
You can test and control the service, for example, with command-line launchctl from the Terminal application:
launchctl load ~/Library/LaunchAgents/com.perforce.main.plist launchctl unload ~/Library/LaunchAgents/com.perforce.main.plist
An amusing side effect of processes started with Launchd is that OS X will restart the service automatically if you shut it down without unloading it, so a Perforce Server stopped with “p4 admin stop” will automatically be restarted. Unload the process instead if you want it permanently shut down.