I have a shell script startup.sh
that does the following (create a RAM disk and start the teamcity agent):
#!/bin/bash
DISK=`/usr/bin/hdiutil attach -nobrowse -nomount ram://16777216`
/usr/sbin/diskutil erasevolume HFS+ "RamDiskCache" $DISK
/Users/administrator/buildAgent/bin/agent.sh start
I can run this from the command line by typing ./startup.sh
and it runs correctly. When I run from launchd, it ONLY creates the RAM disk, teamcity doesn't start.
My launchd plist is located in ~/Library/LaunchAgents
<?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.datafinch.teamcity</string>
<key>Program</key>
<string>/Users/administrator/startup.sh</string>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
What am I missing?
EDIT
Here is the agent.sh file:
https://gist.github.com/chriskooken/19f5856e3ce3c2322c53cb0afa69b057
Your agent.sh script launches the teamcity agent in the background, and then exits. This is contrary to the launchd way of managing jobs -- launchd expects its jobs to run in the foreground, where it can monitor them, restart them if they crash, shut them down when appropriate, etc. Basically, all the stuff you're doing with a PID file is what launchd normally takes care of for you. In this case, the direct problem is that when one of launchd's jobs exits (which yours does almost immediately, after it runs teamcity in the background), launchd will clean up any leftover mess, including killing any orphaned subprocess, like, say, the teamcity agent.
You have two choices:
- Convert to the launchd way of doing things. This'll mean replacing the agent.sh script with one that does things like checking prerequisites, finding Java, etc and then runs the teamcity agent in the foreground. Actually, it's probably best if it
exec
s the agent, so the agent runs directly as a child of launchd, rather than a child of the shell (which is a child of launchd); this gives launchd a more direct connection to monitor and manage it.
- Tell launchd not to kill off abandoned subprocesses by adding
<key>AbandonProcessGroup</key><true/>
to the .plist. This is simpler, but opts you out of all of launchd's other management features.