Thursday 28 August 2008

Running Nexus with launchd on OS X

I've finally got Nexus running for maven builds to help boost the speed downloading and checking repos etc.

This gave me the excuse to finally take a quick look at using launchd which is the preferred OS X way to run daemons and services. First look it appears cool and much nicer than rc/init.d/xinit.d et al.

Here's a really simple always-run nexus script, sonatype.nexus.plist. Just drop it into your ~/Library/LaunchAgents/ directory and you should be good to go.

From the command line you can then do this if you want to boot it up straight away - but it should restart on reboot (which I'll test out next time I've gotta reboot :)
launchctl start sonatype.nexus
I did try get clever and wait for port 8081 to be used before booting up nexus but couldn't get it to work properly so figured just starting it up on boot was easier :)

Update: BTW the script is available under the Apache License 2.0 if anyone wants to copy it or include it in any distro of Nexus

5 comments:

Brian Fox said...

Hi James, mind if we include this in the Nexus bundle going forward?

James Strachan said...

Please do!

I guess keeping it running all the time on startup is maybe simpler than doing the on-demand-wait-for-port-8081 to be used etc.

Jason said...

Looks like you have to first:

launchctl load ~/Library/LaunchAgents/sonatype.nexus.plist

then:

launchctl start sonatype.nexus

Or I suppose add the .plist and log out/in.

Unknown said...

I've just noticed that the plist uses the start argument. This will cause the wrapper to fork, which launchd doesn't like. The net effect is that it'll start nexus once, but you won't be able to control it thereafter.

If you change it to console then everything works as expected:

$ launchctl load ~/Library/LaunchAgents/Nexus.plist

$ launchctl stop com.sonatype.nexus

$ launchctl start com.sonatype.nexus

Steve Tarver said...

My first try at a launchd plist. I spent a little time with this and thought I would add my lessons learned. I created a nexus user on my computer just for the nexus app and repo. I wanted nexus to start on system start and without anyone logged in so other computers could hit it when I was not logged in.

I created a /Library/LaunchAgents directory and got the following error: launchctl: Dubious ownership on file (skipping): /Library/LaunchAgents. Needed to sudo chown root:wheel /Library/LaunchAgents.

I had permission problems and ended up making the plist root:wheel 644. I set run as nexus (user) in both the plist and the nexus conf.

When trying to load sonatype.nexus, I would get: launchctl: no plist was returned for: /Library/LaunchAgents/sonatype.nexus.plist. I had fat-fingered an end tag and had invalid xml. Fixed that.

Next, on load from computer restart, the system.log showed that it appeared to run but was not running when I logged in. I found that launchd garbage collects child processes for security reasons (hates forkers). I added AbandonProcessGroup to inhibit this.

Last, Lingon is a pretty simple way to manage these plists.

Here is the plist that I ended up putting in /Library/LaunchDaemons/


<?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>sonatype.nexus</string>
<key>ProgramArguments</key>
<array>
<string>/Users/nexus/nexus-webapp-1.5.0/bin/jsw/macosx-universal-32/nexus</string>
<string>start</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>UserName</key>
<string>nexus</string>
<key>LaunchOnlyOnce</key>
<true/>
<key>AbandonProcessGroup</key>
<true/>
</dict>
</plist>