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:
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.<key>AbandonProcessGroup</key><true/>
to the .plist. This is simpler, but opts you out of all of launchd's other management features.