I do my Django development work locally on OS X, so I have several different daemons installed on my machine. I used to keep Postgres, MySQL, lighttpd, memcached, and more set up to autostart and run continuously, but I didn't like the burden on performance (real or imagined). Also, I switch between projects frequently and I often need to switch config files based on the project I'm about to work on.
My solution is to use the end-user customization hooks that Doug Hellmann's excellent virtualenvwrapper provides. If you're not familiar with virtualenvwrapper, it makes it easy to manage your virtualenvs in one place and switch between them quickly and conveniently. The project provides several scripts that are meant to be added to by the end-user to customize behavior.
For my configuration files, I create multiple versions with the changes needed for each project, and I then create a symlink to the version I want at the moment. For example, with lighttpd I'll create an
/etc/lighttpd/project-a.conf and an
/etc/lighttpd/project-b.conf, and then create a symlink called
/etc/lighttpd/lighttpd.conf that points to the one I need.
In OS X, I use launchd .plist files that have the OnDemand option set to True. I've posted the .plists I'm using currently to Github. Put these in your
/Library/LaunchDaemon/ folder and then load them using the command:
sudo launchctl load /Library/LaunchDaemon/[plist_filename]
This registers the processes with OS X's launchd system. Afterwards, you can start and stop them using the commands:
sudo launchctl start [label]
sudo launchctl stop [label]
Note that, when starting and stopping, you don't have to use the path to the .plist file. Just use the daemon's label, which is typically the filename without the path or the
Env-specific virtualenvwrapper scripts
I use the project-specific
postdeactivate scripts to swap in the right config and start the daemons that I need for a particular project. You'll find these in the
$WORKON_HOME/[project_name]/bin directory. If your virtualenv is a little old, those scripts may not already be present. As long as you're up-to-date with a recent version of virtualenvwrapper, you can simply add those scripts to your virtualenv's
bin directory yourself.
$WORKON_HOME/project-a/bin/postactivate, I use a script similar to this:
# This hook is run after this virtualenv is activated.
sudo launchctl start org.postgresql.postmaster
sudo launchctl start com.danga.memcached
sudo mv /etc/lighttpd/lighttpd.conf /etc/lighttpd/lighttpd.conf.bak
sudo ln -s /etc/lighttpd/project-a.conf /etc/lighttpd/lighttpd.conf
sudo launchctl start net.lighttpd
I like having the
cd command there so that I can immediately run
$WORKON_HOME/project-a/bin/postdeactivate, I use:
# This hook is run after this virtualenv is deactivated.
sudo launchctl stop org.postgresql.postmaster
sudo launchctl stop com.danga.memcached
sudo launchctl stop net.lighttpd
So now, when I run
workon project-a, postgres, memcached, and lighttpd all
come to life. When I run
workon project-b, the
postdeactivate script for project-a runs, and then the
postactivate script for project-b runs. This effectively switches my lighty conf and restarts the process so it's immediately ready for me. When I
deactivate, the processes shut down and my computer can take advantage of the free memory.
General virtualenvwrapper scripts
Virtualenvwrapper also provides global hooks directly in $WORKON_HOME. Brian Rosner suggested making the config switching generic so you wouldn't have to create scripts for each environment. I haven't tried this yet, but it definitely wouldn't be hard to do. The environment variable
$VIRTUAL_ENV is available within
postactivate scripts, so
$WORKON_HOME/postactivate could include a block that looks something like this:
if [ -f /etc/lighttpd/$VIRTUAL_ENV.conf ]; then
sudo ln -s /etc/lighttpd/$VIRTUAL_ENV.conf /etc/lighttpd/lighttpd.conf
All you would have to do is name your config files after your environments, and they would automatically be symlinked into place when you activate the environment.