<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>Rob Seaman - Home</title>
  <id>tag:blog.robseaman.com,2009:mephisto/</id>
  <generator version="0.8.0" uri="http://mephistoblog.com">Mephisto Drax</generator>
  <link href="http://blog.robseaman.com/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://blog.robseaman.com/" rel="alternate" type="text/html"/>
  <updated>2009-07-12T02:08:41Z</updated>
  <entry xml:base="http://blog.robseaman.com/">
    <author>
      <name>Rob</name>
    </author>
    <id>tag:blog.robseaman.com,2009-07-11:19</id>
    <published>2009-07-11T23:55:00Z</published>
    <updated>2009-07-12T02:08:41Z</updated>
    <category term="Ruby"/>
    <category term="sysinfo"/>
    <link href="http://blog.robseaman.com/2009/7/11/detecting-the-number-of-processors-with-ruby" rel="alternate" type="text/html"/>
    <title>Detecting the number of processors with Ruby</title>
<summary type="html">&lt;p&gt;This post contains a cross platform Ruby method to return the total number of CPU cores.  There are gems, such as &lt;a href=&quot;http:&quot; /&gt;facter&lt;/a&gt;, that will do the same thing and much more but if you just want a quick and dirty single purpose method this will probably suffice.  The only tricky bit was picking the best way to do the determination in Windows.  I ended up using a WMI approach described in Rick Minerich's &lt;a href=&quot;http:&quot; /&gt;There Counting Processors in .NET: The Pros and Cons of Five Different Methods&lt;/a&gt; post.</summary><content type="html">
            &lt;p&gt;This post contains a cross platform Ruby method to return the total number of CPU cores.  There are gems, such as &lt;a href=&quot;http:&quot; /&gt;facter&lt;/a&gt;, that will do the same thing and much more but if you just want a quick and dirty single purpose method this will probably suffice.  The only tricky bit was picking the best way to do the determination in Windows.  I ended up using a WMI approach described in Rick Minerich's &lt;a href=&quot;http:&quot; /&gt;There Counting Processors in .NET: The Pros and Cons of Five Different Methods&lt;/a&gt; post.
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# Returns the number of processor for Linux, OS X or Windows.&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;number_of_processors&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;RUBY_PLATFORM&lt;/span&gt; =~ &lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;linux&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&lt;span class=&quot;dl&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cat /proc/cpuinfo | grep processor | wc -l&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;`&lt;/span&gt;&lt;/span&gt;.to_i&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;elsif&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;RUBY_PLATFORM&lt;/span&gt; =~ &lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;darwin&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&lt;span class=&quot;dl&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sysctl -n hw.logicalcpu&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;`&lt;/span&gt;&lt;/span&gt;.to_i&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;elsif&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;RUBY_PLATFORM&lt;/span&gt; =~ &lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;win32&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;c&quot;&gt;# this works for windows 2000 or greater&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;win32ole&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    wmi = &lt;span class=&quot;co&quot;&gt;WIN32OLE&lt;/span&gt;.connect(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;winmgmts://&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    wmi.ExecQuery(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;select * from Win32_ComputerSystem&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).each &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |system| &lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;begin&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        processors = system.&lt;span class=&quot;co&quot;&gt;NumberOfLogicalProcessors&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;rescue&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        processors = &lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;return&lt;/span&gt; [system.&lt;span class=&quot;co&quot;&gt;NumberOfProcessors&lt;/span&gt;, processors].max&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  raise &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;can't determine 'number_of_processors' for '&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;co&quot;&gt;RUBY_PLATFORM&lt;/span&gt;&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;br /&gt;
          </content>  </entry>
  <entry xml:base="http://blog.robseaman.com/">
    <author>
      <name>Rob</name>
    </author>
    <id>tag:blog.robseaman.com,2009-01-22:18</id>
    <published>2009-01-22T20:18:00Z</published>
    <updated>2009-01-22T20:24:05Z</updated>
    <category term="Ruby"/>
    <category term="multiruby"/>
    <category term="rubinius"/>
    <link href="http://blog.robseaman.com/2009/1/22/adding-rubinius-to-multiruby-versions" rel="alternate" type="text/html"/>
    <title>Adding Rubinius to multiruby Versions</title>
<summary type="html">&lt;p&gt;In previous posts I've covered using &lt;code&gt;&lt;a href=&quot;http://blog.zenspider.com/zentest/2007/12/&quot;&gt;multiruby&lt;/a&gt;&lt;/code&gt; to &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/20/switching-between-ruby-1-8-1-9-with-multiruby&quot;&gt;switch between Ruby 1.8 &amp; 1.9&lt;/a&gt;&lt;/em&gt; and &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/21/adding-jruby-to-multiruby-versions&quot;&gt;how to add JRuby to your multiruby&lt;/a&gt;&lt;/em&gt; environment.  This post describes using &lt;code&gt;multiruby&lt;/code&gt; as a way to install and experiment with &lt;a href=&quot;http://rubini.us/&quot;&gt;Rubinius&lt;/a&gt; in Mac OS X.</summary><content type="html">
            &lt;p&gt;In previous posts I've covered using &lt;code&gt;&lt;a href=&quot;http://blog.zenspider.com/zentest/2007/12/&quot;&gt;multiruby&lt;/a&gt;&lt;/code&gt; to &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/20/switching-between-ruby-1-8-1-9-with-multiruby&quot;&gt;switch between Ruby 1.8 &amp; 1.9&lt;/a&gt;&lt;/em&gt; and &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/21/adding-jruby-to-multiruby-versions&quot;&gt;how to add JRuby to your multiruby&lt;/a&gt;&lt;/em&gt; environment.  This post describes using &lt;code&gt;multiruby&lt;/code&gt; as a way to install and experiment with &lt;a href=&quot;http://rubini.us/&quot;&gt;Rubinius&lt;/a&gt; in Mac OS X.

&lt;/p&gt;
&lt;p&gt;In this post I assume you have &lt;a href=&quot;http://git.or.cz/&quot;&gt;git&lt;/a&gt; and a current version of &lt;code&gt;multiruby&lt;/code&gt;, which is part of the popular ZenTest gem.  If you do have it but your revision is older than 3.11.1 then you should update it. If ZenTest is not installed then see &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/20/switching-between-ruby-1-8-1-9-with-multiruby&quot;&gt;Switching Between Ruby 1.8 &amp; 1.9 with multiruby&lt;/a&gt;&lt;/em&gt; for information about getting started with &lt;code&gt;multiruby&lt;/code&gt;.
&lt;/p&gt;
&lt;h3&gt;Installing Rubinius in &lt;code&gt;~/.multiruby&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;If &lt;code&gt;multiruby&lt;/code&gt; is ready to go, then the place to start is cloning Rubinius to the &lt;code&gt;multiruby&lt;/code&gt; vendor directory: 
&lt;/p&gt;
&lt;pre&gt;
$ cd ~/.multiruby/versions
$ git clone git://github.com/evanphx/rubinius.git 
&lt;/pre&gt;
&lt;p&gt;Rubinius support is built-in to &lt;code&gt;multiruby&lt;/code&gt; but before letting &lt;code&gt;multiruby&lt;/code&gt; do the build take a look at the &lt;code&gt;~/.multiruby/versions/rubinius/doc/getting_start.txt&lt;/code&gt; to see if you're missing any required software. In my case I was missing the &lt;a href=&quot;http://parsetree.rubyforge.org/&quot;&gt;ParseTree&lt;/a&gt; gem:
&lt;/p&gt;
&lt;pre&gt;
$ sudo gem install ParseTree
&lt;/pre&gt;
&lt;p&gt;After getting any known missing prerequisites, the next step is to execute &lt;code&gt;multiruby&lt;/code&gt; which will see &lt;code&gt;rubinius&lt;/code&gt; in its versions directory and automatically try to build it:
&lt;/p&gt;
&lt;pre&gt;
$ multiruby -e &quot;p 1+1&quot;
building and installing rubinius
Running command: rake &amp;&gt; log.build
&lt;/pre&gt;
&lt;p&gt;If you get an error check the &lt;code&gt;log.build&lt;/code&gt; file in &lt;code&gt;~/.multiruby/build/rubinius&lt;/code&gt;.  The most common problem will be a missing prerequisite, something that should be obvious in the log.  If you don't get any errors then after a fairly lengthy build you should see a successful execution:
&lt;/p&gt;
&lt;pre&gt;
...
VERSION = rubinius
CMD     = ~/.multiruby/install/rubinius/bin/rbx -e p 1+1

2

RESULT = 0
...

TOTAL RESULT = 0 failures out of 5

Passed: 1.8.6-p287, jruby-1.1.6, 1.9.1-preview2, rubinius, 1.8.7-p72
Failed: 
&lt;/pre&gt;
&lt;p&gt;That's it, if executing Rubinius via &lt;code&gt;multiruby&lt;/code&gt; is all you want to do then you're done.  If you want to execute Rubinius independently of &lt;code&gt;multiruby&lt;/code&gt; read on about adding it to your PATH.
&lt;/p&gt;
&lt;h3&gt;Running Rubinious Outside of multiruby&lt;/h3&gt;
&lt;p&gt;Rubinius runs Ruby code with its own command name (&lt;code&gt;rbx&lt;/code&gt;). To make the &lt;code&gt;multiruby&lt;/code&gt; version of &lt;code&gt;rbx&lt;/code&gt; available you need to add the &lt;code&gt;rubinius/bin&lt;/code&gt; directory to the PATH in your login initialization file, i.e. your &lt;code&gt;.bash_login&lt;/code&gt; file:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;# manage ruby verisions&lt;tt&gt;
&lt;/tt&gt;export PATH=$PATH~/.multiruby/install/rubinius/bin&lt;tt&gt;
&lt;/tt&gt;export ORIGPATH=$PATH&lt;tt&gt;
&lt;/tt&gt;...&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;I would recommend adding it to the end of your PATH variable, or at least past your existing &lt;code&gt;ruby&lt;/code&gt; command path just in case you ever decide to add the &lt;code&gt;ruby&lt;/code&gt; symlink that I'll discuss next.
&lt;/p&gt;
&lt;h3&gt;Rubinius as Ruby via Alias Switching&lt;/h3&gt;
&lt;p&gt;In &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/20/switching-between-ruby-1-8-1-9-with-multiruby&quot;&gt;Switching Between Ruby 1.8 &amp; 1.9 with multiruby&lt;/a&gt;&lt;/em&gt; I created aliases to set the path in the &lt;code&gt;.bash_login&lt;/code&gt; to select which version of Ruby gets used:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;# switch between ruby verisions&lt;tt&gt;
&lt;/tt&gt;export ORIGPATH=$PATH&lt;tt&gt;
&lt;/tt&gt;alias mr186p287='export PATH=~/.multiruby/install/1.8.6-p287/bin:$ORIGPATH'&lt;tt&gt;
&lt;/tt&gt;alias mr187p72='export PATH=~/.multiruby/install/1.8.7-p72/bin:$ORIGPATH'&lt;tt&gt;
&lt;/tt&gt;alias mr191pre2='export PATH=~/.multiruby/install/1.9.1-preview2/bin:$ORIGPATH'&lt;tt&gt;
&lt;/tt&gt;alias mrjruby='export PATH=~/.multiruby/install/jruby-1.1.6/bin:$ORIGPATH'&lt;tt&gt;
&lt;/tt&gt;alias mroff='export PATH=$ORIGPATH'&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Since &lt;code&gt;multiruby&lt;/code&gt; recognizes the &lt;code&gt;rbx&lt;/code&gt; command you can use Rubinius anytime as long as you added it to your path and setting up an alias to switch over to Rubinius as your default Ruby implementation isn't required.  However, if you have applications that launch &lt;code&gt;ruby&lt;/code&gt; or you just want you to be able to execute Rubinius with the &lt;code&gt;ruby&lt;/code&gt; command then you can still use the same alias technique I described in my previous post. First, create a &lt;code&gt;ruby&lt;/code&gt; symlink with: 
&lt;/p&gt;
&lt;pre&gt;
$ ln -fs ~/.multiruby/install/rubinius/bin/rbx \
&gt; ~/.multiruby/install/rubinius/bin/ruby
&lt;/pre&gt;
&lt;p&gt;Second, setup a new alias in your &lt;code&gt;.bash_login&lt;/code&gt; with something like:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;28&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;alias mrrub='export PATH=~/.multiruby/install/runius/bin:$ORIGPATH'&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Now, after you reopen your terminal session, &lt;code&gt;$ mrrub&lt;/code&gt; will use Multiruby whenever you execute the &lt;code&gt;ruby&lt;/code&gt; command.  You can switch back to your default Ruby implementation with &lt;code&gt;$ mroff&lt;/code&gt;.
&lt;/p&gt;
&lt;p&gt;Again, since Rubinius executes via &lt;code&gt;rbx&lt;/code&gt; and &lt;code&gt;multiruby&lt;/code&gt; is aware of that, so symlinking and aliasing is totally optional. With JRuby the symlink was required for &lt;code&gt;multiruby&lt;/code&gt; compatibility but the alias was optional. When I first setup JRuby I didn't bother with an alias but decided to add it later when I wanted to test scripts that launch &lt;code&gt;ruby&lt;/code&gt; as a subprocess, i.e. &lt;code&gt;`ruby -e ...&lt;/code&gt;.  This time I created the symlink and alias right from the start.
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.robseaman.com/">
    <author>
      <name>Rob</name>
    </author>
    <id>tag:blog.robseaman.com,2009-01-15:16</id>
    <published>2009-01-15T01:51:00Z</published>
    <updated>2009-01-15T07:37:34Z</updated>
    <category term="Website Setup"/>
    <category term="2.2.2"/>
    <category term="cachedexternals"/>
    <category term="git"/>
    <category term="mephisto"/>
    <category term="smtp"/>
    <link href="http://blog.robseaman.com/2009/1/15/upgrading-to-mephisto-0-8-1" rel="alternate" type="text/html"/>
    <title>Upgrading to Mephisto 0.8.1</title>
<summary type="html">&lt;p&gt;Last month &lt;a href=&quot;http://mephistoblog.com/2008/12/21/mephisto-0-8-1-drax-relaunched&quot;&gt;Mephisto 0.8.1: Drax was relaunched&lt;/a&gt;.  Seeing activity on Mephisto was great news in itself.  The update includes support for Rails 2.2.2 and several significant security fixes.  The release is considered experimental but important because of the security fixes. That's a bit of a mixed message but I have no financial stake in my blog so decided to do an update.
&lt;/p&gt;
&lt;p&gt;This post describes my update process.  It provides some general information about the changes and provides an example of using interactive git rebasing but in most cases it won't be a cookie cutter approach that you can follow for your own Mephisto implementation. In &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/1/gitting-started-with-mephisto&quot;&gt;gitting Started with Mephisto&lt;/a&gt;&lt;/em&gt; and other posts I've described how I set-up Mephisto 0.8. Unless you've followed along and are maintaining Mephisto in the same way, or at least maintain your Mephisto blog in a git repository with customizations in your own branch, then your update procedure will probably be significantly different.</summary><content type="html">
            &lt;p&gt;Last month &lt;a href=&quot;http://mephistoblog.com/2008/12/21/mephisto-0-8-1-drax-relaunched&quot;&gt;Mephisto 0.8.1: Drax was relaunched&lt;/a&gt;.  Seeing activity on Mephisto was great news in itself.  The update includes support for Rails 2.2.2 and several significant security fixes.  The release is considered experimental but important because of the security fixes. That's a bit of a mixed message but I have no financial stake in my blog so decided to do an update.
&lt;/p&gt;
&lt;p&gt;This post describes my update process.  It provides some general information about the changes and provides an example of using interactive git rebasing but in most cases it won't be a cookie cutter approach that you can follow for your own Mephisto implementation. In &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/1/gitting-started-with-mephisto&quot;&gt;gitting Started with Mephisto&lt;/a&gt;&lt;/em&gt; and other posts I've described how I set-up Mephisto 0.8. Unless you've followed along and are maintaining Mephisto in the same way, or at least maintain your Mephisto blog in a git repository with customizations in your own branch, then your update procedure will probably be significantly different. 

&lt;/p&gt;
&lt;p&gt;I should point out that I've been using the &lt;a href=&quot;http://github.com/technoweenie/mephisto/tree/master&quot;&gt;technoweenie version&lt;/a&gt; of Mephisto from github and not the &lt;a href=&quot;http://github.com/emk/mephisto/tree/master&quot;&gt;emk version&lt;/a&gt; where all of the latest experimental work is going on.  When I pulled from the master the latest commit in technoweenie branch was very close to the emk v0.8.1 (v0.8-stable) tag that marked the version that's available for &lt;a href=&quot;http://mephistoblog.com/download&quot;&gt;download from the Mephisto site.&lt;/a&gt;  The only additional commits in the official release were a safe_erb test update and emk-safe-erb was updated from 0.1.1 to 0.1.2. The main point is that when I talk about pulling the latest master, it's really a fairly stable version.  At some point I may migrate over to emk but so far I haven't had a compelling reason to do so. 
&lt;/p&gt;
&lt;h3&gt;The Original Plan&lt;/h3&gt;
&lt;p&gt;In &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/1/gitting-started-with-mephisto&quot;&gt;gitting Started with Mephisto&lt;/a&gt;&lt;/em&gt; I described my upgrade strategy for future releases using rebasing:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ git checkout master
[mac]$ git pull
[mac]$ git checkout robseaman
[mac]$ git rebase master
&lt;/pre&gt;
&lt;h3&gt;The Updated Plan&lt;/h3&gt;
&lt;p&gt;When it came time to move to 0.8.1 I stuck with that basic concept but added a few details like a backup step and an interactive rebase instead of an automatic one. There were several reasons for going with an interactive rebase, the biggest ones were that I'd installed Rails 2.0.2 in vendor and used &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/3/cached-externals&quot;&gt;Cached Externals&lt;/a&gt;&lt;/em&gt;.  Allowing the commits associated with those changes when I knew Mephisto had added support for Rails 2.2.2 and probably also changed other externals would result in a bunch of messy conflicts that I'd need to resolve, assuming it worked at all.  Interactive rebasing would provide the control I needed to make the rebase reasonably clean.  The first steps were to do a backup and pull down the latest Mephisto master branch:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ cap data:load_from_prod
[mac]$ cd ..
[mac]$ cp -r mephisto mephisto_backup
[mac]$ cd mephisto
[mac]$ git checkout master
[mac]$ git pull
&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;$ cap data:load_from_prod&lt;/code&gt; (see &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/2/production-data-to-development&quot;&gt;Production Data to Development&lt;/a&gt;&lt;/em&gt; for details) and the copy created a backup of the production database and 0.8 version. After the git-pull I ended up with revision e229865d6e63a6b6c0e6cb7aac21992ca303f94a of Mephisto.
&lt;/p&gt;
&lt;p&gt;With the latest master in hand I looked for changes that would impact my rebase process. More specifically I was looking for changes to any of the externals that I'd been caching (see &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/3/cached-externals&quot;&gt;Cached Externals&lt;/a&gt;&lt;/em&gt;). The first thing that stood out is that my pull of Mephisto included TZInfo-0.3.12 in the &lt;code&gt;vendor/gems&lt;/code&gt; directory. TZInfo can't be vendorized so it shouldn't be there.  In fact the first development commit (emk repository) made after the 0.8.1 release was to remove it. See &lt;a href=&quot;http://groups.google.com/group/MephistoBlog/browse_thread/thread/31cf68a861867925&quot;&gt;
Should TZInfo be included in vendor/gems?&lt;/a&gt; for details.  Since the vendorized copy won't be used make sure you follow 0.8.1 download page instructions: &quot;Before installing: Run sudo gem install tzinfo&quot;. Alternately you can make sure you have all the gems including TZInfo installed on your target by running:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ rake gems:install
&lt;/pre&gt;
&lt;p&gt;On with the rest of the inspection, I already knew I'd need to upgrade to Rails 2.2.2 and of course it wasn't embedded so the next step was to inspect the RSpec directories. The old 2962 versions in 0.8 were from subversion repositories. I knew that a lot of work went into updating the tests for Mephisto so I wasn't surprised to find the RSpec directories contained updated copies of git repositories. A search for &quot;rspec&quot; in &lt;code&gt;gitk&lt;/code&gt; showed a checkin comment indicating that the latest github versions available on 12-4-2008 were used.  Going over to &lt;a href=&quot;http://github.com/dchelimsky/rspec/commits/&quot;&gt;github's rspec commits&lt;/a&gt; the last commit before 12-4-2008 was f85a53bb54b13e6461c8ffbded4933b90e40a86c and the commit for &lt;a href=&quot;http://github.com/dchelimsky/rspec-rails/commits/master&quot;&gt;rspec-rails&lt;/a&gt; was f96eb3fd4d95eb400e87b4f1cf8e6a279f1dbcbd.
&lt;/p&gt;
&lt;h3&gt;Interactive Rebasing&lt;/h3&gt;
&lt;p&gt;OK, now I had the basic information I knew I'd need. With that background I moved on to checkout my custom branch and start the interactive rebase:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ git checkout robseaman
[mac]$ git rebase -i master
&lt;/pre&gt;
&lt;p&gt;Interactive rebasing opens a file called &lt;code&gt;git-rebase-todo&lt;/code&gt; in your editor. &lt;code&gt;git-rebase-todo&lt;/code&gt; contains a list of the branch's commits with an action to be applied to each one. The default is to pick (apply) each one and apply them in order but they can be squashed (merged), edited after they are applied, deleted or reordered.  Here was a pseudo edit copy of my list showing the changes I decided to make:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;35&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;38&lt;tt&gt;
&lt;/tt&gt;39&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;40&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;41&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;e f2b123a Changed to track changes for my blog.&lt;tt&gt;
&lt;/tt&gt;DELETE&amp;gt; pick f25ef13 Froze to Rails 2.0.2.&lt;tt&gt;
&lt;/tt&gt;DELETE&amp;gt; pick 286a82d Updated to Rails 2.0.2 boot.rb.&lt;tt&gt;
&lt;/tt&gt;DELETE&amp;gt; pick c8efd30 Put tzinfo 0.3.12 in vendor dir.&lt;tt&gt;
&lt;/tt&gt;pick dcddd47 Changed secret from distributed version.&lt;tt&gt;
&lt;/tt&gt;pick 0c1579c Disabled multi-site support.&lt;tt&gt;
&lt;/tt&gt;pick f78a7d3 Ran db:bootstrap&lt;tt&gt;
&lt;/tt&gt;pick 7c4f203 Initial versions from capify.&lt;tt&gt;
&lt;/tt&gt;pick d1d5efc First customized version of deploy.rb&lt;tt&gt;
&lt;/tt&gt;pick 9a4a736 Added Railscasts CodeRay style.&lt;tt&gt;
&lt;/tt&gt;pick 4cead81 Updated styles for coderay.&lt;tt&gt;
&lt;/tt&gt;DELETE&amp;gt; pick b6e7478 Added doc directory.&lt;tt&gt;
&lt;/tt&gt;pick b1ac0ef Restyled sidebar and meta fields.&lt;tt&gt;
&lt;/tt&gt;e 5c0bdb4 Added Cached Externals plugin.&lt;tt&gt;
&lt;/tt&gt;DELETE&amp;gt; pick f7308b9 Created externals YAML file.&lt;tt&gt;
&lt;/tt&gt;DELETE&amp;gt; pick 4ff2557 Cached Externals: rails, tzinfo &amp;amp; rspec/rspec_rails&lt;tt&gt;
&lt;/tt&gt;pick 4105041 Change the application user.&lt;tt&gt;
&lt;/tt&gt;pick 5c29462 Added section article count, change tags to use linebreak as separator.&lt;tt&gt;
&lt;/tt&gt;pick 40507f7 Added more coderay standard defs to help code match to linenums.&lt;tt&gt;
&lt;/tt&gt;pick 0289fc4 Added standard coderay.css (from coderay_stylesheet) for reference.&lt;tt&gt;
&lt;/tt&gt;pick 6ff1ba4 Increased top and bottom padding to give a little breathing room.&lt;tt&gt;
&lt;/tt&gt;pick d978f48 Added git://github.com/caritos/action_mailer_tls.git for TLS mail support.&lt;tt&gt;
&lt;/tt&gt;pick a874664 Added gmail blog account settings.&lt;tt&gt;
&lt;/tt&gt;DELETE&amp;gt; pick 4d153be Added action_mailer_tls to the externals list.&lt;tt&gt;
&lt;/tt&gt;pick 66bc24c Commented out display of links to other pages in the same section.&lt;tt&gt;
&lt;/tt&gt;pick 0bfb9c8 Removed Search sidebar title, Added min-nav icon section.&lt;tt&gt;
&lt;/tt&gt;pick df51dd7 Added email subscriptions.&lt;tt&gt;
&lt;/tt&gt;pick 11905d1 Changed mini-nav icon to include text and increased site font size.&lt;tt&gt;
&lt;/tt&gt;pick b1c246b Changed Contact to 'Contact Me'.&lt;tt&gt;
&lt;/tt&gt;pick 58d48cd Changed Contact Me to just Contact.&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;# Rebase e229865..58d48cd onto e229865&lt;tt&gt;
&lt;/tt&gt;#&lt;tt&gt;
&lt;/tt&gt;# Commands:&lt;tt&gt;
&lt;/tt&gt;#  p, pick = use commit&lt;tt&gt;
&lt;/tt&gt;#  e, edit = use commit, but stop for amending&lt;tt&gt;
&lt;/tt&gt;#  s, squash = use commit, but meld into previous commit&lt;tt&gt;
&lt;/tt&gt;#&lt;tt&gt;
&lt;/tt&gt;# If you remove a line here THAT COMMIT WILL BE LOST.&lt;tt&gt;
&lt;/tt&gt;# However, if you remove everything, the rebase will be aborted.&lt;tt&gt;
&lt;/tt&gt;#&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;The line 1 commit contained changes to &lt;code&gt;.gitinore&lt;/code&gt; and line 12 was a &lt;code&gt;.gitinore&lt;/code&gt; for a &lt;code&gt;doc&lt;/code&gt; directory where I save HTML edits of articles. I deleted line 12 and changed line 1 to an edit point so that I could recall the commit and do all &lt;code&gt;.gitinore&lt;/code&gt; changes at once. I deleted lines 2-4 because I wanted to add Rails 2.2.2 and take care of TZInfo as part of the Cached Externals setup, something that I'd redo after the plugin was added after line 14. I deleted line 24 because I decided not to continue to include the &lt;code&gt;action_mailer_tls&lt;/code&gt; plugin in my Cached Externals setup.  I was on the fence about adding it in the first place; the plugin is so small that it didn't provide a performance benefit.  My reason for adding it was simply documentation to keep track of its revision information but I have that recorded elsewhere. Leaving it out meant one less consideration the next time I updated Mephisto.
&lt;/p&gt;
&lt;p&gt;After saving the file there was an immediate conflict on the first commit:
&lt;pre&gt;
warning: too many files, skipping inexact rename detection
Auto-merged .gitignore
CONFLICT (content): Merge conflict in .gitignore
Automatic cherry-pick failed.  After resolving the conflicts,
mark the corrected paths with 'git add ', and
run 'git rebase --continue'
Could not apply f2b123a... Changed to track changes for my blog.
&lt;/pre&gt;
&lt;h3&gt;A new .gitignore&lt;/h3&gt;
&lt;p&gt;Here's what &lt;code&gt;.gitinore&lt;/code&gt; contained:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;.DS_Store&lt;tt&gt;
&lt;/tt&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD:.gitignore&lt;tt&gt;
&lt;/tt&gt;.rake_tasks&lt;tt&gt;
&lt;/tt&gt;Capfile&lt;tt&gt;
&lt;/tt&gt;config/database.yml&lt;tt&gt;
&lt;/tt&gt;config/deploy.rb&lt;tt&gt;
&lt;/tt&gt;config/initializers/session_store.rb&lt;tt&gt;
&lt;/tt&gt;db/*.sqlite3&lt;tt&gt;
&lt;/tt&gt;log/*.log&lt;tt&gt;
&lt;/tt&gt;public/assets&lt;tt&gt;
&lt;/tt&gt;public/cache&lt;tt&gt;
&lt;/tt&gt;public/plugin_assets&lt;tt&gt;
&lt;/tt&gt;tmp&lt;tt&gt;
&lt;/tt&gt;themes&lt;tt&gt;
&lt;/tt&gt;*~&lt;tt&gt;
&lt;/tt&gt;=======&lt;tt&gt;
&lt;/tt&gt;config/database.yml&lt;tt&gt;
&lt;/tt&gt;log&lt;tt&gt;
&lt;/tt&gt;tmp&lt;tt&gt;
&lt;/tt&gt;public/assets&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; f2b123a... Changed to track changes for my blog.:.gitignore&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;I covered setting up the &lt;code&gt;.gitinore&lt;/code&gt; in &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/1/gitting-started-with-mephisto&quot;&gt;gitting Started with Mephisto&lt;/a&gt;&lt;/em&gt; but there were some new considerations with Mephisto's 0.8.1 &lt;code&gt;.gitinore&lt;/code&gt;.  Here were the additional things I considered when deciding how to resolve the conflict:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;config/initializers/session_store.rb&lt;/code&gt; is a file that Mephisto now generates to avoid the weakness with using a common session secret.  Something I had worked around in my original post by generating my own key.  The file is generated as part of the bootstrap process or it can be created independently with a new &lt;code&gt;db:bootstrap:session&lt;/code&gt; or &lt;code&gt;config/initializers/session_store.rb&lt;/code&gt; rake task.  It's obvious the file doesn't belong in Mephisto's project repository on github but I decided to leave it in my private git repository of Mephisto to make deployment easy.
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;db/*.sqlite3&lt;/code&gt; is a new ignore.  I'm not using SQLite but I decided I'd ignore these files in case they get generated automatically as part of running the test suite.
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;public/assets&lt;/code&gt; was something that I had already added. &lt;code&gt;public/cache&lt;/code&gt; and &lt;code&gt;public/plugin_assets&lt;/code&gt; are automatically generated by Mephisto and not part of the code base so I decided I'd also make them part of my &lt;code&gt;.gitignore&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;*~&lt;/code&gt; is for Emacs backup files.  I'm not using Emacs so I didn't bother with adding it.
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;log/*.log&lt;/code&gt; is a more specific ignore for log files. I don't see much significance but went with the new method to keep my implementation in sync if something important happens to get added to the &lt;code&gt;log&lt;/code&gt; directory so I decided to accept this change. 
&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;doc&lt;/code&gt; directory is something I'd originally added to &lt;code&gt;.gitinore&lt;/code&gt; as a separate commit but deleted the line in interactive mode so I could add it after this first &lt;code&gt;.gitignore&lt;/code&gt; commit. Since there was a conflict I decided I'd add it as part of this conflict resolution. 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So that lead to this version of &lt;code&gt;.gitignore&lt;/code&gt;:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;.DS_Store&lt;tt&gt;
&lt;/tt&gt;db/*.sqlite3&lt;tt&gt;
&lt;/tt&gt;log/*.log&lt;tt&gt;
&lt;/tt&gt;public/assets&lt;tt&gt;
&lt;/tt&gt;public/cache&lt;tt&gt;
&lt;/tt&gt;public/plugin_assets&lt;tt&gt;
&lt;/tt&gt;tmp&lt;tt&gt;
&lt;/tt&gt;config/database.yml&lt;tt&gt;
&lt;/tt&gt;doc&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;Resolving Conflicts&lt;/h3&gt;
&lt;p&gt;Adding the resolution and continuing is the standard thing to do after resolving a conflict:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ git add .gitignore
[mac]$ git rebase --continue
warning: too many files, skipping inexact rename detection
Auto-merged config/environment.rb
CONFLICT (content): Merge conflict in config/environment.rb
Automatic cherry-pick failed.  After resolving the conflicts,
mark the corrected paths with 'git add ', and
run 'git rebase --continue'
Could not apply dcddd47... Changed secret from distributed version.
&lt;/pre&gt;
&lt;p&gt;I wasn't surprised by this &lt;code&gt;config/environment.rb&lt;/code&gt; problem.  I knew I'd updated the file to create my own session key and had just discovered there was a fix for this in Mephisto with the addition of  &lt;code&gt;config/initializers/session_store.rb&lt;/code&gt; to &lt;code&gt;.gitignore&lt;/code&gt;. So now I needed to delete the following lines (my original change):
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;57&lt;tt&gt;
&lt;/tt&gt;58&lt;tt&gt;
&lt;/tt&gt;59&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;60&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;61&lt;tt&gt;
&lt;/tt&gt;62&lt;tt&gt;
&lt;/tt&gt;63&lt;tt&gt;
&lt;/tt&gt;64&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; &lt;span class=&quot;co&quot;&gt;HEAD&lt;/span&gt;&lt;span class=&quot;sy&quot;&gt;:config&lt;/span&gt;/environment.rb&lt;tt&gt;
&lt;/tt&gt;=======&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;# Use the database for sessions instead of the file system&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;# (create the session table with 'rake create_sessions_table')&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;# config.action_controller.session_store = :active_record_store&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  config.action_controller.session = { &lt;span class=&quot;sy&quot;&gt;:session_key&lt;/span&gt; =&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;_mephisto_session&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, ....&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt;&amp;gt;  &amp;gt;&amp;gt;&amp;gt; dcddd47... &lt;span class=&quot;co&quot;&gt;Changed&lt;/span&gt; secret from distributed version.&lt;span class=&quot;sy&quot;&gt;:config&lt;/span&gt;/environment.rb&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;And move on:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ git add config/environment.rb
[mac]$ git rebase --continue
warning: too many files, skipping inexact rename detection
Auto-merged config/initializers/custom.rb
CONFLICT (content): Merge conflict in config/initializers/custom.rb
Automatic cherry-pick failed.  After resolving the conflicts,
mark the corrected paths with 'git add ', and
run 'git rebase --continue'
Could not apply 0c1579c... Disabled multi-site support.
&lt;/pre&gt;
&lt;p&gt;This &lt;code&gt;custom.rb&lt;/code&gt; conflict occurred because I had disabled multisite support near another change that went into 0.8.1:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; &lt;span class=&quot;co&quot;&gt;HEAD&lt;/span&gt;&lt;span class=&quot;sy&quot;&gt;:config&lt;/span&gt;/initializers/custom.rb&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;# TODO - We need to wrap these options in Dispatcher.to_prepare, because&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;# the underlying Site, etc., objects will be unloaded on each request in&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;# development mode, and the preferences will be reset.  This is a flaw&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;# in how we handle configuration, and to_prepare is just a workaround.&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;co&quot;&gt;Dispatcher&lt;/span&gt;.to_prepare &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;c&quot;&gt;# Turn this on to get detailed cache sweeper logging in production mode&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;c&quot;&gt;# Site.cache_sweeper_tracing = true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=======&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;c&quot;&gt;# Enable if you want to host multiple sites on this app&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;c&quot;&gt;# Site.multi_sites_enabled = true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Disabled&lt;/span&gt; multi-site support.&lt;span class=&quot;sy&quot;&gt;:config&lt;/span&gt;/initializers/custom.rb&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;c&quot;&gt;# Enable if you want to host multiple sites on this app&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;co&quot;&gt;Site&lt;/span&gt;.multi_sites_enabled = &lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Last spring Mephisto was changed to enable multisite support by default but most people will probably encounter it for the first time in 0.8.1.  I discussed why I disabled it in &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/1/gitting-started-with-mephisto&quot;&gt;gitting Started with Mephisto&lt;/a&gt;&lt;/em&gt;.  Hopefully it's working fine now (if it wasn't before) but I still don't need multisite support and decided to keep it disabled so I deleted lines 8,16-19 and commented out line 22:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;22&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# Site.multi_sites_enabled = true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
 
&lt;/p&gt;
&lt;p&gt;I do have a side note here. If you decide to leave &lt;code&gt;Site.multi_sites_enabled&lt;/code&gt; set to &lt;code&gt;true&lt;/code&gt; and you're using Phusion Passenger then there is one consideration that I've become aware of: Enabling multisite support causes your cache files to be placed under a cache directory (i.e. &lt;code&gt;public/cache/site.com&lt;/code&gt;) instead of in public root.  If you want Passenger to find the cached files may may need mod_rewrite modifications.  Check out Paul Gross's  &lt;em&gt;&lt;a href=&quot;http://pgrs.net/2008/12/22/mephisto-with-phusion-passenger&quot;&gt;Mephisto with Phusion Passenger&lt;/a&gt;&lt;/em&gt; post for details.  Oh well, that's not an issue for me so on to the next stop:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ git add config/initializers/custom.rb
[mac]$ git rebase --continue
Could not apply 0c1579c... Disabled multi-site support.
Robs-Laptop-2:mephisto Rob$ git add config/initializers/custom.rb
Robs-Laptop-2:mephisto Rob$ git rebase --continue
Created commit 47398d9: Disabled multi-site support.
 1 files changed, 1 insertions(+), 1 deletions(-)
Stopped at 5c0bdb4... Added Cached Externals plugin.
You can amend the commit now, with

	git commit --amend

Once you are satisfied with your changes, run

	git rebase --continue

&lt;/pre&gt;
&lt;h3&gt;Updating Cached Externals&lt;/h3&gt;
&lt;p&gt;Finally, I hit my first planned stop after the plugin was added.  At this point I needed to complete the Cached Externals setup, which was pretty much a subset of what I had done in my &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/3/cached-externals&quot;&gt;Cached Externals&lt;/a&gt;&lt;/em&gt; post.
&lt;/p&gt;
&lt;p&gt;Although TZInfo was installed in &lt;code&gt;vendor/gems&lt;/code&gt; in my copy of Mephisto, as I mentioned above it'll be gone in the next stable release. Vendorized versions of TZInfo won't be loaded, at least for now, because Rails (2.1.2+) loads its own TZInfo version that is unfortunately just a subset without support for &lt;code&gt;TimezoneProxy&lt;/code&gt; which is required by Mephisto when you access Admin/Settings.  Since it can't be vendorized I verified that 3.12 was installed on my production server and no longer plan to cache it. I was tempted to remove the gem from my Mephisto implementation but decided to live with it being there for now and wait for the next stable Mephisto release.
&lt;/p&gt;
&lt;p&gt;I did want to cache the new RSpec versions so the current vendor copies needed to be removed:
&lt;pre&gt;
[mac]$ rm -rf vendor/plugins/rspec
[mac]$ rm -rf vendor/plugins/rspec_on_rails
&lt;/pre&gt;
&lt;p&gt;There was no need to freeze Rails 2.2.2, delete it and then include it as a Cached External.  Just making it part of &lt;code&gt;config/externals.yml&lt;/code&gt; would effectively freeze it into vendor.  So, using  information from the 2.2.2 tag on github and what I'd found after the pull, here was my new &lt;code&gt;config/externals.yml&lt;/code&gt;:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;vendor/rails:  # v2.2.2&lt;tt&gt;
&lt;/tt&gt;  :type: git&lt;tt&gt;
&lt;/tt&gt;  # DH old git checkout (1.4.4.4) doesn't support -q&lt;tt&gt;
&lt;/tt&gt;  :scm_verbose: true&lt;tt&gt;
&lt;/tt&gt;  :repository: git://github.com/rails/rails.git&lt;tt&gt;
&lt;/tt&gt;  :revision: ff561370739eb809d1d006ea842cd2b1e43f6950&lt;tt&gt;
&lt;/tt&gt;vendor/plugins/rspec: # 12-4-2008&lt;tt&gt;
&lt;/tt&gt;  :type: git&lt;tt&gt;
&lt;/tt&gt;  # DH old git checkout (1.4.4.4) doesn't support -q&lt;tt&gt;
&lt;/tt&gt;  :scm_verbose: true&lt;tt&gt;
&lt;/tt&gt;  :repository: git://github.com/dchelimsky/rspec.git&lt;tt&gt;
&lt;/tt&gt;  :revision: f85a53bb54b13e6461c8ffbded4933b90e40a86c&lt;tt&gt;
&lt;/tt&gt;vendor/plugins/rspec_on_rails: # 12-4-2008&lt;tt&gt;
&lt;/tt&gt;  :type: git&lt;tt&gt;
&lt;/tt&gt;  # DH old git checkout (1.4.4.4) doesn't support -q&lt;tt&gt;
&lt;/tt&gt;  :scm_verbose: true&lt;tt&gt;
&lt;/tt&gt;  :repository: git://github.com/dchelimsky/rspec-rails.git&lt;tt&gt;
&lt;/tt&gt;  :revision: f96eb3fd4d95eb400e87b4f1cf8e6a279f1dbcbd&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;With that file in place it was time to use the configuration to load up the cache and create the symbolic links:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ cap local externals:setup
&lt;/pre&gt;
&lt;p&gt;At this point I did a little verification using &lt;code&gt;git-status&lt;/code&gt; and then committed my changes:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ git add config/externals.yml
[mac]$ git commit config/externals.yml -m &quot;Created externals YAML file.&quot;
[mac]$ git add .
[mac]$ git commit -a -m &quot;Cached Externals: rails, rspec and rspec_rails.&quot;
[mac]$ git rebase --continue
Successfully rebased and updated refs/heads/robseaman.
&lt;/pre&gt;
&lt;h3&gt;Common 0.8.1 Update Stuff&lt;/h3&gt;
&lt;p&gt;Great, no more conflicts and that completed the rebasing. Just a couple of 0.8.1 update related tasks remained: 
&lt;/p&gt;
&lt;pre&gt;
[mac]$ rake config/initializers/session_store.rb
[mac]$ git add config/initializers/session_store.rb
[mac]$ git commit config/initializers/session_store.rb -m \
&gt; &quot;Created session key for this Mephisto site.&quot;
[mac]$ rake db:migrate
[mac]$ git add db/schema.rb
[mac]$ git commit db/schema.rb -m &quot;Ran migrations for Mephisto update.&quot;
&lt;/pre&gt;
&lt;p&gt;To work with the new security scheme &lt;code&gt;config/initializers/session_store.rb&lt;/code&gt; needed to be created and since I decided to put it in my git repository it also needed to be committed.  0.8.1 had a new migration so running migrations and checking in the updated schema was also required.
&lt;/p&gt;
&lt;h3&gt;New Theme Locations&lt;/h3&gt;
&lt;p&gt;I figured I was done but the first time I ran &lt;code&gt;script/server&lt;/code&gt; I got a 500 error on my first page load and found this entry in the log:
&lt;/p&gt;
&lt;pre&gt;
MissingThemesError (No themes found in 
'/Users/Rob/work/mephisto/themes/development/site-1/simpla'.  
This must be set correctly in the site settings. You may be 
able to fix this by running 'rake db:bootstrap:copy_default_theme'):
&lt;/pre&gt;
&lt;p&gt;After looking around a little I discovered the location of themes for non-production environments was changed to reflect the environment.  If you'd rather keep the code that way you could just run in production mode by making sure you have usable production database settings in the &lt;code&gt;database.yml&lt;/code&gt; and running &lt;code&gt;script/server -e production&lt;/code&gt; from the local environment, or you could keep a separate copy of your production theme in themes/development.  I didn't like those solutions, I wanted to run my production theme(s) in the development environment and I didn't want to deal with making sure my development themes were always copied over to production.  So, instead of living with the change, I chose to modify the line in Mephisto that sets the &lt;code&gt;THEME_ROOT&lt;/code&gt; location in &lt;code&gt;lib/mephisto/theme_root.rb&lt;/code&gt; from:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;    (&lt;span class=&quot;co&quot;&gt;Rails&lt;/span&gt;.env.production? ? &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;themes&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; : &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;themes/&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;co&quot;&gt;Rails&lt;/span&gt;.env&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;to:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;    (&lt;span class=&quot;co&quot;&gt;Rails&lt;/span&gt;.env.test? ? &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;themes/&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;co&quot;&gt;Rails&lt;/span&gt;.env&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; : &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;themes&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Then I checked in the change and did some verification:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ git add lib/mephisto/theme_root.rb
[mac]$ git commit lib/mephisto/theme_root.rb -m \
&gt; &quot;Made themes/ the default themes dir for all except test.&quot;
[mac]$ script/server
&lt;/pre&gt;
&lt;h3&gt;Deploying to Production&lt;/h3&gt;
&lt;p&gt;Once I was satisfied that things were working it was time to deploy to production.  &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/1/deploying-mephisto-with-capistrano-to-dreamhost&quot;&gt;Deploying Mephisto with Capistrano to DreamHost&lt;/a&gt;&lt;/em&gt; describes my deployment setup, but I'm doing deployments in a standard way:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ cap deploy:migrations
&lt;/pre&gt;
&lt;p&gt;In the end the update wasn't too bad.  The upgrade complexities associated with Cached Externals wouldn't have occurred in a normal project, they only existed because I decided to use Cached Externals on someone else's project in my custom branch.  Even at that once I figured out what had changed the update went pretty quickly.   
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.robseaman.com/">
    <author>
      <name>Rob</name>
    </author>
    <id>tag:blog.robseaman.com,2009-01-14:17</id>
    <published>2009-01-14T06:03:00Z</published>
    <updated>2009-01-15T16:55:14Z</updated>
    <category term="Website Setup"/>
    <category term="1.8.7"/>
    <category term="actionmailer"/>
    <category term="gmail"/>
    <category term="smtp"/>
    <category term="ssl"/>
    <category term="tls"/>
    <link href="http://blog.robseaman.com/2009/1/14/updating-gmail-ssl-smtp-support-for-ruby-1-8-7" rel="alternate" type="text/html"/>
    <title>Updating Gmail SSL SMTP Support for Ruby 1.8.7</title>
<summary type="html">&lt;p&gt;In &lt;em&gt;&lt;a href=&quot;http://localhost:3000/2008/12/4/adding-gmail-ssl-smtp-support-to-rails&quot;&gt;Adding Gmail SSL SMTP Support to Rails&lt;/a&gt;&lt;/em&gt; I described the use of a simple Rails plugin to provide SSL SMTP support.  Today I upgraded to a new version of Mephisto and while testing it in production I discovered that I couldn't send emails.  It turns out that it had nothing to do with the Mephisto upgrade; my DreamHost server had been updated to Ruby 1.8.7 and the &lt;a href=&quot;http://github.com/caritos/action_mailer_tls/tree/master&quot;&gt;action_mailer_tls&lt;/a&gt; plugin I was using wasn't compatible.  Oh well, I guess I deserved that surprise for using shared hosting and adding a monkey patch plugin.  This post describes a simple fix.</summary><content type="html">
            &lt;p&gt;In &lt;em&gt;&lt;a href=&quot;http://localhost:3000/2008/12/4/adding-gmail-ssl-smtp-support-to-rails&quot;&gt;Adding Gmail SSL SMTP Support to Rails&lt;/a&gt;&lt;/em&gt; I described the use of a simple Rails plugin to provide SSL SMTP support.  Today I upgraded to a new version of Mephisto and while testing it in production I discovered that I couldn't send emails.  It turns out that it had nothing to do with the Mephisto upgrade; my DreamHost server had been updated to Ruby 1.8.7 and the &lt;a href=&quot;http://github.com/caritos/action_mailer_tls/tree/master&quot;&gt;action_mailer_tls&lt;/a&gt; plugin I was using wasn't compatible.  Oh well, I guess I deserved that surprise for using shared hosting and adding a monkey patch plugin.  This post describes a simple fix. 

&lt;/p&gt;
&lt;p&gt;The problem occurred because the 1.8.7 version of Net::SMTP changed its &lt;em&gt;private&lt;/em&gt; &lt;code&gt;check_auth_args&lt;/code&gt; method.  Fortunately, I had just removed the &lt;a href=&quot;http://github.com/caritos/action_mailer_tls/tree/master&quot;&gt;action_mailer_tls&lt;/a&gt; plugin from Cached Externals so I was able to do a quick code fix in the plugins directory.  Here's the change I made to &lt;code&gt;vendor/plugins/action_mailer_tls/lib/smtp_tls.rb&lt;/code&gt;.
&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;Net::SMTP.class_eval#do_start&lt;/code&gt; replace:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;8&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;check_auth_args user, secret, authtype &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; user &lt;span class=&quot;r&quot;&gt;or&lt;/span&gt; secret&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;with:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;co&quot;&gt;RUBY_VERSION&lt;/span&gt;.match(&lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\d&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;+)&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\d&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;+)&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\d&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;+)&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;gv&quot;&gt;$1&lt;/span&gt;.to_i &amp;lt;= &lt;span class=&quot;i&quot;&gt;1&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class=&quot;gv&quot;&gt;$2&lt;/span&gt;.to_i &amp;lt;= &lt;span class=&quot;i&quot;&gt;8&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class=&quot;gv&quot;&gt;$3&lt;/span&gt;.to_i &amp;lt;= &lt;span class=&quot;i&quot;&gt;6&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  check_auth_args user, secret, authtype &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; user &lt;span class=&quot;r&quot;&gt;or&lt;/span&gt; secret&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;elsif&lt;/span&gt; user &lt;span class=&quot;r&quot;&gt;or&lt;/span&gt; secret&lt;tt&gt;
&lt;/tt&gt;  check_auth_method(authtype || &lt;span class=&quot;co&quot;&gt;DEFAULT_AUTH_TYPE&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  check_auth_args user, secret&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Check it in:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ git add vendor/plugins/action_mailer_tls/lib/smtp_tls.rb
[mac]$ git commit -a -m &quot;Fixed auth check method for 1.8.7 compatibility.&quot;
&lt;/pre&gt;
&lt;p&gt;And deploy it:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ cap deploy
&lt;/pre&gt;
&lt;p&gt;If you're starting from scratch and want something that already works I did notice there are other similar solutions with 1.8.7 support available on the Internet.  Simplificator's &lt;a href=&quot;http://github.com/simplificator/tls-support/tree/master&quot;&gt;tls-support&lt;/a&gt; gem on github is one example.
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.robseaman.com/">
    <author>
      <name>Rob</name>
    </author>
    <id>tag:blog.robseaman.com,2008-12-21:15</id>
    <published>2008-12-21T06:53:00Z</published>
    <updated>2008-12-21T06:54:45Z</updated>
    <category term="Ruby"/>
    <category term="jruby"/>
    <category term="multiruby"/>
    <link href="http://blog.robseaman.com/2008/12/21/adding-jruby-to-multiruby-versions" rel="alternate" type="text/html"/>
    <title>Adding JRuby to multiruby Versions</title>
<summary type="html">&lt;p&gt;In &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/20/switching-between-ruby-1-8-1-9-with-multiruby&quot;&gt;Switching Between Ruby 1.8 &amp; 1.9 with multiruby&lt;/a&gt;&lt;/em&gt; I covered setting up and using Ruby 1.8 and 1.9 versions in &lt;code&gt;&lt;a href=&quot;http://blog.zenspider.com/zentest/2007/12/&quot;&gt;multiruby&lt;/a&gt;&lt;/code&gt;.  This post describes adding &lt;a href=&quot;http://jruby.codehaus.org/&quot;&gt;JRuby&lt;/a&gt; to the list of &lt;code&gt;multiruby&lt;/code&gt; versions in Mac OS X.</summary><content type="html">
            &lt;p&gt;In &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/20/switching-between-ruby-1-8-1-9-with-multiruby&quot;&gt;Switching Between Ruby 1.8 &amp; 1.9 with multiruby&lt;/a&gt;&lt;/em&gt; I covered setting up and using Ruby 1.8 and 1.9 versions in &lt;code&gt;&lt;a href=&quot;http://blog.zenspider.com/zentest/2007/12/&quot;&gt;multiruby&lt;/a&gt;&lt;/code&gt;.  This post describes adding &lt;a href=&quot;http://jruby.codehaus.org/&quot;&gt;JRuby&lt;/a&gt; to the list of &lt;code&gt;multiruby&lt;/code&gt; versions in Mac OS X.

&lt;/p&gt;
&lt;h3&gt;Install JRuby in &lt;code&gt;~/.multiruby&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;multiruby&lt;/code&gt; doesn't have built-in support for JRuby but it works by tracking its installations in the &lt;code&gt;~/.multiruby/versions&lt;/code&gt; and &lt;code&gt;~/.multiruby/install&lt;/code&gt; directories.  Setting up the directory structure to look like a &lt;a href=&quot;http://en.wikipedia.org/wiki/Ruby_MRI&quot;&gt;MRI&lt;/a&gt; build from a tarball does most of what's necessary: 
&lt;pre&gt;
$ curl -O http://dist.codehaus.org/jruby/1.1.6/jruby-bin-1.1.6.tar.gz
$ tar -C ~/.multiruby/install -zxf jruby-bin-1.1.6.tar.gz
$ mv jruby-bin-1.1.6.tar.gz ~/.multiruby/versions/jruby-1.1.6.tar.gz
&lt;/pre&gt;
&lt;p&gt;That will provide access to the &lt;code&gt;jruby&lt;/code&gt; command but &lt;code&gt;multiruby&lt;/code&gt; only knows about using &lt;code&gt;ruby&lt;/code&gt; so we'll need to fool it with a symbolic link:  
&lt;/p&gt;
&lt;pre&gt;
$ ln -fs ~/.multiruby/install/jruby-1.1.6/bin/jruby \
&gt; ~/.multiruby/install/jruby-1.1.6/bin/ruby
&lt;/pre&gt;
&lt;p&gt;Now verify that it works:
&lt;/p&gt;
&lt;pre&gt;
$ multiruby -e &quot;p 1+1&quot;
&lt;/pre&gt;
&lt;p&gt;Although that installation was from a binary distribution it wouldn't be much more difficult to do it from source.  You just need to make sure the base names in the &lt;code&gt;versions&lt;/code&gt; and &lt;code&gt;install&lt;/code&gt; directories match when you're done.
&lt;/p&gt;
&lt;h3&gt;Adding JRuby to the PATH&lt;/h3&gt;
&lt;p&gt;In &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/20/switching-between-ruby-1-8-1-9-with-multiruby&quot;&gt;Switching Between Ruby 1.8 &amp; 1.9 with multiruby&lt;/a&gt;&lt;/em&gt; I created aliases to set the path in the &lt;code&gt;.bash_login&lt;/code&gt; to selected version of Ruby:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;# switch between ruby verisions&lt;tt&gt;
&lt;/tt&gt;export ORIGPATH=$PATH&lt;tt&gt;
&lt;/tt&gt;alias mr186p287='export PATH=~/.multiruby/install/1.8.6-p287/bin:$ORIGPATH'&lt;tt&gt;
&lt;/tt&gt;alias mr187p72='export PATH=~/.multiruby/install/1.8.7-p72/bin:$ORIGPATH'&lt;tt&gt;
&lt;/tt&gt;alias mr191pre2='export PATH=~/.multiruby/install/1.9.1-preview2/bin:$ORIGPATH'&lt;tt&gt;
&lt;/tt&gt;alias mroff='export PATH=$ORIGPATH'&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;If we wanted to execute JRuby with the &lt;code&gt;ruby&lt;/code&gt; command then we could add an alias for JRuby too but since JRuby has its own command names (&lt;code&gt;jruby&lt;/code&gt;, &lt;code&gt;jgem&lt;/code&gt;,&lt;code&gt;jirb&lt;/code&gt;) we can allow them to always be available if we just make sure that the &lt;code&gt;ruby&lt;/code&gt; symlink we created doesn't come before any real &lt;code&gt;ruby&lt;/code&gt; commands by adding it to our path:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;# manage ruby verisions&lt;tt&gt;
&lt;/tt&gt;export PATH=$PATH~/.multiruby/install/jruby-1.1.6/bin&lt;tt&gt;
&lt;/tt&gt;export ORIGPATH=$PATH&lt;tt&gt;
&lt;/tt&gt;...&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;BTW: If you want an alias that you can execute to make the &lt;code&gt;ruby&lt;/code&gt; command executes JRuby:
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;alias mrjruby='export PATH=~/.multiruby/install/jruby-1.1.6/bin:$ORIGPATH'&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;then you'll probably also want to setup symlinks for &lt;code&gt;gem -&gt; jgem&lt;/code&gt; and &lt;code&gt;irb -&gt; jirb&lt;/code&gt;. That setup could be done instead of or in addition to the PATH change on line 23 above.  I didn't bother with the alias or the additional symlinks; to me using the JRuby commands in their native jXXX format seems like the way to go.
&lt;/p&gt;
&lt;p&gt;
That's it, JRuby is now a first class citizen in &lt;code&gt;multiruby&lt;/code&gt; and &lt;code&gt;multiruby_setup&lt;/code&gt; and &lt;code&gt;jruby&lt;/code&gt;, &lt;code&gt;jgem&lt;/code&gt;, and &lt;code&gt;jirb&lt;/code&gt; are all available.
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.robseaman.com/">
    <author>
      <name>Rob</name>
    </author>
    <id>tag:blog.robseaman.com,2008-12-20:14</id>
    <published>2008-12-20T02:06:00Z</published>
    <updated>2008-12-21T06:52:59Z</updated>
    <category term="Ruby"/>
    <category term="1.8.6"/>
    <category term="1.8.7"/>
    <category term="1.9.1-preview2"/>
    <category term="leopard"/>
    <category term="multiruby"/>
    <link href="http://blog.robseaman.com/2008/12/20/switching-between-ruby-1-8-1-9-with-multiruby" rel="alternate" type="text/html"/>
    <title>Switching Between Ruby 1.8 &amp; 1.9 with multiruby</title>
<summary type="html">&lt;p&gt;I just recently built and installed three different Ruby versions (see &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/10/from-ruby-1-8-6-to-1-87-and-back-again-on-leopard&quot;&gt;Installing Ruby 1.8.6, 1.8.7 and 1.9 on Leopard&lt;/a&gt;&lt;/em&gt;).  Following that I wanted to do some benchmark testing between 1.8 and 1.9 on a separate project so I began to use &lt;a href=&quot;http://www.zenspider.com/ZSS/Products/ZenTest/&quot;&gt;ZenTest&lt;/a&gt;'s &lt;code&gt;&lt;a href=&quot;http://blog.zenspider.com/zentest/2007/12/&quot;&gt;multiruby&lt;/a&gt;&lt;/code&gt;.  It worked great for the benchmarking and I started to think about how to use &lt;code&gt;multiruby&lt;/code&gt; as a way to manage and switch between Ruby installations. As I started looking into it I came across Dr Nic's &lt;em&gt;&lt;a href=&quot;http://drnicwilliams.com/2008/12/11/future-proofing-your-ruby-code/&quot;&gt;Future proofing your Ruby code. Ruby 1.9.1 is coming&lt;/a&gt;&lt;/em&gt; post, which turned on the rest of the lights for me.  The Dr Nic post does a nice job of describing how to use &lt;code&gt;multiruby&lt;/code&gt; including setting up specific Ruby versions, adding gem support and using it with &lt;a href=&quot;http://github.com/drnic/sake-tasks/tree/master&quot;&gt;sake tasks&lt;/a&gt;. I'll cover some of the same setup and usage information so that this post stands alone but I won't repeat it all so I recommend you read &lt;a href=&quot;http://drnicwilliams.com/2008/12/11/future-proofing-your-ruby-code/&quot;&gt;Dr Nic's post&lt;/a&gt;.  In addition I'll provide information about how to overcome a RubyGems installation issue that I encountered and how to use the &lt;code&gt;multiruby&lt;/code&gt; Ruby installations as a way to dynamically switch between Ruby versions. I'll also discuss how the static build and install from source approach used in &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/10/from-ruby-1-8-6-to-1-87-and-back-again-on-leopard&quot;&gt;Installing Ruby 1.8.6, 1.8.7 and 1.9 on Leopard&lt;/a&gt;&lt;/em&gt; could be modified to be provide a non-&lt;code&gt;multiruby&lt;/code&gt; dependent way to do Ruby version switching. At the end of the post I'll mention using symlinks as an alternative and how that approach could be used with &lt;code&gt;multiruby&lt;/code&gt;.</summary><content type="html">
            &lt;p&gt;I just recently built and installed three different Ruby versions (see &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/10/from-ruby-1-8-6-to-1-87-and-back-again-on-leopard&quot;&gt;Installing Ruby 1.8.6, 1.8.7 and 1.9 on Leopard&lt;/a&gt;&lt;/em&gt;).  Following that I wanted to do some benchmark testing between 1.8 and 1.9 on a separate project so I began to use &lt;a href=&quot;http://www.zenspider.com/ZSS/Products/ZenTest/&quot;&gt;ZenTest&lt;/a&gt;'s &lt;code&gt;&lt;a href=&quot;http://blog.zenspider.com/zentest/2007/12/&quot;&gt;multiruby&lt;/a&gt;&lt;/code&gt;.  It worked great for the benchmarking and I started to think about how to use &lt;code&gt;multiruby&lt;/code&gt; as a way to manage and switch between Ruby installations. As I started looking into it I came across Dr Nic's &lt;em&gt;&lt;a href=&quot;http://drnicwilliams.com/2008/12/11/future-proofing-your-ruby-code/&quot;&gt;Future proofing your Ruby code. Ruby 1.9.1 is coming&lt;/a&gt;&lt;/em&gt; post, which turned on the rest of the lights for me.  The Dr Nic post does a nice job of describing how to use &lt;code&gt;multiruby&lt;/code&gt; including setting up specific Ruby versions, adding gem support and using it with &lt;a href=&quot;http://github.com/drnic/sake-tasks/tree/master&quot;&gt;sake tasks&lt;/a&gt;. I'll cover some of the same setup and usage information so that this post stands alone but I won't repeat it all so I recommend you read &lt;a href=&quot;http://drnicwilliams.com/2008/12/11/future-proofing-your-ruby-code/&quot;&gt;Dr Nic's post&lt;/a&gt;.  In addition I'll provide information about how to overcome a RubyGems installation issue that I encountered and how to use the &lt;code&gt;multiruby&lt;/code&gt; Ruby installations as a way to dynamically switch between Ruby versions. I'll also discuss how the static build and install from source approach used in &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/10/from-ruby-1-8-6-to-1-87-and-back-again-on-leopard&quot;&gt;Installing Ruby 1.8.6, 1.8.7 and 1.9 on Leopard&lt;/a&gt;&lt;/em&gt; could be modified to be provide a non-&lt;code&gt;multiruby&lt;/code&gt; dependent way to do Ruby version switching. At the end of the post I'll mention using symlinks as an alternative and how that approach could be used with &lt;code&gt;multiruby&lt;/code&gt;.

&lt;/p&gt;
&lt;h3&gt;Set-Up&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;multiruby&lt;/code&gt; is part of the popular ZenTest gem so it's likely you already have it.  If you do have it but your revision is older than 3.11.0 you should update it, if it's not installed then it's available on rubyforge:
&lt;/p&gt;
&lt;pre&gt;
$ sudo gem install ZenTest
&lt;/pre&gt;
&lt;p&gt;When &lt;code&gt;multiruby&lt;/code&gt; is run for the first time it sets up a hidden directory structure for Ruby versions in user home ( &lt;code&gt;~/.multiruby&lt;/code&gt;) and downloads and installs the latest 1.8 and 1.9 releases of Ruby:
&lt;/p&gt;
&lt;pre&gt;
$ multiruby -e &quot;p 1+1&quot;
  ...
  Put other ruby tarballs in ~/.multiruby/versions to use them.
  ...
VERSION = 1.8.7-p72
CMD     = ~/.multiruby/install/1.8.7-p72/bin/ruby -e p 1+1

/Users/Rob/.multiruby/install/1.8.7-p72/bin/ruby: no such file to load -- ubygems 
      (LoadError)

RESULT = 256

VERSION = 1.9.0-5
CMD     = ~/.multiruby/install/1.9.0-5/bin/ruby -e p 1+1

2

RESULT = 0

TOTAL RESULT = 1 failures out of 2

Passed: 1.9.0-5
Failed: 1.8.7-p72
&lt;/pre&gt;
&lt;p&gt;I didn't show all of the output but left in the &quot;&lt;code&gt;Put other ruby tarballs in ~/.multiruby/versions&lt;/code&gt;&quot; line because it's worthy of note.  If the installation worked then you'll see &quot;&lt;code&gt;RESULT = 0&lt;/code&gt;&quot; for each of the Ruby versions but in my case I had a &quot;&lt;code&gt;no such file to load -- ubygems&lt;/code&gt;&quot; error on the 1.8.7 version.  This is a result of a conflict with the current Ruby installation.  If you get the same error just temporarily unset the &lt;code&gt;RUBYOPT&lt;/code&gt; environment variable (&lt;code&gt;$ unset RUBYOPT &lt;/code&gt;) and continue following these instructions. Updating RubyGems (coming right up) will correct the problem.
&lt;/p&gt;
&lt;p&gt;&lt;code&gt;multiruby_setup&lt;/code&gt; is used to manage the installed ruby versions. The next step is to use the command to install the latest RubyGems update:
&lt;pre&gt;
$ multiruby_setup update:rubygems
&lt;/pre&gt;
&lt;h3&gt;Managing Installations&lt;/h3&gt;
&lt;p&gt;Typing &quot;&lt;code&gt;$ multiruby_setup&lt;/code&gt;&quot; without any arguments will provide you with a usage list.  One of the first things you'll want to know is how to control which versions of Ruby you use. The automatic version detection when &lt;code&gt;multiruby_setup&lt;/code&gt; is run the first time makes it easy to get started but in the case of 1.9 that means v1.9.0-5 is installed and it's more likely you'll want the latest 1.9.1 preview release.  Dr Nic showed installing using subversion (&lt;code&gt;$ multiruby_setup mri:svn:tag:v1_9_1_preview2&lt;/code&gt;). So, just to be different, here's how to add preview2 from a tarball:&lt;/p&gt;
&lt;pre&gt;
$ curl -O ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-preview2.tar.gz
$ mv ruby-1.9.1-preview2.tar.gz ~/.multiruby/versions
multiruby -e &quot;p 1+1&quot;
$ multiruby -e &quot;p 1+1&quot;
&lt;/pre&gt;
&lt;p&gt;Dr Nic also mentioned how to get a list of Ruby tagged releases with subversion (&lt;code&gt;$ svn list http://svn.ruby-lang.org/repos/ruby/tags&lt;/code&gt;).  The equivalent for tarballs for 1.8 and 1.9 would be:&lt;/p&gt;
&lt;pre&gt;
$ curl ftp://ftp.ruby-lang.org/pub/ruby/1.8/ 
$ curl ftp://ftp.ruby-lang.org/pub/ruby/1.9/ 
&lt;/pre&gt;
&lt;p&gt;Now that we have the 1.9.1-preview2 release, here's the command to remove v1.9.0-5:&lt;/p&gt;
&lt;pre&gt;
$ multiruby_setup rm:1.9.0-5
&lt;/pre&gt;
&lt;h3&gt;RubyGems&lt;/h3&gt;
&lt;p&gt;By default each version has it's own copy of RubyGems. If you want to leave it that way and install the same gems in all versions you can use Ruby's &lt;code&gt;-S&lt;/code&gt; option with multiruby.  multiruby also looks for the VERSIONS and EXCLUDED_VERSIONS environment variables with verions separated by a &quot;:&quot;.  For example, if we had three Ruby versions installed: 
&lt;/p&gt;
&lt;pre&gt;
$ multiruby_setup list
Known versions:
  1.8.6-p287
  1.8.7-p72
  1.9.1-preview2
&lt;/pre&gt;
&lt;p&gt;and wanted to install Rails in just the 1.8 versions we could use:&lt;/p&gt;
&lt;pre&gt;
$ export VERSIONS=1.8.6-p287:1.8.7-p72
$ multiruby -S gem install rails
&lt;/pre&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;pre&gt;
$ export EXCLUDED_VERSIONS=1.9.1-preview2
$ multiruby -S gem install rails
&lt;/pre&gt;
&lt;p&gt;Allowing each version to have it's own copy of gems provides fine grained control.  If you'd rather just have all versions share gems (1.8 &amp; 1.9 will still be separate) that can be done too:&lt;/p&gt;
&lt;pre&gt;
$ multiruby_setup rubygems:merge
&lt;/pre&gt;
&lt;h3&gt;Switching Between Ruby Versions&lt;/h3&gt;
&lt;p&gt;The gem install example shows how &lt;code&gt;multiruby&lt;/code&gt; allows control of which versions it runs by setting environment variables but it adds output that you probably don't want when running a single version of Ruby.  Dr Nic also points out how you can isolate and run a specific cucumber scenario against a specific ruby version by cutting and pasting the results of a multiruby run.  It's simple to extend those concepts to allow any of the Ruby commands to change if we just modify the path.  For example, to use the 1.9.1-preview2 version installed above:
&lt;pre&gt;
$ export PATH=~/.multiruby/install/1.9.1-preview2/bin:$PATH
ruby -v
ruby 1.9.1 (2008-12-01 revision 20438) [i386-darwin9.5.0]
&lt;/pre&gt;
&lt;p&gt;Having the path set is convenient since it also makes 1.9.1 &lt;code&gt;irb, erb, gem&lt;/code&gt; and gem commands directly available.
&lt;/p&gt;
&lt;p&gt;Of course it's a pain to type the &lt;code&gt;export&lt;/code&gt; command each time and it would be nice to easily get back to the default Ruby installation.  A simple solution is to add add aliases to your login initialization file. Depending on your shell this may be done differently but for my bash shell I added the following to the end of &lt;code&gt;~/.bash_login&lt;/code&gt;:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;# switch between ruby versions&lt;tt&gt;
&lt;/tt&gt;export ORIGPATH=$PATH&lt;tt&gt;
&lt;/tt&gt;alias mr186p287='export PATH=~/.multiruby/install/1.8.6-p287/bin:$ORIGPATH'&lt;tt&gt;
&lt;/tt&gt;alias mr187p72='export PATH=~/.multiruby/install/1.8.7-p72/bin:$ORIGPATH'&lt;tt&gt;
&lt;/tt&gt;alias mr191pre2='export PATH=~/.multiruby/install/1.9.1-preview2/bin:$ORIGPATH'&lt;tt&gt;
&lt;/tt&gt;alias mroff='export PATH=$ORIGPATH'&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;So switching to the latest 1.8.6 Ruby versions becomes as easy as:
&lt;/p&gt;
&lt;pre&gt;
$ mr186p287
&lt;/pre&gt;
&lt;p&gt;&quot;&lt;code&gt;$ mroff&lt;/code&gt;&quot; reverts to the default install and &quot;&lt;code&gt;$ alias&lt;/code&gt;&quot; provides a reminder of what's available.  I haven't done a lot with this switching method yet but so far it seems to work for me.  If it continues to work well at some point I may even remove my &lt;code&gt;/usr/local&lt;/code&gt; Ruby installation and just add &lt;code&gt;mr186p287&lt;/code&gt; to the end of my &lt;code&gt;.bash_login&lt;/code&gt;.  Of course, I'll leave the Leopard 1.8.6 Ruby installation  alone.
&lt;/p&gt;
&lt;h3&gt;Other Ways to Switch Ruby Versions&lt;/h3&gt;
&lt;p&gt;I haven't tested this but the same alias-PATH method used above could be done without &lt;code&gt;multiruby&lt;/code&gt; by doing &lt;a href=&quot;http://blog.robseaman.com/2008/12/10/from-ruby-1-8-6-to-1-87-and-back-again-on-leopard&quot;&gt;&lt;code&gt;/usr/local&lt;/code&gt; build and installs&lt;/a&gt; into a separate installation directory (instead of /usr/local/bin) and changing the configure portion of the build.  For example, 1.9.1-preview2 could be build from source and aliased with:
&lt;pre&gt;
$ sudo mkdir -p /usr/local/1.9.1-preview2
$ cd /usr/local/src
$ curl -O ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-preview2.tar.gz
$ tar xzvf ruby-1.9.1-preview2.tar.gz
$ cd ruby-1.9.1-preview2
$ ./configure --prefix /usr/local/1.9.1-preview2 --enable-shared \
&gt; --enable-pthread CFLAGS=-D_XOPEN_SOURCE=1
$ make
$ sudo make install
$ cd ..
&lt;/pre&gt;
&lt;p&gt;and:&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;# switch between ruby verisions&lt;tt&gt;
&lt;/tt&gt;export ORIGPATH=$PATH&lt;tt&gt;
&lt;/tt&gt;alias mr191pre2='export PATH=/usr/local/bin/1.9.1-preview2/bin:$ORIGPATH'&lt;tt&gt;
&lt;/tt&gt;alias mroff='export PATH=$ORIGPATH'&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;in the &lt;code&gt;.bash_login&lt;/code&gt;.  Again, I haven't tested this so there may be some tweaking to get the installation correct but it's the same principle as we used with the &lt;code&gt;multiruby&lt;/code&gt; solution.  The upside is that you have complete control of builds and installations, but that seems minor there's no reason you can't do your own builds in the &lt;code&gt;~/.multiruby&lt;/code&gt; directories. On the downside you lose the sharing of Ruby versions with &lt;code&gt;multiruby&lt;/code&gt; and you lose &lt;code&gt;multiruby&lt;/code&gt; and &lt;code&gt;multiruby_setup&lt;/code&gt;'s abilities to manage the versions as a group.
&lt;/p&gt;
&lt;p&gt;Another way to switch, and I what I thought I'd use prior to thinking about using PATH to switch between Ruby installations is a symlink system like Daniel Manages describes in his &lt;em&gt;&lt;a href=&quot;http://www.dcmanges.com/blog/install-multiple-versions-of-ruby-on-osx-leopard&quot;&gt;Install Multiple Versions of Ruby on Leopard&lt;/a&gt;&lt;/em&gt;.  It's very similar to the &lt;code&gt;/usr/local&lt;/code&gt; method I just described but uses simlinks in &lt;code&gt;/usr/local/bin&lt;/code&gt; instead of adding to PATH.  The symlinks could also be used with the &lt;code&gt;~/.multiruby/install&lt;/code&gt; versions to make to work with &lt;code&gt;multiruby&lt;/code&gt; as well.
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.robseaman.com/">
    <author>
      <name>Rob</name>
    </author>
    <id>tag:blog.robseaman.com,2008-12-12:13</id>
    <published>2008-12-12T17:49:00Z</published>
    <updated>2009-01-20T21:18:46Z</updated>
    <category term="Ruby"/>
    <category term="popen"/>
    <category term="popen3"/>
    <category term="popen4"/>
    <category term="process.kill"/>
    <category term="sysint"/>
    <link href="http://blog.robseaman.com/2008/12/12/sending-ctrl-c-to-a-subprocess-with-ruby" rel="alternate" type="text/html"/>
    <title>Sending CTRL-C to a Subprocess with Ruby</title>
<summary type="html">&lt;p&gt;Ruby provides several simple ways to launch subprocesses. Ruby's &lt;code&gt;popen&lt;/code&gt; method comes into play in situations where cross platform handling of subprocess IO is required. Ruby also provides mechanisms to trap and send signals, such as the &lt;code&gt;SYSINT&lt;/code&gt; (Control-C) signal.  Putting &lt;code&gt;popen&lt;/code&gt; and signal handling together to launch and manage a subprocess is straight forward but there's a limitation; &lt;code&gt;popen&lt;/code&gt; lacks support for capturing standard error.  By default standard error output is just displayed on the screen as if the subprocess was launched from the command line.  There are a couple of workarounds available, in some cases it may be acceptable to discard standard error by redirecting it as part of the subprocess launch command, i.e. &quot;&lt;code&gt;command 2&gt;/dev/null&lt;/code&gt;&quot;; another, and typically better, option is to redirect standard error so that it's merged with standard output, i.e. &quot;&lt;code&gt;command 2&gt;&amp;1&lt;/code&gt;&quot;.  Unfortunately the redirection impacts the Process ID (pid) for the launched subprocess, which breaks the simple standard signal handling that I mentioned earlier. In addition to the pid issue, getting the Control-C signalling support to work in Windows can be challenging. This post walks through an example that shows &lt;code&gt;popen&lt;/code&gt; usage and how to send Control-C signals to a subprocess in Windows and Unix when standard error is redirected.  It concludes with a brief discussion of &lt;code&gt;popen3&lt;/code&gt; and &lt;code&gt;popen4&lt;/code&gt; as alternatives to &lt;code&gt;popen&lt;/code&gt;.</summary><content type="html">
            &lt;p&gt;Ruby provides several simple ways to launch subprocesses. Ruby's &lt;code&gt;popen&lt;/code&gt; method comes into play in situations where cross platform handling of subprocess IO is required. Ruby also provides mechanisms to trap and send signals, such as the &lt;code&gt;SYSINT&lt;/code&gt; (Control-C) signal.  Putting &lt;code&gt;popen&lt;/code&gt; and signal handling together to launch and manage a subprocess is straight forward but there's a limitation; &lt;code&gt;popen&lt;/code&gt; lacks support for capturing standard error.  By default standard error output is just displayed on the screen as if the subprocess was launched from the command line.  There are a couple of workarounds available, in some cases it may be acceptable to discard standard error by redirecting it as part of the subprocess launch command, i.e. &quot;&lt;code&gt;command 2&gt;/dev/null&lt;/code&gt;&quot;; another, and typically better, option is to redirect standard error so that it's merged with standard output, i.e. &quot;&lt;code&gt;command 2&gt;&amp;1&lt;/code&gt;&quot;.  Unfortunately the redirection impacts the Process ID (pid) for the launched subprocess, which breaks the simple standard signal handling that I mentioned earlier. In addition to the pid issue, getting the Control-C signalling support to work in Windows can be challenging. This post walks through an example that shows &lt;code&gt;popen&lt;/code&gt; usage and how to send Control-C signals to a subprocess in Windows and Unix when standard error is redirected.  It concludes with a brief discussion of &lt;code&gt;popen3&lt;/code&gt; and &lt;code&gt;popen4&lt;/code&gt; as alternatives to &lt;code&gt;popen&lt;/code&gt;.

&lt;/p&gt;
&lt;p&gt;I'll start with a simple Ruby program called &lt;code&gt;sub.rb&lt;/code&gt; that will stand in for a program that we want to execute:
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;trap(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; &lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;co&quot;&gt;STDERR&lt;/span&gt;.puts &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sub pid &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;gv&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; Control-C&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    exit &lt;span class=&quot;i&quot;&gt;2&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;puts &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;gv&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;co&quot;&gt;STDOUT&lt;/span&gt;.flush&lt;tt&gt;
&lt;/tt&gt;sleep &lt;span class=&quot;i&quot;&gt;10&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;The program prints its pid (&lt;code&gt;$$&lt;/code&gt;) and exits normally after 10 seconds if it doesn't receive a Control-C.  If Control-C is pressed or sent from another process the &lt;code&gt;trap&lt;/code&gt; handler is executed, it prints an error message and exits with an error code.  Ruby allows traps to be specified by number or as a long or abbreviated string.  For example, &lt;code&gt;2&lt;/code&gt;, &lt;code&gt;'SYSINT'&lt;/code&gt; or just &lt;code&gt;'INT'&lt;/code&gt; can be used to specify the Control-C trap.  For a complete list of available traps open &lt;code&gt;irb&lt;/code&gt; and type &lt;code&gt;Signal.list&lt;/code&gt;.  If you intend to use signals in a application targeted to multiple platforms, keep in mind that the list is OS dependent with Windows only supporting a small number of traps.  Back to &lt;code&gt;sub.rb&lt;/code&gt;, it's easy to check out the program by running it from the command line and pressing Control-C:
&lt;pre&gt;[mac]$	 ruby sub.rb
2994
^Csub pid 2994 Control-C
&lt;/pre&gt;
&lt;h3&gt;Unix without Standard Error&lt;/h3&gt;
&lt;p&gt;Next up is program called &lt;code&gt;popen_sub.rb&lt;/code&gt; that will execute &lt;code&gt;sub.rb&lt;/code&gt;, capture its output and send it a Control-C:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;co&quot;&gt;IO&lt;/span&gt;.popen(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ruby sub.rb&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |pipe|&lt;tt&gt;
&lt;/tt&gt;  puts &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;parent pid: &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;gv&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;, popen return (child) pid: &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;pipe.pid&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  line = pipe.gets      &lt;span class=&quot;c&quot;&gt;# pid from child&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  puts &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;child says it's pid is: &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+line&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;co&quot;&gt;Process&lt;/span&gt;.kill &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, pipe.pid&lt;tt&gt;
&lt;/tt&gt;  childs_last_word = pipe.gets&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; childs_last_word&lt;tt&gt;
&lt;/tt&gt;    puts &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;child's last word: &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + childs_last_word&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;puts &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;child's exit code: &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;gv&quot;&gt;$?&lt;/span&gt;.exitstatus&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;This first pass shows a basic way to use &lt;code&gt;popen&lt;/code&gt; and capture the subprocess output.
&lt;code&gt;Process.kill&lt;/code&gt; sends a &lt;code&gt;SYSINT&lt;/code&gt; (Control-C) signal to the subprocess and concludes by printing &lt;code&gt;$?.exitstatus&lt;/code&gt;, which contains the exit code. So what happens when it's run:
&lt;pre&gt;[mac]$	ruby popen_sub.rb
parent pid: 3046, popen return (child) pid: 3047
child says it's pid is: 3047
sub pid 3047 Control-C
child's exit code: 2
&lt;/pre&gt;
&lt;p&gt;It works, &lt;code&gt;popen&lt;/code&gt; captured standard output from &lt;code&gt;sub.rb&lt;/code&gt;, sent it a Control-C and captured its exit code.
&lt;/p&gt;
&lt;h3&gt;Adding Support for Standard Error&lt;/h3&gt;
&lt;p&gt;The code worked but &lt;code&gt;popen_sub.rb&lt;/code&gt; didn't capture &lt;code&gt;sub.rb&lt;/code&gt;'s standard error output as the &lt;code&gt;childs_last_word&lt;/code&gt;.  The standard error output just went directly to the display. Since we're already capturing standard output a simple way to capture standard error is to redirect the error stream when &lt;code&gt;sub.rb&lt;/code&gt; is launched:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;co&quot;&gt;IO&lt;/span&gt;.popen(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ruby sub.rb 2&amp;gt;&amp;amp;1&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |pipe|&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;That's easy and an Internet search will make it clear that it's a common practice. so what happens when the updated &lt;code&gt;popen_sub.rb&lt;/code&gt; is run:
&lt;/p&gt;
&lt;pre&gt;[mac]$	ruby popen_sub.rb
parent pid: 3060, popen return (child) pid: 3061
child says it's pid is: 3062
# 10 second delay
child's exit code: 0
&lt;/pre&gt;
&lt;p&gt;That not what we wanted, obviously the &lt;code&gt;SYSINT&lt;/code&gt; signal wasn't received and you can see why by looking at the pid.  The redirection caused the &lt;code&gt;pipe.pid&lt;/code&gt; to return 3061 but the actual pid for &lt;code&gt;sub.rb&lt;/code&gt; was 3062.  Now what? We can't just increment the pid returned by &lt;code&gt;pipe.pid&lt;/code&gt;; assuming pids are assigned in certain ways by all OS's and that the &lt;code&gt;pipe.pid&lt;/code&gt; from &lt;code&gt;IO.popen&lt;/code&gt; will never handle redirection correctly is weak.  But we could send the &lt;code&gt;SYSINT&lt;/code&gt; to all processes in the current process group.  There are a couple of ways to do that:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;co&quot;&gt;Process&lt;/span&gt;.kill &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, -&lt;span class=&quot;co&quot;&gt;Process&lt;/span&gt;.getpgrp&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;or
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;co&quot;&gt;Process&lt;/span&gt;.kill &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Passing a negative pid indicates that it's a group ID. Using &lt;code&gt;Process.getpgrp&lt;/code&gt; (or it's close relative &lt;code&gt;-Process.getpgid($$)&lt;/code&gt;) to retrieve the process group ID is direct and obvious. So how does using zero work? Unfortunately Ruby's rdoc for &lt;code&gt;Process.kill&lt;/code&gt; is incorrect regarding using a pid of zero.  It indicates the signal is sent to the current process but that's not true. Looking at the &lt;code&gt;rb_f_kill()&lt;/code&gt; function in Ruby's &lt;code&gt;signal.c&lt;/code&gt; module there's some handling to support &lt;a href=&quot;http://www.cs.ucsb.edu/~almeroth/classes/W99.276/assignment1/signals.html&quot;&gt;Posix and Berkley style&lt;/a&gt; &lt;code&gt;kill()&lt;/code&gt; calls but other than that pids are just passed to the Unix OS call.  Some Unix documentation states that using zero for the pid will send the signal to all processes, except system processes but I've only seen behavior consistent with &lt;a href=&quot;http://www.cs.ucsb.edu/~almeroth/classes/W99.276/assignment1/signals.html&quot;&gt;this description&lt;/a&gt;:
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&quot;If pid is 0, sig shall be sent to all processes (excluding an unspecified set of system processes) whose process group ID is equal to the process group ID of the sender, and for which the process has permission to send a signal.&quot;&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;With either group ID solution the parent process will also get the &lt;code&gt;SYSINT&lt;/code&gt; signal so it will need to have a trap handler in place when the signal is sent. The handler doesn't have to do anything so it can be as simple as this:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;trap(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) {}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;If the parent doesn't setup a trap handler then Ruby's default SYSINT exception handling will take place, printing an error and terminating the program.  That leads to the biggest caveat with this approach, since the signal goes to processes in the group, not just the current process and child processes, all parent processes need to set-up a handler and ignore the signal. This isn't an issue when you run the application directly from Ruby since it's the top-level parent. It can even be made to work as a child if you write the code for the ancestor processes but it is an issue when the Ruby application is spawned by a process.  Unless you go through the trouble to patch the top-level parent so it handles signals the way you want then when the Ruby app decides to send a &lt;code&gt;SYSINT&lt;/code&gt;, the parent will get the signal too and in most cases terminate.  For apps that are intended to be standalone this isn't a show stopper but it's something to beware of. One common situation where it shows up is when running tests. It's not an issue with directly running unit or coverage tests (i.e. &lt;code&gt;ruby test/test_xxx.rb&lt;/code&gt; or &lt;code&gt;rcov test/test_xxx.rb&lt;/code&gt;) but it is a problem when running those tests with &lt;code&gt;rake&lt;/code&gt; or &lt;code&gt;rake coverage&lt;/code&gt;.  In my test code I put code in to check for &lt;code&gt;Process.getpgrp == Process.pid&lt;/code&gt;, if it's &lt;code&gt;false&lt;/code&gt; I print a warning and skip tests that result in &lt;code&gt;SYSINT&lt;/code&gt;s. Another workaround would be to place similar code in the application itself to avoid sending a &lt;code&gt;SYSINT&lt;/code&gt; when there's a parent.
&lt;/p&gt;
&lt;h3&gt;Making it work in Windows&lt;/h3&gt;
&lt;p&gt;There's been &lt;code&gt;Process.kill&lt;/code&gt; support for Windows since Ruby 1.7.x but Ruby's &lt;code&gt;win32.c&lt;/code&gt; &lt;code&gt;kill()&lt;/code&gt; function has this check at the top:
&lt;/p&gt;	
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;3179&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;3180&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;3181&lt;tt&gt;
&lt;/tt&gt;3182&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; (pid &amp;lt;= &lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;) {&lt;tt&gt;
&lt;/tt&gt;  errno = EINVAL;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;return&lt;/span&gt; -&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;That makes it pretty obvious that only individual process IDs are supported in Windows.  &lt;em&gt;Actually, I'm not sure if it would matter if there was group pid support since I wasn't able to get Ruby's &lt;code&gt;Process.kill&lt;/code&gt; to work with standard pids in Vista or XP using the original non-redirect &lt;code&gt;popen_sub.rb&lt;/code&gt; from above. That seems hard to believe so may be I did something wrong.  I was focussed on group pids by the time I looked at Windows, so, I didn't dig into it but it definitely fell short of my expectation that the same code would just work in both Windows and Unix.&lt;/em&gt;
&lt;/p&gt;	
&lt;p&gt;&lt;a href=&quot;http://rubyforge.org/projects/win32utils&quot;&gt;Win32 Utils&lt;/a&gt; provides an alternative with its &lt;code&gt;win32-process&lt;/code&gt; gem.  The gem is installed with the &lt;a href=&quot;http://rubyinstaller.rubyforge.org/wiki/wiki.pl?RubyInstaller&quot;&gt; One-Click Ruby Installer for Windows&lt;/a&gt; gem pack so it's already part of most Windows installations.  At first glance it doesn't appear to be much better than Ruby's built in support. Again, there's no group PID support so &lt;code&gt;Process.getpgrp&lt;/code&gt; and &lt;code&gt;-Process.getpgid($$)&lt;/code&gt; won't work. It does support using zero for the pid but unfortunately it implements the support as Ruby's rdoc says it should instead of the way the Ruby code implements it.  Specifically, it intercepts the zero and translates it to the pid of the current process. &lt;em&gt;And, just like with the standard Ruby implementation, &lt;code&gt;Process.kill&lt;/code&gt; didn't work for me with normal pids on Vista or XP.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;Ah, but there's a loophole that we can take advantage of in the &lt;code&gt;win32-process&lt;/code&gt; gem. If we use &lt;code&gt;nil&lt;/code&gt; for the pid it will get translated to &lt;code&gt;NULL&lt;/code&gt; (0L in c/c++) before being passed as the &lt;code&gt;dwProcessGroupId&lt;/code&gt; parameter to the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms683155(VS.85).aspx&quot;&gt;GenerateConsoleCtrlEvent()&lt;/a&gt; Windows function.  A zero for that parameter means that &lt;em&gt;&quot;the signal is generated in all processes that share the console of the calling process&quot;&lt;/em&gt;.  Yeah baby! OK, it's a hack and depends on the implementation of &lt;code&gt;win32-process&lt;/code&gt; but we don't have a lot of choices. 
&lt;/p&gt;
&lt;p&gt;That leads to the final version of &lt;code&gt;popen_sub.rb&lt;/code&gt;:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;RUBY_PLATFORM&lt;/span&gt; =~ &lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;win32&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;win32/process&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;# GenerateConsoleCtrlEvent, dwProcessGroupId = 0L &amp;lt; NULL &amp;lt; nil&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;sysint_gpid&lt;/span&gt;; &lt;span class=&quot;pc&quot;&gt;nil&lt;/span&gt;; &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;sysint_gpid&lt;/span&gt;; -&lt;span class=&quot;co&quot;&gt;Process&lt;/span&gt;.getpgrp; &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;co&quot;&gt;IO&lt;/span&gt;.popen(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ruby sub.rb 2&amp;gt;&amp;amp;1&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |pipe|&lt;tt&gt;
&lt;/tt&gt;  trap(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    puts &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;parent pid: &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;gv&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; Control-C&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  puts &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;parent pid: &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;gv&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;, popen return (child) pid: &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;pipe.pid&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  line = pipe.gets      &lt;span class=&quot;c&quot;&gt;# pid from child&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  puts &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;child says it's pid is: &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+line&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;co&quot;&gt;Process&lt;/span&gt;.kill &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, sysint_gpid&lt;tt&gt;
&lt;/tt&gt;  childs_last_word = pipe.gets&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; childs_last_word&lt;tt&gt;
&lt;/tt&gt;    puts &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;child's last word: &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + childs_last_word&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;puts &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;child's exit code: &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;gv&quot;&gt;$?&lt;/span&gt;.exitstatus&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;The trap handler could have been placed in the top-level scope but I put it inside the &lt;code&gt;popen&lt;/code&gt; block to make it clear that scoping rules apply when defining a trap handler.  Also, in a real application that wanted to ignore SYSINTs the handler would be defined as '&lt;code&gt;trap(&quot;INT&quot;) {}&lt;/code&gt;', like I showed above, but for the test application I wanted to see when the parent received the signal.  Here's a run of the program from Windows:
&lt;/p&gt;
&lt;pre&gt;
Z:\work\ptest&gt;ruby popen_sub.rb
parent pid: 200, popen return (child) pid: 1468
child says it's pid is: 376
parent pid: 200 Control-C
child's last word: sub pid 376 Control-C
child's exit code: 2
&lt;/pre&gt;
&lt;p&gt;That was a Windows run but it works fine in Unix too.  That's it, both standard output and standard error went through the parent process and the parent successfully sent a Control-C (SYSINT) signal to the subprocess.  BTW: If you don't care about standard error then the same code could also be used without the redirection.  That would be helpful if you need cross platform support and you have the same problems I had getting &lt;code&gt;Process.kill&lt;/code&gt; to work with &lt;code&gt;pipe.pid&lt;/code&gt; in Windows.
&lt;/p&gt;
&lt;h3&gt;Other Options&lt;/h3&gt;
&lt;p&gt;If redirecting standard error doesn't meet your needs then &lt;code&gt;popen3&lt;/code&gt; and &lt;code&gt;popen4&lt;/code&gt; are alternatives to &lt;code&gt;popen&lt;/code&gt; that provide separate access to the standard error stream&lt;/code&gt;.  
&lt;/p&gt;
&lt;p&gt;Unfortunately standard library support for &lt;code&gt;popen3&lt;/code&gt; is limited to Unix and it doesn't provide an way to get to the subprocess pid so I don't see a way to send signals without opening up the method. There is a &lt;a href=&quot;http://rubyforge.org/projects/win32utils&quot;&gt;Win32 Utils&lt;/a&gt; &lt;a href=&quot;http://raa.ruby-lang.org/project/win32-open3/0.2.6&quot;&gt;win32-open3&lt;/a&gt; library that provides &lt;code&gt;popen3&lt;/code&gt; support.  I gave it a quick try but I couldn't get it to work. May be I installed the wrong version or since I had issues with all Windows &lt;code&gt;Process.kill&lt;/code&gt; implementations using standard pids, may be I ran into some related user error but I didn't bother to look into it very much because the project I'm working on requires signal support, and I was concerned about the issues I saw reported when googling for '&lt;code&gt;popen3 ruby windows&lt;/code&gt;' and finally, because it's not included in the Win32 Utils gems that are distributed with the &lt;a href=&quot;http://rubyinstaller.rubyforge.org/wiki/wiki.pl?RubyInstaller&quot;&gt; One-Click Ruby Installer for Windows&lt;/a&gt;, and I wasn't crazy about making it a separate prerequisite.
&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://popen4.rubyforge.org/&quot;&gt;&lt;code&gt;popen4&lt;/code&gt;&lt;/a&gt;'s advantage over &lt;code&gt;popen3&lt;/code&gt; is that it provides access to the subprocess pid along with the three IO streams. I didn't use it instead of &lt;code&gt;popen&lt;/code&gt; because not part of the Unix standard library and I thought the Windows installation requirements were too complex. So, I didn't want it as a dependancy for any application that I might end up distributing.
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.robseaman.com/">
    <author>
      <name>Rob</name>
    </author>
    <id>tag:blog.robseaman.com,2008-12-10:12</id>
    <published>2008-12-10T08:02:00Z</published>
    <updated>2009-01-14T06:22:38Z</updated>
    <category term="Ruby"/>
    <category term="1.8.6"/>
    <category term="1.8.7"/>
    <category term="1.9.1-preview2"/>
    <category term="installation"/>
    <category term="leopard"/>
    <category term="multiruby"/>
    <category term="readline"/>
    <link href="http://blog.robseaman.com/2008/12/10/from-ruby-1-8-6-to-1-87-and-back-again-on-leopard" rel="alternate" type="text/html"/>
    <title>Installing Ruby 1.8.6, 1.8.7 and 1.9 on Leopard</title>
<summary type="html">&lt;p&gt;&lt;em&gt;Dec. 19, 2008 Update: This post covers setting up and switching the default Ruby installation in &lt;code&gt;/usr/local&lt;/code&gt;.  If you're looking for a more dynamic way to test and/or switch between Ruby versions see &lt;a href=&quot;http://blog.robseaman.com/2008/12/20/switching-between-ruby-1-8-1-9-with-multiruby&quot;&gt;Switching Between Ruby 1.8 &amp; 1.9 with multiruby&lt;/a&gt;&lt;/em&gt;.
&lt;/p&gt;
&lt;p&gt;I had originally installed Ruby 1.8.6 on Tiger from source using Dan Benjamin's &lt;em&gt;&lt;a href=&quot;http://danbenjamin.com/articles/2007/02/ruby-rails-mongrel-mysql-osx&quot;&gt;Building Ruby, Rails, Subversion, Mongrel, and MySQL on Mac OS X&lt;/a&gt;&lt;/em&gt; instructions.  I upgraded to Leopard but continued to run the &lt;code&gt;/usr/local&lt;/code&gt; version of Ruby.  It has been working fine for me but for various reasons I decided it was time to upgrade to 1.8.7. I was happy to see Dan had created updated instructions for Leopard in his &lt;em&gt;&lt;a href=&quot;http://danbenjamin.com/articles/2008/02/ruby-rails-leopard&quot;&gt;Installing Ruby, Rubygems, Rails, and Mongrel on Mac OS X 10.5 (Leopard)&lt;/a&gt;&lt;/em&gt; post. So I decided that I'd just install over my 1.8.6 version.  It didn't go off without a hitch, I ran into a problem compiling readline.  This post documents what worked to resolve the problem, my journey back to 1.8.6, how to add 1.9 support and how to switch between versions.</summary><content type="html">
            &lt;p&gt;&lt;em&gt;Dec. 19, 2008 Update: This post covers setting up and switching the default Ruby installation in &lt;code&gt;/usr/local&lt;/code&gt;.  If you're looking for a more dynamic way to test and/or switch between Ruby versions see &lt;a href=&quot;http://blog.robseaman.com/2008/12/20/switching-between-ruby-1-8-1-9-with-multiruby&quot;&gt;Switching Between Ruby 1.8 &amp; 1.9 with multiruby&lt;/a&gt;&lt;/em&gt;.
&lt;/p&gt;
&lt;p&gt;I had originally installed Ruby 1.8.6 on Tiger from source using Dan Benjamin's &lt;em&gt;&lt;a href=&quot;http://danbenjamin.com/articles/2007/02/ruby-rails-mongrel-mysql-osx&quot;&gt;Building Ruby, Rails, Subversion, Mongrel, and MySQL on Mac OS X&lt;/a&gt;&lt;/em&gt; instructions.  I upgraded to Leopard but continued to run the &lt;code&gt;/usr/local&lt;/code&gt; version of Ruby.  It has been working fine for me but for various reasons I decided it was time to upgrade to 1.8.7. I was happy to see Dan had created updated instructions for Leopard in his &lt;em&gt;&lt;a href=&quot;http://danbenjamin.com/articles/2008/02/ruby-rails-leopard&quot;&gt;Installing Ruby, Rubygems, Rails, and Mongrel on Mac OS X 10.5 (Leopard)&lt;/a&gt;&lt;/em&gt; post. So I decided that I'd just install over my 1.8.6 version.  It didn't go off without a hitch, I ran into a problem compiling readline.  This post documents what worked to resolve the problem, my journey back to 1.8.6, how to add 1.9 support and how to switch between versions.

&lt;/p&gt;
&lt;h3&gt;ruby-1.8.7-p72&lt;/h3&gt;
&lt;p&gt;My first step, and original goal, was to upgrade to 1.8.7. Since I already had 1.8.6 in &lt;code&gt;/usr/local&lt;/code&gt; I already had RubyGems so I thought I just needed to follow the &lt;a href=&quot;http://danbenjamin.com/articles/2008/02/ruby-rails-leopard#ruby&quot;&gt;Ruby installation instructions&lt;/a&gt;.  Here's a repeat of Dan's information about how to do that:
&lt;/p&gt;
&lt;pre&gt;
$ cd /usr/local/src
$ curl -O ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p72.tar.gz
$ tar xzvf ruby-1.8.7-p72.tar.gz
$ cd ruby-1.8.7-p72
$ ./configure --enable-shared --enable-pthread CFLAGS=-D_XOPEN_SOURCE=1
$ make
$ sudo make install
$ cd ..
&lt;/pre&gt;
&lt;p&gt;But the instructions were for a fresh Leopard install and I ran into the following problem during the make:
&lt;/p&gt;
&lt;pre&gt;
compiling readline
gcc -I. -I../.. -I../../. -I../.././ext/readline -DHAVE_READLINE_READLINE_H ...
... -D_XOPEN_SOURCE=1  -fno-common -pipe -fno-common   -c readline.c
readline.c: In function ‘filename_completion_proc_call’:
readline.c:703: error: ‘filename_completion_function’ undeclared
     (first use in this function)
readline.c:703: error: (Each undeclared identifier is reported only once
readline.c:703: error: for each function it appears in.)
readline.c:703: warning: assignment makes pointer from integer without a cast
readline.c: In function ‘username_completion_proc_call’:
readline.c:730: error: ‘username_completion_function’ undeclared 
     (first use in this function)
readline.c:730: warning: assignment makes pointer from integer without a cast
{standard input}:358:non-relocatable subtraction expression, 
     &quot;_mReadline&quot; minus &quot;L00000000007$pb&quot;
{standard input}:358:symbol: &quot;_mReadline&quot; can't be undefined in a 
      subtraction expression
...
{standard input}:249:non-relocatable subtraction expression, &quot;_completion_proc&quot;
       minus &quot;L00000000003$pb&quot;
{standard input}:249:symbol: &quot;_completion_proc&quot; can't be undefined in a 
        subtraction expression
make[1]: *** [readline.o] Error 1
make: *** [all] Error 1
&lt;/pre&gt;
&lt;p&gt;I went through a couple of failed correction attempts based on posts from others before finding Angelbob’s Musings on Programming, &lt;em&gt;&lt;a href=&quot;http://www.angelbob.com/musings/?p=34&quot;&gt;Compiling Ruby 1.8.7 on a PowerBook G4 with Mac OS X 10.4&lt;/a&gt;&lt;/em&gt;
post.  Bob's post explains that the issue relates to which version of readline you're using and Ruby not knowing whether functions have an &quot;rl_&quot; prepended to function names but that you can explicitly provide the information in Ruby's &lt;code&gt;config.h&lt;/code&gt;. Since I'd messed with the 1.8.7 source directories I deleted the whole thing, extracted it again and then, after re-running the &lt;a href=&quot;http://danbenjamin.com/articles/2008/02/ruby-rails-leopard#ruby&quot;&gt;configure&lt;/a&gt; command, I added the following to &lt;code&gt;config.h&lt;/code&gt;:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;193&lt;tt&gt;
&lt;/tt&gt;194&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;195&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;#define HAVE_RL_FILENAME_COMPLETION_FUNCTION 1&lt;tt&gt;
&lt;/tt&gt;#define HAVE_RL_USERNAME_COMPLETION_FUNCTION 1&lt;tt&gt;
&lt;/tt&gt;#define HAVE_RL_COMPLETION_MATCHES 1&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;This time the make and installed worked fine. I could have left it at that but since Dan's instructions would have worked with a fresh Leopard computer I decided to get rid of the &lt;code&gt;/usr/local&lt;/code&gt; readline version that I had installed back when I was running Tiger.  I didn't want to deal with non-standard (meaning non-native to Leopard) readline issues again.  First I made sure I didn't have other &lt;code&gt;/usr/local/&lt;/code&gt; readline dependencies, I didn't; in my case readline 5.1 was only installed to get the orignal &lt;a href=&quot;http://danbenjamin.com/articles/2007/02/ruby-rails-mongrel-mysql-osx&quot;&gt;Ruby 1.8.6 environment set-up&lt;/a&gt;, so I nixed it:
&lt;/p&gt;
&lt;pre&gt;
$ cd /usr/local/src
$ cd readline-5.1 
$ sudo make uninstall
&lt;/pre&gt;
&lt;p&gt;From there I started again over with &lt;a href=&quot;http://danbenjamin.com/articles/2008/02/ruby-rails-leopard#ruby&quot;&gt;Dan's Leopard instructions&lt;/a&gt;. This time everything worked without modifying the &lt;code&gt;config.h&lt;/code&gt;.
&lt;/p&gt;
&lt;h3&gt;1.8.6-p287&lt;/h3&gt;
&lt;p&gt;Unfortunately I couldn't stick with 1.8.7.  Mephisto is using 2.0.2 and starting it in 1.8.7 results in this error:
&lt;pre&gt;
undefined method `[]' for #
&lt;/pre&gt;
&lt;p&gt;So, I moved back to Ruby 1.8.6. This time I got the latest version and dropped the use of the &lt;code&gt;/usr/local&lt;/code&gt; readline:
&lt;/p&gt;
&lt;pre&gt;
$ cd /usr/local/src
$ curl -O ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.6-p287.tar.gz
$ tar xzvf ruby-1.8.6-p287.tar.gz
$ cd ruby-1.8.6-p287
$ ./configure --enable-shared --enable-pthread CFLAGS=-D_XOPEN_SOURCE=1
$ make
$ sudo make install
$ sudo make install-doc
$ cd ..
&lt;/pre&gt;
&lt;h3&gt;1.9.1-preview2&lt;/h3&gt;
&lt;p&gt;Other than the 1.8.7 and Rails incompatibility everything was fine and, since switching between installations was now fresh in my mind, I decided it was finally time to try the latest 1.9 release:
&lt;/p&gt;
&lt;pre&gt;
$ cd /usr/local/src
$ curl -O ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-preview2.tar.gz
$ tar xzvf ruby-1.9.1-preview2.tar.gz
$ cd ruby-1.9.1-preview2
$ ./configure --enable-shared --enable-pthread CFLAGS=-D_XOPEN_SOURCE=1
$ make
$ sudo make install
$ cd ..
&lt;/pre&gt;
&lt;p&gt;After I'd done a little testing going back to 1.8.6 was easy:
&lt;/p&gt;
&lt;pre&gt;
$ cd /usr/local/src/ruby-1.8.6-p287
$ sudo make install
$ sudo make install-doc
&lt;/pre&gt;
&lt;p&gt;So, with the readline issue gone, I can switch my default installation by just changing to appropriate build and running &quot;&lt;code&gt;sudo make install&lt;/code&gt;&quot; (and &quot;&lt;code&gt;sudo make install-doc&lt;/code&gt;&quot; for pre 1.8.7 releases)  whenever I want.  
&lt;/p&gt;
&lt;p&gt;I should add a caveat at this point, it's generally been fine to install Ruby over old versions and I didn't notice any problems but there is a chance that a file from a previous install won't get overwritten and could cause a problem.  Also, my goal was just to upgrade, it wasn't to come up with an optimal or clean way to switch between versions.  
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.robseaman.com/">
    <author>
      <name>Rob</name>
    </author>
    <id>tag:blog.robseaman.com,2008-12-04:10</id>
    <published>2008-12-04T17:21:00Z</published>
    <updated>2009-01-14T06:07:37Z</updated>
    <category term="Website Setup"/>
    <category term="actionmailer"/>
    <category term="gmail"/>
    <category term="smtp"/>
    <category term="ssl"/>
    <category term="tls"/>
    <link href="http://blog.robseaman.com/2008/12/4/adding-gmail-ssl-smtp-support-to-rails" rel="alternate" type="text/html"/>
    <title>Adding Gmail SSL SMTP Support to Rails</title>
<summary type="html">&lt;p&gt;&lt;em&gt;Jan. 13, 2009 Update: If you're using Ruby 1.8.7 see &lt;a href=&quot;http://blog.robseaman.com/2009/1/14/updating-gmail-ssl-smtp-support-for-ruby-1-8-7&quot;&gt;Updating Gmail SSL SMTP Support for Ruby 1.8.7&lt;/a&gt; for a compatibility fix to the plugin used in this post.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;DreamHost provides it's own SMTP support but their default set-up uses Gmail, which only supports SSL based SMTP connections.  Rails 2.2 with Ruby 1.9 provides SSL support in ActionMailer via Ruby's 1.9 Net::SMTP class.  That's great but it's still a very new combination and I wanted support for DreamHost's Ruby 1.8.5 and &lt;a href=&quot;http://mephistoblog.com/&quot;&gt;Mephisto&lt;/a&gt; using Rails 2.0.2. Fortunately it's simple to get SSL (a.k.a. TLS) based SMTP connections to work.  Within a few minutes of hitting the browser search button I saw three options: &lt;a href=&quot;http://www.ruby-forum.com/topic/140855#626247&quot;&gt;lift 1.9 Net::SMTP code&lt;/a&gt;, &lt;a href=&quot;http://wiki.rubyonrails.org/rails/pages/HowToSendEmailsWithActionMailer&quot;&gt;use msmtp&lt;/a&gt;, and, the method I chose, &lt;a href=&quot;http://www.stephenchu.com/2006/06/how-to-use-gmail-smtp-server-to-send.html&quot;&gt;a small plugin that patches Net::SMTP&lt;/a&gt;. No, I didn't look into the merits of each solution and I didn't do any type of exhaustive search to see what else might be available, I just picked what looked like an easy way to get the job done. This post documents where to find the plugin and how to use it.</summary><content type="html">
            &lt;p&gt;&lt;em&gt;Jan. 13, 2009 Update: If you're using Ruby 1.8.7 see &lt;a href=&quot;http://blog.robseaman.com/2009/1/14/updating-gmail-ssl-smtp-support-for-ruby-1-8-7&quot;&gt;Updating Gmail SSL SMTP Support for Ruby 1.8.7&lt;/a&gt; for a compatibility fix to the plugin used in this post.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;DreamHost provides it's own SMTP support but their default set-up uses Gmail, which only supports SSL based SMTP connections.  Rails 2.2 with Ruby 1.9 provides SSL support in ActionMailer via Ruby's 1.9 Net::SMTP class.  That's great but it's still a very new combination and I wanted support for DreamHost's Ruby 1.8.5 and &lt;a href=&quot;http://mephistoblog.com/&quot;&gt;Mephisto&lt;/a&gt; using Rails 2.0.2. Fortunately it's simple to get SSL (a.k.a. TLS) based SMTP connections to work.  Within a few minutes of hitting the browser search button I saw three options: &lt;a href=&quot;http://www.ruby-forum.com/topic/140855#626247&quot;&gt;lift 1.9 Net::SMTP code&lt;/a&gt;, &lt;a href=&quot;http://wiki.rubyonrails.org/rails/pages/HowToSendEmailsWithActionMailer&quot;&gt;use msmtp&lt;/a&gt;, and, the method I chose, &lt;a href=&quot;http://www.stephenchu.com/2006/06/how-to-use-gmail-smtp-server-to-send.html&quot;&gt;a small plugin that patches Net::SMTP&lt;/a&gt;. No, I didn't look into the merits of each solution and I didn't do any type of exhaustive search to see what else might be available, I just picked what looked like an easy way to get the job done. This post documents where to find the plugin and how to use it. 

&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.infoq.com/articles/ruby-open-classes-monkeypatching&quot;&gt;Monkey patching can be a slippery slope&lt;/a&gt; but in this case the solution in Steven Chu's &lt;em&gt;&lt;a href=&quot;http://www.stephenchu.com/2006/06/how-to-use-gmail-smtp-server-to-send.html&quot;&gt;How to use GMail SMTP server to send emails in Rails ActionMailer&lt;/a&gt;&lt;/em&gt; post was so simple and transparent that I decided it was the way to go.  Steven provided the code to extend ActionMailer to support TLS but not the plugin packaging so before doing that myself I did quick search on github and found that &lt;a href=&quot;http://caritos.com/&quot;&gt;Eladio Caritos&lt;/a&gt; had the code in an &lt;a href=&quot;http://github.com/caritos/action_mailer_tls/tree/master&quot;&gt;action_mailer_tls&lt;/a&gt; git repository.
&lt;/p&gt;
&lt;p&gt;With Rails 2.1.0 or greater you can install the repository as a plugin:
&lt;pre&gt;
[mac]$ script/plugin install git://github.com/caritos/action_mailer_tls.git
&lt;/pre&gt;
&lt;p&gt;With older versions you have to &lt;a href=&quot;http://dev.rubyonrails.org/changeset/9049&quot;&gt;install it&lt;/a&gt; manually:
&lt;pre&gt;
[mac]$ git clone --depth 1 git://github.com/caritos/action_mailer_tls.git \
&gt; vendor/plugins/action_mailer_tls
[mac]$ rm -rf vendor/plugins/action_mailer_tls/.git
&lt;/pre&gt;
&lt;p&gt;The README in the plugin is based on Steven's post, which is a bit dated.  The recommendation is to add SMTP configuration to &lt;code&gt;config/environment.rb&lt;/code&gt;: 
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;34&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;35&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;38&lt;tt&gt;
&lt;/tt&gt;39&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;40&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;41&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;co&quot;&gt;ActionMailer&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Base&lt;/span&gt;.server_settings = {&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;sy&quot;&gt;:address&lt;/span&gt; =&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;smtp.gmail.com&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;sy&quot;&gt;:port&lt;/span&gt; =&amp;gt; &lt;span class=&quot;i&quot;&gt;587&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;sy&quot;&gt;:domain&lt;/span&gt; =&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mycompany.com&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;sy&quot;&gt;:authentication&lt;/span&gt; =&amp;gt; &lt;span class=&quot;sy&quot;&gt;:plain&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;sy&quot;&gt;:user_name&lt;/span&gt; =&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;sy&quot;&gt;:password&lt;/span&gt; =&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Way back in Rails 1.2.2 the &lt;a href=&quot;http://dev.rubyonrails.org/changeset/6212&quot;&gt;&lt;code&gt;config/initializers&lt;/code&gt; directory was added to replace this type of use of &lt;code&gt;config/environment.rb&lt;/code&gt;&lt;/a&gt; and the &lt;a href=&quot;http://github.com/rails/rails/commit/6744e35b25f79e2529e764a6d3d581b6d7dcd971&quot;&gt;server_settings method was dropped in favor of smtp_settings&lt;/a&gt;.  So, I created a &lt;code&gt;config/initializers/mail.rb&lt;/code&gt; file that looks like this:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;co&quot;&gt;ActionMailer&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Base&lt;/span&gt;.smtp_settings = {&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;sy&quot;&gt;:address&lt;/span&gt; =&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;smtp.gmail.com&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;sy&quot;&gt;:port&lt;/span&gt; =&amp;gt; &lt;span class=&quot;i&quot;&gt;587&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;# :domain =&amp;gt; &amp;quot;robseaman.com&amp;quot;, # HELO domain (not req'd)&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;sy&quot;&gt;:authentication&lt;/span&gt; =&amp;gt; &lt;span class=&quot;sy&quot;&gt;:plain&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;sy&quot;&gt;:user_name&lt;/span&gt; =&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;blog@robseaman.com&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;sy&quot;&gt;:password&lt;/span&gt; =&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mypass&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;From an email standpoint that's all there was to it, Gmail support was complete.
&lt;/p&gt;
&lt;h3&gt;Housekeeping&lt;/h3&gt;
&lt;p&gt;Since I'm using &lt;a href=&quot;http://blog.robseaman.com/2008/12/3/cached-externals&quot;&gt;Cached Externals&lt;/a&gt; I also added an entry to my &lt;code&gt;config/externals.yml&lt;/code&gt; file:
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;34&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;35&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;38&lt;tt&gt;
&lt;/tt&gt;39&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;vendor/plugins/action_mailer_tls:&lt;tt&gt;
&lt;/tt&gt;  :type: git&lt;tt&gt;
&lt;/tt&gt;  # DH old git checkout (1.4.4.4) doesn't support -q&lt;tt&gt;
&lt;/tt&gt;  :scm_verbose: true&lt;tt&gt;
&lt;/tt&gt;  :repository: git://github.com/caritos/action_mailer_tls.git&lt;tt&gt;
&lt;/tt&gt;  :revision: 0bc370bbfcbb6c25485c11c13a1662f1728d97e5&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;and ran:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ cap local externals:setup
&lt;/pre&gt;
&lt;p&gt;to cache the plugin.  There's very little code in the plugin so I didn't cache it expecting a performance benefit; I just wanted to create an explicit record of where I got it and which revision I used.
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.robseaman.com/">
    <author>
      <name>Rob</name>
    </author>
    <id>tag:blog.robseaman.com,2008-12-03:8</id>
    <published>2008-12-03T20:08:00Z</published>
    <updated>2009-01-15T17:00:06Z</updated>
    <category term="Website Setup"/>
    <category term="cachedexternals"/>
    <category term="capistrano"/>
    <category term="mephisto"/>
    <link href="http://blog.robseaman.com/2008/12/3/cached-externals" rel="alternate" type="text/html"/>
    <title>Cached Externals</title>
<summary type="html">&lt;p&gt;&lt;em&gt;Jan. 14, 2009 Update: The techniques discussed in this post are still relevant but the externals only apply to Mephisto 0.8. See &lt;a href=&quot;http://blog.robseaman.com/2009/1/15/upgrading-to-mephisto-0-8-1&quot;&gt;Upgrading to Mephisto 0.8.1&lt;/a&gt; for information about the externals that I'm currently caching.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://github.com/37signals/cached_externals/tree/master&quot;&gt;Cached Externals&lt;/a&gt; is a Rails plugin that extends &lt;a href=&quot;http://www.capify.org/&quot;&gt;Capistrano&lt;/a&gt; to speed up deployments by not deploying vendor gems and plugins unless they change. The way it accomplishes the performance gain also results in explicit management of the cached gems and plugins, something worthwhile in it's own right. In this this post I'll walk you through installation and use of the plugin by describing how I used it for this &lt;a href=&quot;http://mephistoblog.com/&quot;&gt;Mephisto&lt;/a&gt; blog application.  &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/1/gitting-started-with-mephisto&quot;&gt;gitting Started with Mephisto&lt;/a&gt;&lt;/em&gt; describes how the application was set-up and &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/1/deploying-mephisto-with-capistrano-to-dreamhost&quot;&gt;Deploying Mephisto with Capistrano to DreamHost&lt;/a&gt;&lt;/em&gt; provides the pre-Cached Externals deployment details.  Basically the app is just a customized copy of Mephisto in a git repository.  The vendor directory holds Rails 2.0.2 and TZInfo along with all the gems and plugins that are part of the Mephisto distribution.  The repository is kept locally on a laptop so Capistrano's copy strategy is used to deploy it to the production server.</summary><content type="html">
            &lt;p&gt;&lt;em&gt;Jan. 14, 2009 Update: The techniques discussed in this post are still relevant but the externals only apply to Mephisto 0.8. See &lt;a href=&quot;http://blog.robseaman.com/2009/1/15/upgrading-to-mephisto-0-8-1&quot;&gt;Upgrading to Mephisto 0.8.1&lt;/a&gt; for information about the externals that I'm currently caching.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://github.com/37signals/cached_externals/tree/master&quot;&gt;Cached Externals&lt;/a&gt; is a Rails plugin that extends &lt;a href=&quot;http://www.capify.org/&quot;&gt;Capistrano&lt;/a&gt; to speed up deployments by not deploying vendor gems and plugins unless they change. The way it accomplishes the performance gain also results in explicit management of the cached gems and plugins, something worthwhile in it's own right. In this this post I'll walk you through installation and use of the plugin by describing how I used it for this &lt;a href=&quot;http://mephistoblog.com/&quot;&gt;Mephisto&lt;/a&gt; blog application.  &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/1/gitting-started-with-mephisto&quot;&gt;gitting Started with Mephisto&lt;/a&gt;&lt;/em&gt; describes how the application was set-up and &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/1/deploying-mephisto-with-capistrano-to-dreamhost&quot;&gt;Deploying Mephisto with Capistrano to DreamHost&lt;/a&gt;&lt;/em&gt; provides the pre-Cached Externals deployment details.  Basically the app is just a customized copy of Mephisto in a git repository.  The vendor directory holds Rails 2.0.2 and TZInfo along with all the gems and plugins that are part of the Mephisto distribution.  The repository is kept locally on a laptop so Capistrano's copy strategy is used to deploy it to the production server.

&lt;/p&gt;
&lt;h3&gt;Using Cached Externals&lt;/h3&gt;
&lt;p&gt;The first step is is to install Cached Externals.  It's a Rails plugin on &lt;a href=&quot;http://github.com/&quot;&gt;github&lt;/a&gt; so if your using any Rails version greater than 2.1.0 you can install it directly:
&lt;pre&gt;
[mac]$ script/plugin install git://github.com/37signals/cached_externals.git
&lt;/pre&gt;
&lt;p&gt;but since the Mephisto implementation is using Rails 2.0.2, I had to &lt;a href=&quot;http://dev.rubyonrails.org/changeset/9049&quot;&gt;install it&lt;/a&gt; manually:
&lt;pre&gt;
[mac]$ git clone --depth 1 git://github.com/37signals/cached_externals.git \
&gt; vendor/plugins/cached_externals
[mac]$ rm -rf vendor/plugins/cached_externals/.git
&lt;/pre&gt;
&lt;p&gt;Once the plugin is installed it's just a matter of following the instructions in the &lt;code&gt;README.rdoc&lt;/code&gt; and deciding which externals to cache.  Capistrano 2 is the minimum requirement, this blog is deployed using 2.5.2, so no problem there. The next step is to check to make sure this line is in the &lt;code&gt;Capify&lt;/code&gt; file:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;co&quot;&gt;Dir&lt;/span&gt;[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;vendor/plugins/*/recipes/*.rb&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;].each { |plugin| load(plugin) }&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;It was in mine.  If it's not in yours then you'll need to add the line or rerun &lt;code&gt;capify .&lt;/code&gt;
&lt;/p&gt;
&lt;p&gt;To support an external gem or plugin you need to let Cached Externals know about it by creating an entry for it in a &lt;code&gt;config/externals.yml&lt;/code&gt; file. The gem or plugin needs to be in an external repository that's accessible locally and on the deployment target. The YAML entry for each external contains information about the type of repository, where it is and which revision is required.
&lt;/p&gt;
&lt;p&gt;If you know the repository and revision information for your gems and plugins then creating the YAML file should be easy.  If you don't have or don't want to list all of the information then start with the big externals. It's a good idea to have an explicit list of this information for all of your gems and plugins but you won't see nearly as much of a performance benefit from the smaller externals.  For my Mephisto application I'd installed the Rails and the TZInfo gems myself but the other gems and plugins came bundled as part of Mephisto so I didn't have any of the revision information and, since I'm only merging in the Mephisto master branch and not maintaining the application details, I was only interested in performance gains, not the management benefit. Digging up data for all the gems and plugins would be more effort than it was worth, especially for some of those unversioned plugins.  So, instead of trying to cache everything, I did a check for low hanging fruit:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ cd vendor
[mac]$ du -sk *
[mac]$ cd plugins
[mac]$ du -sk *
[mac]$ cd ../..
&lt;/pre&gt;
&lt;p&gt;Of course Rails was the monster at about 9.8M, TZInfo was 3.8M, and the other 4 gems only totaled about 700K with the largest being 336K. All 25 plugins totaled 4.8M with RSpec weighing in at 2.1M, RSpec on Rails about 600K and the next largest plugin was only about 300K. So if I only cached 4 of 31 externals: Rails, TZInfo, RSpec and RSpec on Rails, I could cover 16.3 of 19.1 MB.
&lt;/p&gt;
&lt;p&gt;After finding the repositories on github and RubyForge (I'll describe how I found the exact revision information later) I created this &lt;code&gt;config/externals.yml&lt;/code&gt; file:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;vendor/rails:  # v2.0.2&lt;tt&gt;
&lt;/tt&gt;  :type: git&lt;tt&gt;
&lt;/tt&gt;  # DH old git checkout (1.4.4.4) doesn't support -q&lt;tt&gt;
&lt;/tt&gt;  :scm_verbose: true&lt;tt&gt;
&lt;/tt&gt;  :repository: git://github.com/rails/rails.git&lt;tt&gt;
&lt;/tt&gt;  :revision: e454cf721ea2deca1b1b991339a5d30161dcfb9c&lt;tt&gt;
&lt;/tt&gt;vendor/tzinfo-0.3.12:&lt;tt&gt;
&lt;/tt&gt;  :type: subversion&lt;tt&gt;
&lt;/tt&gt;  :repository: http://tzinfo.rubyforge.org/svn/trunk/tzinfo&lt;tt&gt;
&lt;/tt&gt;  :revision: &amp;quot;210&amp;quot;&lt;tt&gt;
&lt;/tt&gt;vendor/plugins/rspec: # pre 1.1.0&lt;tt&gt;
&lt;/tt&gt;  :type: subversion&lt;tt&gt;
&lt;/tt&gt;  :repository: http://rspec.rubyforge.org/svn/trunk/rspec&lt;tt&gt;
&lt;/tt&gt;  :revision: &amp;quot;2962&amp;quot;&lt;tt&gt;
&lt;/tt&gt;vendor/plugins/rspec_on_rails: # pre 1.1.0&lt;tt&gt;
&lt;/tt&gt;  :type: subversion&lt;tt&gt;
&lt;/tt&gt;  :repository: http://rspec.rubyforge.org/svn/trunk/rspec_on_rails&lt;tt&gt;
&lt;/tt&gt;  :revision: &amp;quot;2962&amp;quot;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;The file assumes that Subversion and git are installed on both the local deployment PC and on the deployment target.  If you aren't sure if you have the correct source code control software on the client and target then check for it. For example, I used &lt;code&gt;git --version&lt;/code&gt; and &lt;code&gt;svn --version&lt;/code&gt; on my hosting service to see what was installed. If you're missing an SCM that you need then either install it, delete the appropriate entries in your &lt;code&gt;externals.yml&lt;/code&gt; or move the gem or plugin to another external repository that you can support. 
&lt;/p&gt;
&lt;p&gt;Here are some additional notes about the YAML file:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cached Externals creates a new SCM instance for each repository.  So any SCM option variables that are normally set in &lt;code&gt;deploy.rb&lt;/code&gt; need to be set for each cached item.
&lt;/li&gt;
&lt;li&gt;In my case &lt;code&gt;:scm_verbose&lt;/code&gt; had to be set because my DreamHost server has an old verion of git (1.4.4.4) and the -q (--quiet) flag that's used in git-checkout when &lt;code&gt;:scm_verbose&lt;/code&gt; isn't set won't work with old versions of git.
&lt;/li&gt;
&lt;li&gt;I used the SHA1 code for the Rails revision but it's a tagged release so &lt;code&gt;v2.0.2&lt;/code&gt; could have been used instead.
&lt;/li&gt;
&lt;li&gt;I always use the &lt;code&gt;http://&lt;/code&gt; link for RubyForge subversion repositories. The &lt;code&gt;svn://&lt;/code&gt; transport to RubyForge isn't reliable for me but the &lt;code&gt;http://&lt;/code&gt; transport works fine.  I've never investigated why but I do know it's a common issue.
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The next step is to remove externals referenced in the &lt;code&gt;externals.yml&lt;/code&gt; from the &lt;code&gt;vendor&lt;/code&gt; directory.  If your following along then at this point I'd recommend you're prepared for any problems by having a clean repository (everything's committed or stashed) or by making a backup copy of the vendor items before doing this:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ rm -rf vendor/rails
[mac]$ rm -rf vendor/tzinfo-0.3.12
[mac]$ rm -rf vendor/plugins/rspec
[mac]$ rm -rf vendor/plugins/rspec_on_rails
&lt;/pre&gt;
&lt;p&gt;Somehow that feels uncomfortable, but no worries, the files will get replaced when the local cached copies are retrieved.  Well, actually the files will be placed in a &lt;code&gt;../shared/externals/vendor&lt;/code&gt; directory and symlinks to them will be created in the proper locations in the vendor directory.  Yes, the &lt;code&gt;shared&lt;/code&gt; directory will be at the same level as the application directory.  Here's how to load up the cache:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ cap local externals:setup
&lt;/pre&gt;
&lt;p&gt;That will result in a big retrieval so after it's done it's a good time to make sure everything looks correct with &lt;code&gt;git status&lt;/code&gt;. Here's what I saw with &lt;code&gt;git status&lt;/code&gt; after loading the local cache using the &lt;code&gt;externals.yml&lt;/code&gt; file from above:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ show git status
# On branch robseaman
# Changed but not updated:
#   (use &quot;git add/rm ...&quot; to update what will be committed)
#
#	deleted:    vendor/rails/REVISION_5fa0457542b0ff541d0a80ff8c3561eec8e35959
#	modified:   vendor/tzinfo-0.3.12/lib/tzinfo/ruby_core_support.rb
#	modified:   vendor/tzinfo-0.3.12/test/tc_ruby_core_support.rb
#
# Untracked files:
#   (use &quot;git add ...&quot; to include in what will be committed)
#
#	vendor/plugins/rspec
#	vendor/plugins/rspec_on_rails
#	vendor/rails
#	vendor/tzinfo-0.3.12
no changes added to commit (use &quot;git add&quot; and/or &quot;git commit -a&quot;)
&lt;/pre&gt;
&lt;p&gt;The untracked files were the symlinks, no problem. The deleted &lt;code&gt;rails/REVISION_5fa045...&lt;/code&gt; was just an empty touch file that was created when Rails was frozen into the vendor directory.  It doesn't indicate that the 5fa04575 revision should have used in the &lt;code&gt;externals.yml&lt;/code&gt; file. The 5fa04575... revision number is the SHA1 of the latest commit on github at the time when Rails was downloaded.  There were no other issues in the Rails directory so it looked good.  Ah, but the TZinfo files looked like trouble, so I used git-diff to find out:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ git diff
diff --git a/vendor/rails/REVISION_5fa0457542b0ff541d0a80ff8c3561eec8e35959 \
           b/vendor/rails/REVISION_5fa0457542b0ff541d0a80ff8c3561eec8e35959
deleted file mode 100644
index e69de29..0000000
diff --git a/vendor/tzinfo-0.3.12/lib/tzinfo/ruby_core_support.rb \
           b/vendor/tzinfo-0.3.12/lib/tzinfo/ruby_core_support.rb
old mode 100644
new mode 100755
diff --git a/vendor/tzinfo-0.3.12/test/tc_ruby_core_support.rb \
           b/vendor/tzinfo-0.3.12/test/tc_ruby_core_support.rb
old mode 100644
new mode 100755
&lt;/pre&gt;
&lt;p&gt;Hmm, the only difference was the addition of execute permission on the files.  I'm not sure why the settings were different but it didn't seem like a big deal to me so I considered it good.
&lt;/p&gt;
&lt;p&gt;I was waiting to discuss how I found external revision numbers until I covered &lt;code&gt;cap local externals:setup&lt;/code&gt;, &lt;code&gt;git status&lt;/code&gt; and &lt;code&gt;git diff&lt;/code&gt; because they were a big part of my search. I started by picking likely candidates.  For Rails this was just a matter of using the tags drop-down on github and selecting the revision for v2.0.2. For TZInfo I used svnX to browse the repository on RubyForge and the 0.3.12 release comments were near the top.  For the RSpec plugins I examined &lt;code&gt;CHANGES&lt;/code&gt; file in Mephisto's vendor copy which led me to 1.1.0. I found 1.1.0 and other old versions of RSpec and RSpec on Rails in a Subversion repository on RubyForge, so I used svnX again and plugged the 1.1.0 release revision in &lt;code&gt;externals.yml&lt;/code&gt;.  Then I ran &lt;code&gt;cap local externals:setup&lt;/code&gt; and used a combination of git-status and git-diff to see what was different. Rails and TZInfo matched but the RSpec plugins didn't.  There were enough differences that I ran git-diff on one file at time, trying to pick the file most likely to help me find the correct version.  From the diff of the &lt;code&gt;CHANGES&lt;/code&gt; file I could tell that Mephisto was using a pre-1.1.0 edge version.  Looking at checkin history with svnX gave me a pretty good idea how far back to go, so I trashed the &lt;code&gt;../shared/externals/vendor/plugins&lt;/code&gt; directory, re-ran &lt;code&gt;cap local externals:setup&lt;/code&gt; and checked the differences again. The &lt;code&gt;CHANGES&lt;/code&gt; file didn't have every detail so I ended up having to do this a few times, narrowing it down each time until I found a match.
&lt;/p&gt; 
&lt;p&gt;Given that I was setting this up for an application that I knew little about, I was lucky. If I'd have wanted to do this for a gem or plugin that had been customized I would have had to put the custom version in an external repository like github or left it out of the cache.  Also, all of the externals I looked for were on github or RubyForge, were well tagged and were good about documenting version information in their distribution.  Searching for the RSpec revision gave me an clue about how much of a pain this could have been if good tagging and release documentation practices hadn't been followed.  The lesson here is to not wait until final deployment before you start to keep track of externals; do it as the externals are installed.  
&lt;/p&gt; 
&lt;p&gt;After you're satisfied with your shared cache you'll want to commit the results to source control.  For me that meant:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ git add .
[mac]$ git commit -a -m &quot;Cached Externals: rails, tzinfo &amp; rspec/rspec_rails&quot;
&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;cap local externals:setup&lt;/code&gt; will need to be run anytime &lt;code&gt;externals.yml&lt;/code&gt; is updated.  And, if you're using git, there's one last related housekeeping item.  Cached Externals includes &lt;code&gt;post-checkout&lt;/code&gt; and &lt;code&gt;post-merge&lt;/code&gt; git hooks to automatically makes sure the correct symlinks are used.  They work by running &lt;code&gt;cap local externals:setup&lt;/code&gt; when switching between branches, pulling and merging.  Before installing the hooks check (using &lt;code&gt;ls .git/hooks&lt;/code&gt;) to make sure that you don't already have your own versions of the hooks.  I didn't have either so I used the Cached Externals rake task to install the hooks:
&lt;pre&gt;
[mac]$ rake git:hooks:install
&lt;/pre&gt;
&lt;p&gt;If you already have one or both of the hooks then you'll need to merge in the Cached Externals versions from the plugin's &lt;code&gt;script/git-hooks&lt;/code&gt; directory or decide whether you want your old hooks or the Cached Externals hooks.
&lt;/p&gt;
&lt;p&gt;At this point I did a git-tag to mark the application as a release and then did a new deployment:
&lt;/p&gt;
&lt;pre&gt;$ cap deploy
&lt;/pre&gt;
&lt;p&gt;It's not mandatory to deploy right after setting up Cached Externals but I wanted to isolate it as a separate release in case anything went wrong. The first deployment was slower because it has to clone the external repositories.  I also noticed false error reporting on the git status messages.  You'll probably see the same thing; there will be a lot of messages that look like this:  
&lt;/p&gt;
&lt;pre&gt;
...
*** [err :: blog.robseaman.com] 11% (186/1690) done
*** [err :: blog.robseaman.com] 12% (203/1690) done
*** [err :: blog.robseaman.com] 13% (220/1690) done
...
&lt;/pre&gt;
&lt;p&gt;It looks bad but it's not a problem. It just indicates git must be using the error stream for status reporting. Of course it's a good idea to do some verification that the symlinks and directories look correct after the deployment.  When I checked my results everything was fine.
&lt;/p&gt;
&lt;p&gt;After the first run things should be fast until one or more externals need updating.  For the Mephisto blog my deployment gzip file went from 3.2 MB to under 1 MB with what seemed to be a corresponding time savings.  
&lt;/p&gt;
&lt;h3&gt;Additional Information&lt;/h3&gt;
&lt;p&gt;Cached External's main purpose is to speed up deployments but the way it accomplishes this inherently helps you track and share the externals that you decide to cache. Externals management is a category where there are already several solutions. &lt;a href=&quot;http://piston.rubyforge.org/&quot;&gt;Piston&lt;/a&gt;, &lt;a href=&quot;http://github.com/evilchelu/braid/wikis/home&quot;&gt;Braid&lt;/a&gt;, the &lt;a href=&quot;http://www.kernel.org/pub/software/scm/git/docs/howto/using-merge-subtree.html&quot;&gt;subtree merge strategy&lt;/a&gt;, &lt;a href=&quot;http://www.kernel.org/pub/software/scm/git/docs/git-submodule.html&quot;&gt;git submodules&lt;/a&gt; and &lt;a href=&quot;http://svnbook.red-bean.com/en/1.5/svn.advanced.externals.html&quot;&gt;svn:externals&lt;/a&gt; are some of the more popular ways to manage the vendor externals. Gary Lam has put together a github repository for his &lt;a href=&quot;http://github.com/gary/dependency_management_talk/tree/master&quot;&gt;Dependancy Management Talk&lt;/a&gt; with a &lt;a href=&quot;http://www.apple.com/iwork/keynote/&quot;&gt;Keynote&lt;/a&gt; presentation, example implementations and notes that cover Cached Externals, the solutions I mentioned and others.
&lt;/p&gt; 
&lt;p&gt;Gary's repository is a great resource and this note in his &lt;code&gt;notes.markdown&lt;/code&gt; file caught my attention:
&lt;/p&gt; 
&lt;pre&gt;
* script/generate has issues with symlinks?  
  did not detect generators from symlinked plugins
&lt;/pre&gt;
&lt;p&gt;When I first read Gary's note I did try the &lt;code&gt;rspec_model&lt;/code&gt; generator script from the rspec_on_rails plugin after the symlinks were in place and it worked fine.  After looking into it more I found out that the problem Gary refers to is an &lt;a href=&quot;http://rails.lighthouseapp.com/projects/8994/tickets/449-script-generator-does-not-find-generators-in-symlinked-plugins&quot;&gt;issue with some versions of Rails&lt;/a&gt;. It looks like the problem was &lt;a href=&quot;http://github.com/rails/rails/commit/aa7859c9768f4447b4f67808b2c92f4d0cb48cb2&quot;&gt;fixed in February 2007&lt;/a&gt;, &lt;a href=&quot;http://github.com/rails/rails/commit/dd665ff9679514e354336bb183a9b40ad17145fb&quot;&gt;inadvertently broken as part of another fix in March 2008&lt;/a&gt;  and finally &lt;a href=&quot;http://github.com/rails/rails/commit/84ceff6921a0619de049301a1b8600b51a7e56f8&quot;&gt;fixed again in June, 2008&lt;/a&gt;.  Going by dates it would mean generators in symlinked plugins worked from Rails 1.2.3 to 2.0.2, were broken in Rails 2.0.3 and have worked fine since 2.1.1.  The Mephisto blog uses Rails 2.0.2, so it's not surprising that I didn't see the issue.  If you run into this problem then you'll need to update your Rails version, eliminate the affected plugin from the cache or temporarily replace the symlink with the real thing when you use a generator.
&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://weblog.jamisbuck.org/&quot;&gt;Jamis Buck&lt;/a&gt;, the author of Cached Externals, discussed the importance of deployment performance and how Cached Externals is different than other Capistrano caching techniques in his  &lt;em&gt;&lt;a href=&quot;http://www.37signals.com/svn/posts/1364-cachedexternals-managing-application-dependencies&quot;&gt;
CachedExternals: managing application dependencies&lt;/a&gt;&lt;/em&gt; post on the &lt;a href=&quot;http://blogcabin.37signals.com/svn/&quot;&gt;Signal vs. Noise&lt;/a&gt; blog.  Finally, I should mention that I found out about Cached External from &lt;a href=&quot;http://railsenvy.com/2008/11/5/rails-envy-podcast-episode-054-11-05-2008&quot;&gt;a Rails Envy podcast&lt;/a&gt;.
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.robseaman.com/">
    <author>
      <name>Rob</name>
    </author>
    <id>tag:blog.robseaman.com,2008-12-02:7</id>
    <published>2008-12-02T01:01:00Z</published>
    <updated>2008-12-02T01:25:40Z</updated>
    <category term="Website Setup"/>
    <category term="capistrano"/>
    <category term="mysql"/>
    <category term="rsync"/>
    <link href="http://blog.robseaman.com/2008/12/2/production-data-to-development" rel="alternate" type="text/html"/>
    <title>Production Data to Development</title>
<summary type="html">&lt;p&gt;It's often helpful to be able to bring MySQL production data down to a development machine.  I wanted to do this for my Mephisto blog engine (see &lt;a href=&quot;http://blog.robseaman.com/2008/12/1/gitting-started-with-mephisto&quot;&gt;gitting Started with Mephisto&lt;/a&gt; and &lt;a href=&quot;http://blog.robseaman.com/2008/12/1/deploying-mephisto-with-capistrano-to-dreamhost&quot;&gt;Deploying Mephisto with Capistrano to DreamHost&lt;/a&gt;) so that I could see how changes would look with existing data before deploying an update.  Production data is also useful for tracking down bugs with production data and for backups. This post describes the &lt;a href=&quot;http://www.capify.org/&quot;&gt;Capistrano&lt;/a&gt;  namespace I created for doing this.</summary><content type="html">
            &lt;p&gt;It's often helpful to be able to bring MySQL production data down to a development machine.  I wanted to do this for my Mephisto blog engine (see &lt;a href=&quot;http://blog.robseaman.com/2008/12/1/gitting-started-with-mephisto&quot;&gt;gitting Started with Mephisto&lt;/a&gt; and &lt;a href=&quot;http://blog.robseaman.com/2008/12/1/deploying-mephisto-with-capistrano-to-dreamhost&quot;&gt;Deploying Mephisto with Capistrano to DreamHost&lt;/a&gt;) so that I could see how changes would look with existing data before deploying an update.  Production data is also useful for tracking down bugs with production data and for backups. This post describes the &lt;a href=&quot;http://www.capify.org/&quot;&gt;Capistrano&lt;/a&gt;  namespace I created for doing this. 

&lt;/p&gt;
&lt;p&gt;Before writing my own code I googled and found that Peter Harkins had posted &lt;em&gt;&lt;a href=&quot;http://push.cx/2007/capistrano-task-to-load-production-data&quot;&gt;Capistrano Task to Load Production Data&lt;/a&gt;&lt;/em&gt; with an implementation that did basically what I wanted.  I also found a &lt;a href=&quot;http://codesnippets.joyent.com/posts/show/1215&quot;&gt;Joyent CodeSnippets post&lt;/a&gt; from &lt;a href=&quot;http://tramchase.com&quot;&gt;Jamie Wilkinson&lt;/a&gt; that was based on Peter's code but added support for Capistrano 2.0 and gzip before doing the download. I didn't need the gzip support so I started with Peter's code.  I'm using Capistrano 2.5.2 and I added additional code to include downloading files in the &lt;code&gt;public/assets&lt;/code&gt; directory, pull the production database connection information from the server (instead of the development &lt;code&gt;database.yml&lt;/code&gt;), get the password off of the &lt;code&gt;mysqldump&lt;/code&gt; command line, split the download from the load to provide cached loading and backup functionality, and use &lt;a href=&quot;http://samba.anu.edu.au/ftp/rsync/rsync.html&quot;&gt;rsync&lt;/a&gt; delta transfers to speed up the transfers.
&lt;/p&gt;
&lt;p&gt;With those changes I ended up with a larger (but still not big) implementation with three tasks in a namespace called &lt;code&gt;data&lt;/code&gt;.  You could load this from a separate recipe file but I just added it to the end of my &lt;code&gt;deploy.rb&lt;/code&gt; file.  Here's the namespace:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;62&lt;tt&gt;
&lt;/tt&gt;63&lt;tt&gt;
&lt;/tt&gt;64&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;65&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;66&lt;tt&gt;
&lt;/tt&gt;67&lt;tt&gt;
&lt;/tt&gt;68&lt;tt&gt;
&lt;/tt&gt;69&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;70&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;71&lt;tt&gt;
&lt;/tt&gt;72&lt;tt&gt;
&lt;/tt&gt;73&lt;tt&gt;
&lt;/tt&gt;74&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;75&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;76&lt;tt&gt;
&lt;/tt&gt;77&lt;tt&gt;
&lt;/tt&gt;78&lt;tt&gt;
&lt;/tt&gt;79&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;80&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;81&lt;tt&gt;
&lt;/tt&gt;82&lt;tt&gt;
&lt;/tt&gt;83&lt;tt&gt;
&lt;/tt&gt;84&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;85&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;86&lt;tt&gt;
&lt;/tt&gt;87&lt;tt&gt;
&lt;/tt&gt;88&lt;tt&gt;
&lt;/tt&gt;89&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;90&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;91&lt;tt&gt;
&lt;/tt&gt;92&lt;tt&gt;
&lt;/tt&gt;93&lt;tt&gt;
&lt;/tt&gt;94&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;95&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;96&lt;tt&gt;
&lt;/tt&gt;97&lt;tt&gt;
&lt;/tt&gt;98&lt;tt&gt;
&lt;/tt&gt;99&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;100&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;101&lt;tt&gt;
&lt;/tt&gt;102&lt;tt&gt;
&lt;/tt&gt;103&lt;tt&gt;
&lt;/tt&gt;104&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;105&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;106&lt;tt&gt;
&lt;/tt&gt;107&lt;tt&gt;
&lt;/tt&gt;108&lt;tt&gt;
&lt;/tt&gt;109&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;110&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;111&lt;tt&gt;
&lt;/tt&gt;112&lt;tt&gt;
&lt;/tt&gt;113&lt;tt&gt;
&lt;/tt&gt;114&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;115&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;116&lt;tt&gt;
&lt;/tt&gt;117&lt;tt&gt;
&lt;/tt&gt;118&lt;tt&gt;
&lt;/tt&gt;119&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;120&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;121&lt;tt&gt;
&lt;/tt&gt;122&lt;tt&gt;
&lt;/tt&gt;123&lt;tt&gt;
&lt;/tt&gt;124&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;125&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;126&lt;tt&gt;
&lt;/tt&gt;127&lt;tt&gt;
&lt;/tt&gt;128&lt;tt&gt;
&lt;/tt&gt;129&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;130&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;131&lt;tt&gt;
&lt;/tt&gt;132&lt;tt&gt;
&lt;/tt&gt;133&lt;tt&gt;
&lt;/tt&gt;134&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;135&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;136&lt;tt&gt;
&lt;/tt&gt;137&lt;tt&gt;
&lt;/tt&gt;138&lt;tt&gt;
&lt;/tt&gt;139&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# Derived from http://push.cx/2007/capistrano-task-to-load-production-data&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;namespace &lt;span class=&quot;sy&quot;&gt;:data&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;yaml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  set &lt;span class=&quot;sy&quot;&gt;:sql_dump_file&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;dump.&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;application&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;.sql&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  desc &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;lt;&amp;lt;-DESC&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;k&quot;&gt;&lt;tt&gt;
&lt;/tt&gt;    Get production data and load it into development. A new copy of the&lt;tt&gt;
&lt;/tt&gt;    production database and production public/assets are cached and&lt;tt&gt;
&lt;/tt&gt;    loaded into the development environment.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&lt;tt&gt;
&lt;/tt&gt;  DESC&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  task &lt;span class=&quot;sy&quot;&gt;:load_from_prod&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    cache_prod_data&lt;tt&gt;
&lt;/tt&gt;    load_from_cache&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  desc &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;lt;&amp;lt;-DESC&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;k&quot;&gt;&lt;tt&gt;
&lt;/tt&gt;    Get production and cache it locally. The production database and &lt;tt&gt;
&lt;/tt&gt;    production public/assets directory are downloaded and cached.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&lt;tt&gt;
&lt;/tt&gt;  DESC&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  task &lt;span class=&quot;sy&quot;&gt;:cache_prod_data&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:roles&lt;/span&gt; =&amp;gt; &lt;span class=&quot;sy&quot;&gt;:db&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:only&lt;/span&gt; =&amp;gt; { &lt;span class=&quot;sy&quot;&gt;:primary&lt;/span&gt; =&amp;gt; &lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt; } &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    on_rollback { run &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;rm &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;current_path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/tmp/&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;sql_dump_file&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;yaml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    database_yml = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    run &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cat &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;current_path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/config/database.yml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |_, _, database_yml| &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    config = &lt;span class=&quot;co&quot;&gt;YAML&lt;/span&gt;::load(database_yml)[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;production&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;    run &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mysqldump &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;mysql_options(config, &lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt;)&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; &amp;gt; &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;current_path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/tmp/&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;sql_dump_file&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |ch, _, out| &lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; out =~ &lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;^Enter password: &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        ch.send_data &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;config[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        puts out &lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;co&quot;&gt;FileUtils&lt;/span&gt;.mkdir_p(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;tmp/data/public/assets&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    logger.debug &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;rsyncing &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;sql_dump_file&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; from &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;application&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    system &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;rsync -lrp &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;user&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;application&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;current_path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/tmp/&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;sql_dump_file&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; tmp/data&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    run &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;rm &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;current_path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/tmp/&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;sql_dump_file&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;    logger.debug &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;rsyncing assets from &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;application&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    system &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;rsync -lrp --delete &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+&lt;tt&gt;
&lt;/tt&gt;             &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;user&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;application&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;shared_path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/assets tmp/data/public&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  desc &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;lt;&amp;lt;-DESC&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;k&quot;&gt;&lt;tt&gt;
&lt;/tt&gt;    (Re)load cached production data into development. Use&lt;tt&gt;
&lt;/tt&gt;    data:cache_prod_data or data:load_from_prod to create the cache.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&lt;tt&gt;
&lt;/tt&gt;  DESC&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  task &lt;span class=&quot;sy&quot;&gt;:load_from_cache&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    config = &lt;span class=&quot;co&quot;&gt;YAML&lt;/span&gt;::load_file(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;config/database.yml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;development&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.exist?(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;tmp/data/&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;sql_dump_file&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;tt&gt;
&lt;/tt&gt;      mysql_load = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mysql &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;mysql_options(config)&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; &amp;lt; tmp/data/&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;sql_dump_file&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      logger.debug &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;%(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;executing &amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;mysql_load.sub(&lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;-p&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\S&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;-px&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      system mysql_load &lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;co&quot;&gt;FileUtils&lt;/span&gt;.rm_rf(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;public/assets/*&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;co&quot;&gt;FileUtils&lt;/span&gt;.cp_r(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;tmp/data/public/assets&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      abort &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;The data cache is empty, try 'cap data:load_from_prod'&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;# Return MySQL options for a specific configuration.&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;mysql_options&lt;/span&gt;(config, prompt_for_password=&lt;span class=&quot;pc&quot;&gt;false&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; config[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;] &lt;tt&gt;
&lt;/tt&gt;      password_opt = prompt_for_password ? &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; -p&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; : &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; -p&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;config[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      password_opt = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;-u &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;config[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; -h &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;config[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;config[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;database&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+ &lt;tt&gt;
&lt;/tt&gt;    password_opt&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;And here's a breakdown of the tasks and their features:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cap data:cache_prod_data&lt;/code&gt; dumps and downloads the latest copy of the production database and the public/assets directory.  The database configuration is pulled from the &lt;code&gt;database.yml&lt;/code&gt; on the server so no account information is needed on the local machine. The MySQL password is kept out of the command line so it's left out of the Capistrano log and out of the process list (see &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/1/hiding-mysql-passwords-with-capistrano&quot;&gt;Hiding MySQL Passwords with Capistrano&lt;/a&gt;&lt;/em&gt;).  The download uses &lt;a href=&quot;http://samba.anu.edu.au/ftp/rsync/rsync.html&quot;&gt;rsync&lt;/a&gt; to a cache in the local &lt;code&gt;tmp/data&lt;/code&gt; directory.  This is intended to make the transfer fast and eliminate the need for a creating new dump when reloading a previous dump is good enough.  &lt;code&gt;data:cache_prod_data&lt;/code&gt; is used as a step in &lt;code&gt;data:load_from_prod&lt;/code&gt; but is also useful as standalone task for getting a backup copy of the database.  It could be used in a crontab as is with backup software like Time Machine taking care of versioning.  Alternatively, with some additional software you could create time stamped compressed versions of the &lt;code&gt;tmp/data&lt;/code&gt; directory after download.
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cap data:load_from_cache&lt;/code&gt; will reload a the last version of the production data, printing an error if the data doesn't exist in the local cache.  This eliminates the dump and transfer when you're fine with just restarting with a fresh copy of the last downloaded version of production data. One scenario is that you've mucking with production data in the development environment and want to reload a fresh copy. Another is that you're doing regular back-ups using &lt;code&gt;data:cache_prod_data&lt;/code&gt; during off hours and the cache contains current enough information for your development testing.
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cap data:load_from_prod&lt;/code&gt; downloads the current production data into the cache and development environment by combining &lt;code&gt;data:cache_prod_data&lt;/code&gt; and &lt;code&gt;data:load_from_cache&lt;/code&gt;.  If you always want the latest copy of production data you can use this task and forget about the other two.
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Limitations&lt;/h3&gt;
&lt;p&gt;I'm sure there are lot more than this but the obvious ones are:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The code specific to MySQL and specific to moving from production to development.
&lt;/li&gt;
&lt;li&gt;It does a complete database dump.  I think the rsync delta transfer and caching are sweet but if your database is quite big then some form of delta dumping and loading of the database will also be needed. Perhaps tracking changes since the last backup using some type of journaling or a similar technology along with smarter dumping. 
&lt;/li&gt;
&lt;li&gt;The entire production database is made available on a development machine.  That's fine for many applications but if you have privacy concerns about the contents of the production database then copying the production database to a development machine isn't a good idea and in some cases, such as the need to comply with &lt;a href=&quot;http://www.hhs.gov/ocr/hipaa/&quot;&gt;HIPPA&lt;/a&gt; regulations, it may even be a legal violation.  In those situations you'll need to be smarter on the server side and either obfuscate or limit the what data is transfered.
&lt;/li&gt;
&lt;li&gt;MySQL vulnerabilities to process list visibility are handled on the production server but not on the development client. &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/1/hiding-mysql-passwords-with-capistrano&quot;&gt;Hiding MySQL Passwords with Capistrano&lt;/a&gt;&lt;/em&gt; describes the scope of the issue and suggestions for possible solutions if this is a problem in your environment.
&lt;/li&gt;
&lt;/ol&gt;
          </content>  </entry>
  <entry xml:base="http://blog.robseaman.com/">
    <author>
      <name>Rob</name>
    </author>
    <id>tag:blog.robseaman.com,2008-12-01:9</id>
    <published>2008-12-01T22:16:00Z</published>
    <updated>2008-12-04T17:26:54Z</updated>
    <category term="Security"/>
    <category term="capistrano"/>
    <category term="mysql"/>
    <link href="http://blog.robseaman.com/2008/12/1/hiding-mysql-passwords-with-capistrano" rel="alternate" type="text/html"/>
    <title>Hiding MySQL Passwords with Capistrano</title>
<summary type="html">&lt;p&gt;I was using &lt;a href=&quot;http://www.capify.org/&quot;&gt;Capistrano&lt;/a&gt; 2.5.2 to run a MySQL dump on a deployment target and what started as a simple implementation to prevent the command line password from showing up in the Capistrano log evolved into a research effort about the security of using passwords on the MySQL command line.  This post describes how to suppress &lt;code&gt;run&lt;/code&gt; execution lines from showing up in the Capistrano log, the real risks with using passwords on the MySQL command line and how to use Capistrano to avoid command line passwords without putting the password in a &lt;code&gt;~/.my.cnf&lt;/code&gt; file.</summary><content type="html">
            &lt;p&gt;I was using &lt;a href=&quot;http://www.capify.org/&quot;&gt;Capistrano&lt;/a&gt; 2.5.2 to run a MySQL dump on a deployment target and what started as a simple implementation to prevent the command line password from showing up in the Capistrano log evolved into a research effort about the security of using passwords on the MySQL command line.  This post describes how to suppress &lt;code&gt;run&lt;/code&gt; execution lines from showing up in the Capistrano log, the real risks with using passwords on the MySQL command line and how to use Capistrano to avoid command line passwords without putting the password in a &lt;code&gt;~/.my.cnf&lt;/code&gt; file.

&lt;/p&gt;
&lt;p&gt;I'll start from the beginning ... the Capistrano logger level is set to &lt;code&gt;DEBUG&lt;/code&gt; by default and that caused MySQL command line passwords to be displayed/logged whenever MySQL was invoked via &lt;code&gt;run&lt;/code&gt;.  I didn't like that so I came up with a very direct solution to hide the password and leave everything else alone.  Here's the code segment from a Capistrano task to do that:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;98&lt;tt&gt;
&lt;/tt&gt;99&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;100&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;101&lt;tt&gt;
&lt;/tt&gt;102&lt;tt&gt;
&lt;/tt&gt;103&lt;tt&gt;
&lt;/tt&gt;104&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;105&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;106&lt;tt&gt;
&lt;/tt&gt;107&lt;tt&gt;
&lt;/tt&gt;108&lt;tt&gt;
&lt;/tt&gt;109&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;110&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;111&lt;tt&gt;
&lt;/tt&gt;112&lt;tt&gt;
&lt;/tt&gt;113&lt;tt&gt;
&lt;/tt&gt;114&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;115&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;116&lt;tt&gt;
&lt;/tt&gt;117&lt;tt&gt;
&lt;/tt&gt;118&lt;tt&gt;
&lt;/tt&gt;119&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;yaml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;database_yml = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;run &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cat &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;current_path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/config/database.yml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |_, _, database_yml| &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;config = &lt;span class=&quot;co&quot;&gt;YAML&lt;/span&gt;::load(database_yml)[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;production&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;mysql_dump = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mysqldump -u &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;config[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; -p&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;config[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;-h &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;config[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;config[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;database&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; &amp;gt; &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;current_path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/tmp/dump.sql&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;c&quot;&gt;# surpress debug log output to hide the password&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;current_logger_level = &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.logger.level&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; current_logger_level &amp;gt;= &lt;span class=&quot;co&quot;&gt;Capistrano&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Logger&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;DEBUG&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  logger.debug &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;%(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;executing &amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;mysql_dump.sub(&lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;-p&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\S&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;-px&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.logger.level = &lt;span class=&quot;co&quot;&gt;Capistrano&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Logger&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;INFO&lt;/span&gt; &lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;run mysql_dump &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |ch, _, out| &lt;tt&gt;
&lt;/tt&gt;  puts out &lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;c&quot;&gt;# restore logger level&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.logger.level = current_logger_level&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;It worked and I was satisfied for a while but a FIXME comment in a &lt;a href=&quot;http://codesnippets.joyent.com/posts/show/1215&quot;&gt;Joyent CodeSnippets post&lt;/a&gt; with similar code started bothering me:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# FIXME pass shows up in process list, &lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;c&quot;&gt;# do not use in shared hosting!!! Use a .my.cnf instead&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;I knew, or I thought I knew, that MySQL took care of hiding passwords on the process list but I decided to verify how they did it. I found a lot of posts from from people claiming there was no protection at all and several others that like me thought MySQL had the issue resolved. Eventually I looked at the C source and found some good posts.  Here's what I found:
&lt;/p&gt;
&lt;p&gt;There's a window of time when MySQL command line passwords are visible on the process list. That's not to say that you can always just grab MySQL command line passwords with &lt;code&gt;ps -ef&lt;/code&gt; as many posts claim. Despite posts to the contrary, MySQL is smart enough to try to hide command line passwords and, for the most popular Unix systems, this works.  In general the window of vulnerability only exists between the time a MySQL tool is launched and the time the MySQL code does the hiding (see &lt;a href=&quot;http://bugs.mysql.com/bug.php?id=2271&quot;&gt;here&lt;/a&gt;).  Since it processes command line arguments very early, it's a small window. I read claims that you could put &lt;code&gt;ps&lt;/code&gt; in a loop to exploit the window and find passwords.  I never saw any proof that something so simplistic would work and given the frequency of command execution and the small window size I have my doubts. On the other hand, I'm sure it's possible to come up with some programatic way to exploit the window and then there's always the chance that someone could have lucky timing with a single &lt;code&gt;ps -ef&lt;/code&gt;.  
&lt;/p&gt;
&lt;p&gt;The hiding is done by modifying the password argv like this: &lt;code&gt;while (*argument) *argument++= 'x';&lt;/code&gt; then if it's the last argument it gets truncated to 0 length.  From my search on the MySQL 5.1.30 source this hiding technique appears to be done for all commands, it's definitely done for &lt;code&gt;mysql&lt;/code&gt;, &lt;code&gt;mysqldump&lt;/code&gt; and &lt;code&gt;mysqladmin&lt;/code&gt;. I already mentioned the window of vulnerability but there are two additional issues: First, unless the password is the last command line argument, its length can be determined by counting the x's.  I didn't look at source for older versions but the x'ing out seems to have been in place for a very long time. On a 4.0.23 implementation that I have on &lt;a href=&quot;http://www.phpwebhosting.com/&quot;&gt;phpwebhosting.com&lt;/a&gt; the x'ing out worked but the truncation didn't, from &lt;a href=&quot;http://lists.mysql.com/internals/17475?f=plain&quot;&gt;this post&lt;/a&gt; it appears to have been fixed in 4.1.
&lt;/p&gt;
&lt;p&gt;The bigger issue is that the method won't work for all Unix systems. It seems to be fine for some systems like Linux and Darwin (OS X) but not for others like &lt;a href=&quot;http://bugs.mysql.com/bug.php?id=11952&quot;&gt;Slackware that don't overwrite the process list entries when argv's are changed&lt;/a&gt;.  The theory is that it works for the &lt;a href=&quot;http://en.wikipedia.org/wiki/BSD&quot;&gt;BSD-ish&lt;/a&gt; Unix versions and not for the &lt;a href=&quot;http://en.wikipedia.org/wiki/System_V&quot;&gt;SysV-ish&lt;/a&gt; flavors.  May be, but during my search I did see what looked like a credible report that one user could see passwords after moving from Linux to FreeBSD. I'm curious about that but not so curious that I'm willing to create a FreeBSD VM with MySQL to check it out. It's easy to verify whether or not password hiding works on your system by starting &lt;code&gt;mysql&lt;/code&gt; and then opening up another process and running &lt;code&gt;ps -ef&lt;/code&gt;. On most Unix system you'll see the password x'd out as in &lt;code&gt;-px xxxxxxxx&lt;/code&gt; or just &lt;code&gt;-px&lt;/code&gt;. &lt;code&gt;-px&lt;/code&gt; will show up alone if the &lt;code&gt;-p&lt;/code&gt; option is the last command line argument.    
&lt;/p&gt;
&lt;p&gt;In many environments the issues I mentioned just aren't real problems. Even some shared hosting environments manage to keep the process list private, this is true on &lt;a href=&quot;http://dreamhost.com/&quot;&gt;DreamHost&lt;/a&gt; for example, so it's only an issue within your own accounts.  OTH in other environments it is a big deal. Even if the password hiding works, if your processes show up when someone else does a &lt;code&gt;ps -ef&lt;/code&gt; at just the right time they'll get your password.  Now, I'm not trying to say that the MySQL password hiding is bogus. Security is almost always a matter of degree and the technique used protects passwords far better then doing nothing.  That said, it seems wise not to use a command line password in a shared environment if it can be avoided and fortunately that's easy.
&lt;/p&gt;
&lt;h3&gt;Avoiding the MySQL --password Option with Capistrano&lt;/h3&gt;
&lt;p&gt;The general recommendation I found to avoid the &lt;code&gt;--password&lt;/code&gt; option is in line with the comment from the Joyent CodeSnippets post, put the password in &lt;code&gt;~/.my.cnf&lt;/code&gt;.  That allows you to avoid command line passwords with any scripting tool including Capistrano.  The downside is it means another configuration step to setup &lt;code&gt;~/.my.cnf&lt;/code&gt; and you have a plaintext password in an additional file (it's already in &lt;code&gt;database.yml&lt;/code&gt; for Rails).  In my Capistrano script I'm already loading the production server's &lt;code&gt;database.yml&lt;/code&gt; so I decided to handle it in the &lt;code&gt;run&lt;/code&gt; block by interactively responding to MySQL's password prompt.  Here's the code fragment:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;98&lt;tt&gt;
&lt;/tt&gt;99&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;100&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;101&lt;tt&gt;
&lt;/tt&gt;102&lt;tt&gt;
&lt;/tt&gt;103&lt;tt&gt;
&lt;/tt&gt;104&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;105&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;106&lt;tt&gt;
&lt;/tt&gt;107&lt;tt&gt;
&lt;/tt&gt;108&lt;tt&gt;
&lt;/tt&gt;109&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;110&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;111&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;yaml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;database_yml = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;run &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cat &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;current_path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/config/database.yml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |_, _, database_yml| &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;config = &lt;span class=&quot;co&quot;&gt;YAML&lt;/span&gt;::load(database_yml)[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;production&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;run &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mysqldump -u &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;config[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; -p -h &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;config[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;config[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;database&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; &amp;gt; &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;current_path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/tmp/dump.sql&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |ch, _, out| &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; out =~ &lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;^Enter password: &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    ch.send_data &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;config[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    puts out &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Since we're using a SSH channel the password is protected and as a bonus the code for suppressing log output is no longer needed making the code segment shorter and cleaner.   &lt;em&gt;If you want to see the task that actually uses this snippet then take a look at the the &lt;code&gt;data:cache_prod_data&lt;/code&gt; task in the &lt;a href=&quot;http://blog.robseaman.com/2008/12/2/production-data-to-development&quot;&gt;Production Data to Development&lt;/a&gt; post.&lt;/em&gt;
&lt;/p&gt;
&lt;h3&gt;Limitations&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;run&lt;/code&gt; code block solution is for executing on a remote server. It doesn't address executing MySQL commands from the local deployment client.  Before trying to solve it you should consider whether or not you really need to. There's no logging issue when executing local commands and the process list security limitations aren't as likely to be a problem; they weren't for me.  But, if this is something you need to or want to take care of then you'll need to use &lt;code&gt;~/.my.cnf&lt;/code&gt; or investigate ways to respond to the MySQL password prompt. Handling the prompt would mean leaving the simple Ruby subprocess methods like &lt;code&gt;%x&lt;/code&gt;, &lt;code&gt;`&lt;/code&gt;, &lt;code&gt;exec&lt;/code&gt; and &lt;code&gt;system&lt;/code&gt; behind.  &lt;code&gt;PTY.spawn&lt;/code&gt; and &lt;code&gt;expect&lt;/code&gt; would probably work and look very similar to the &lt;code&gt;run&lt;/code&gt; code block but &lt;code&gt;pty&lt;/code&gt; is Unix specific. You may also be able to get &lt;code&gt;popen&lt;/code&gt; to work but I'm not sure how you'd handle the prompting with &lt;code&gt;popen&lt;/code&gt;.
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.robseaman.com/">
    <author>
      <name>Rob</name>
    </author>
    <id>tag:blog.robseaman.com,2008-12-01:6</id>
    <published>2008-12-01T07:32:00Z</published>
    <updated>2008-12-03T20:16:48Z</updated>
    <category term="Website Setup"/>
    <category term="capistrano"/>
    <category term="dreamhost"/>
    <category term="git"/>
    <category term="mephisto"/>
    <link href="http://blog.robseaman.com/2008/12/1/deploying-mephisto-with-capistrano-to-dreamhost" rel="alternate" type="text/html"/>
    <title>Deploying Mephisto with Capistrano to DreamHost</title>
<summary type="html">&lt;p&gt;This post describes how to use &lt;a href=&quot;http://www.capify.org/&quot;&gt;Capistrano&lt;/a&gt; to deploy a &lt;a href=&quot;http://mephistoblog.com/&quot;&gt;Mephisto&lt;/a&gt; based blogging engine to a DreamHost account running &lt;a href=&quot;http://www.modrails.com/&quot;&gt;Phusion Passenger&lt;/a&gt;.  The blog code is deployed from a local &lt;a href=&quot;http://git.or.cz/&quot;&gt;git&lt;/a&gt; repository. &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/1/gitting-started-with-mephisto&quot;&gt;gitting Started with Mephisto&lt;/a&gt;&lt;/em&gt; describes how the repository was set-up.  With some modifications the script and commands presented here should be adaptable to other hosting services and other Phusion based Rails applications.</summary><content type="html">
            &lt;p&gt;This post describes how to use &lt;a href=&quot;http://www.capify.org/&quot;&gt;Capistrano&lt;/a&gt; to deploy a &lt;a href=&quot;http://mephistoblog.com/&quot;&gt;Mephisto&lt;/a&gt; based blogging engine to a DreamHost account running &lt;a href=&quot;http://www.modrails.com/&quot;&gt;Phusion Passenger&lt;/a&gt;.  The blog code is deployed from a local &lt;a href=&quot;http://git.or.cz/&quot;&gt;git&lt;/a&gt; repository. &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/1/gitting-started-with-mephisto&quot;&gt;gitting Started with Mephisto&lt;/a&gt;&lt;/em&gt; describes how the repository was set-up.  With some modifications the script and commands presented here should be adaptable to other hosting services and other Phusion based Rails applications.

&lt;/p&gt;
&lt;p&gt;This was my first use of Capistrano.  To get a foundation I watched the &lt;a href=&quot;https://peepcode.com/products/capistrano-2&quot;&gt;PeepCode, Capistrano 2&lt;/a&gt; screencast, read the &lt;a href=&quot;http://www.capify.org/getting-started/from-the-beginning&quot;&gt;From the Beginning&lt;/a&gt; page at the Capistrano site, and watched the &lt;a href=&quot;http://railscasts.com/episodes/133-capistrano-tasks&quot;&gt;Capistrano Tasks&lt;/a&gt; &lt;a href=&quot;http://railscasts.com&quot;&gt;Railscast&lt;/a&gt;.  All of those were good resources, the Railscast episode from Ryan Bates was particularly applicable due to Ryan's use of git and coverage of assets.  The best coming up to speed tip that I can provide is to open up the gem source code and use it as a reference.  Pay particular attention to the &lt;code&gt;lib/capistrano/recipes/deploy.rb&lt;/code&gt; file.  It contains the default tasks, contains a large chunk of the built-in variables and makes the deployment execution order clear.
&lt;/p&gt;
&lt;h3&gt;Server Prerequisites&lt;/h3&gt;
&lt;p&gt;If you haven't set up a user account with SSH access that Capistrano can use for deployment then do it now.  Any existing user account will do but one minor point that may affect the username you choose is that your web directory will eventually reside somewhere under one of your users home path, i.e. it'll end up some place like &lt;em&gt;/home/username/mywebapp.com/current/public&lt;/em&gt;. I created a user called rsblog to house and deploy my blog application.  Setting up a separate deployment user would also be a reasonable choice but DreamHost doesn't provide superuser (sudo) access. So if you go that way you'll need to configure group permissions to allow you to deploy files to the application user's directory tree.
&lt;/p&gt;
&lt;p&gt;Capistrano supports a &lt;code&gt;:password&lt;/code&gt; variable that will allow you to put a password in your script but it's more secure to setup a public key instead.  If you haven't done that then  &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/11/30/ssh-with-leopard&quot;&gt;DreamHost SSH Access with Leopard.html&lt;/a&gt;&lt;/em&gt; walks you through the setup if you have Mac Leopard. For other systems you can start with the &lt;a href=&quot;http://wiki.dreamhost.com/SSH&quot;&gt;DreamHost SSH Wiki&lt;/a&gt;.  
&lt;/p&gt;
&lt;p&gt;You'll also need to create a database for Mephisto on the DreamHost server.  To do that open up your control panel to the &lt;a href=&quot;https://panel.dreamhost.com/index.cgi?tree=goodies.mysql&amp;amp;&quot;&gt;Goodies &gt; Manage MySQL&lt;/a&gt; section and create one using the &lt;em&gt;Create a new MySQL database:&lt;/em&gt; section. The database name has to be unique so the default name in the &lt;code&gt;database.yml&lt;/code&gt; file, mephisto_production, probably won't work. A common approach is to prefix the name you want with your domain name, for example, I used robseaman_mephisto_production. When you create the database it's a good idea to create a new user that only has database access rather than using a shell account.  You can do this by selecting &lt;em&gt;Create a new user now...&lt;/em&gt; from the &lt;strong&gt;First User:&lt;/strong&gt; drop down in the &lt;em&gt;Create a new MySQL database:&lt;/em&gt; section.  The concept is that separate accounts will limit your vulnerability if one of your accounts is compromised (you know, stolen, hacked into, etc...). In general creating separate accounts for different roles with each account having just enough permissions to do its job is a common and solid practice.  That (along with plagiarism) is the basis for why there's a separate &lt;em&gt;deploy&lt;/em&gt; user account in so many of the Capistrano examples.  If this is a new concept to you and you start applying it then be sure to use some common sense in your role breakdowns, too many accounts create administration headaches. Ah, but I digress ... back to the subject.
&lt;/p&gt;
&lt;h3&gt;Capistrano Setup&lt;/h3&gt;
&lt;p&gt;The current version of Capistrano is 2.5.2 as I'm writing this.  Upgrade if you have an older version. If you haven't installed Capistrano yet then the gem is installed in the usual way:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ sudo gem install capistrano
&lt;/pre&gt;
&lt;p&gt;Great, easy as Ruby, now it's time to &quot;capify&quot; the application. This will create the &lt;code&gt;Capfile&lt;/code&gt; and &lt;code&gt;config/deploy.rb&lt;/code&gt; files and keep our repository clean:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ cd mephisto
[mac]$ capify .
[mac]$ git add .
[mac]$ git commit -a -m &quot;Initial versions from capify.&quot;
&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Capfile&lt;/code&gt; doesn't need any changes.  &lt;code&gt;config/deploy.rb&lt;/code&gt; needs extensive overhauling.  There's a &lt;code&gt;config/deploy.example.rb&lt;/code&gt; that Mephisto provides but I didn't use it and if you're following along and using the same or similar environment then I think you'll end up with a fewer modifications if you just use mine.  I'll show it in chunks so I can describe its contents.  Here's part one: 
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# Settings that change from app to app&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;set &lt;span class=&quot;sy&quot;&gt;:user&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;rsblog&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;set &lt;span class=&quot;sy&quot;&gt;:application&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;blog.robseaman.com&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;set &lt;span class=&quot;sy&quot;&gt;:scm&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:git&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;set &lt;span class=&quot;sy&quot;&gt;:branch&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;robseaman&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# &amp;quot;master&amp;quot; would be more typical&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;set &lt;span class=&quot;sy&quot;&gt;:repository&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;file:///Users/Rob/work/mephisto/.git&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;set &lt;span class=&quot;sy&quot;&gt;:deploy_via&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:copy&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;set &lt;span class=&quot;sy&quot;&gt;:git_shallow_clone&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;set &lt;span class=&quot;sy&quot;&gt;:copy_exclude&lt;/span&gt;, [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;.git&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;.gitignore&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;set &lt;span class=&quot;sy&quot;&gt;:deploy_to&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/home/&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;user&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;application&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;You'll need to change some of this first part of &lt;code&gt;deploy.com&lt;/code&gt; to your own settings. Here's an overview:  The &lt;code&gt;user&lt;/code&gt;&lt;sup&gt;2&lt;/sup&gt; is your SSH user account that you have setup to do the deployment.  The &lt;code&gt;application&lt;/code&gt;&lt;sup&gt;3&lt;/sup&gt; is the domain name. I created a separate &lt;code&gt;git&lt;/code&gt; &lt;sup&gt;4&lt;/sup&gt; &lt;code&gt;branch&lt;/code&gt;&lt;sup&gt;5&lt;/sup&gt; from master to keep my changes separate from the open source version of Mephisto.  Replace it with whatever branch you want to deploy.  Since I'm using a local file &lt;code&gt;repository&lt;sup&gt;6&lt;/sup&gt;&lt;/code&gt; from my laptop I chose the &lt;code&gt;copy&lt;/code&gt;&lt;sup&gt;7&lt;/sup&gt; deployment strategy. &lt;code&gt;:git_shallow_clone&lt;/code&gt; &lt;sup&gt;8&lt;/sup&gt;sets the &lt;code&gt;--depth&lt;/code&gt; to 1 to make the clone faster, we're not passing the git repository anyway. Eliminating the .git/.gitignore&lt;sup&gt;9&lt;/sup&gt; on the server results in a significant reduction in compression time. With this Mephisto repository it takes us from a 8.9 MB transfer down to 3.2 MB.  My choice of &lt;code&gt;deploy_to&lt;/code&gt;&lt;sup&gt;10&lt;/sup&gt; follows DreamHost defaults but if you created a separate user for deploying then you'll need to change &lt;code&gt;#{user}&lt;/code&gt;&lt;sup&gt;10&lt;/sup&gt; to the name of DreamHost user that you want to contain the application.  You can also change the &lt;code&gt;#{application}&lt;/code&gt;&lt;sup&gt;10&lt;/sup&gt; part of the path to something different, i.e. &lt;code&gt;mephisto&lt;/code&gt; or whatever you want.  You could also set &lt;code&gt;:copy_cache&lt;/code&gt; to true; I tried it but I didn't notice a significant difference either way so I left it out.
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# App specific tasks:&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;namespace &lt;span class=&quot;sy&quot;&gt;:deploy&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  desc &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;lt;&amp;lt;-DESC&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;k&quot;&gt;&lt;tt&gt;
&lt;/tt&gt;    Bootstrap the Mephisto production database.  Runs the Mephisto &lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;    db:bootstrap rake task for the production database.  Normally run &lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;    one time as part of the initial deployment:&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;      $ cap deploy:setup&lt;tt&gt;
&lt;/tt&gt;      $ cap deploy:update&lt;tt&gt;
&lt;/tt&gt;      $ cap deploy:bootstrap&lt;tt&gt;
&lt;/tt&gt;      &lt;tt&gt;
&lt;/tt&gt;    WARNING! This task will reinitialize your database.  If you run &lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;    it after the initial deployment all of your content will be lost.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&lt;tt&gt;
&lt;/tt&gt;  DESC&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  task &lt;span class=&quot;sy&quot;&gt;:bootstrap&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:roles&lt;/span&gt; =&amp;gt; [&lt;span class=&quot;sy&quot;&gt;:db&lt;/span&gt;], &lt;span class=&quot;sy&quot;&gt;:only&lt;/span&gt; =&amp;gt; { &lt;span class=&quot;sy&quot;&gt;:primary&lt;/span&gt; =&amp;gt; &lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt; } &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    run &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cd &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;current_path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;; rake RAILS_ENV=production db:bootstrap&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;I decided to create a separate section (starting a line 12 above) at the top of my &lt;code&gt;deploy.rb&lt;/code&gt; file for application specific tasks.  In this case I added code to run Mephisto's &lt;code&gt;db:bootstrap&lt;/code&gt; task on the production server.  The task description in lines 14-25 says it all. If you don't want a task to do the bootstrap from the client than you can leave this code out; it's no problem to &lt;code&gt;ssh&lt;/code&gt; to the server and run &lt;code&gt;rake db:bootstrap&lt;/code&gt; when you need to. The task is something I added early on while I was just figuring out how things worked and saw several implementations with the equivalent functionality.  It saves a little typing but it's rarely done and the manual steps are so simple it doesn't really provide that much of a benefit.
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;35&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;38&lt;tt&gt;
&lt;/tt&gt;39&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;40&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# The rest is generic for DH a shared hosting deployment, assumming:&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;c&quot;&gt;#   - Phusion Passenger is used&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;c&quot;&gt;#   - An assets dir in public that's not part of the scm repository.&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;c&quot;&gt;#   - The database.yml is not in the repository &lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;set &lt;span class=&quot;sy&quot;&gt;:use_sudo&lt;/span&gt;, &lt;span class=&quot;pc&quot;&gt;false&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;role &lt;span class=&quot;sy&quot;&gt;:app&lt;/span&gt;, application&lt;tt&gt;
&lt;/tt&gt;role &lt;span class=&quot;sy&quot;&gt;:web&lt;/span&gt;, application&lt;tt&gt;
&lt;/tt&gt;role &lt;span class=&quot;sy&quot;&gt;:db&lt;/span&gt;,  application, &lt;span class=&quot;sy&quot;&gt;:primary&lt;/span&gt; =&amp;gt; &lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Lines 31-40 contain pretty standard stuff. We can't &lt;code&gt;use_sudo&lt;/code&gt;&lt;sup&gt;35&lt;/sup&gt; on DreamHost and the &lt;code&gt;role&lt;/code&gt;s&lt;sup&gt;37-39&lt;/sup&gt; are all on the same server.
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;41&lt;tt&gt;
&lt;/tt&gt;42&lt;tt&gt;
&lt;/tt&gt;43&lt;tt&gt;
&lt;/tt&gt;44&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;45&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;46&lt;tt&gt;
&lt;/tt&gt;47&lt;tt&gt;
&lt;/tt&gt;48&lt;tt&gt;
&lt;/tt&gt;49&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;50&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;51&lt;tt&gt;
&lt;/tt&gt;52&lt;tt&gt;
&lt;/tt&gt;53&lt;tt&gt;
&lt;/tt&gt;54&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;55&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;56&lt;tt&gt;
&lt;/tt&gt;57&lt;tt&gt;
&lt;/tt&gt;58&lt;tt&gt;
&lt;/tt&gt;59&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;60&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;namespace &lt;span class=&quot;sy&quot;&gt;:deploy&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  desc &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Restart passenger.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  task &lt;span class=&quot;sy&quot;&gt;:restart&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    run &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;touch &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;current_path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/tmp/restart.txt&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  desc &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Initial setup of the shared_path.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  task &lt;span class=&quot;sy&quot;&gt;:setup_shared&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    run &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mkdir -p &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;shared_path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/config &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;shared_path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/assets&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  desc &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Gets the shared_path ready for use with the release.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  task &lt;span class=&quot;sy&quot;&gt;:prepare_shared&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    run &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ln -nfs &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;shared_path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/assets &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;release_path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/public/assets&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    run &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ln -nfs &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;shared_path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/config/database.yml &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+&lt;tt&gt;
&lt;/tt&gt;              &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;release_path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/config/database.yml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;after &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;deploy:setup&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;deploy:setup_shared&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;before &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;deploy:finalize_update&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;deploy:prepare_shared&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Lines 41-60 contain the &lt;code&gt;deploy&lt;/code&gt; namespace tasks. Phusion Passenger is restarted&lt;sup&gt;42-45&lt;/sup&gt; in the usual way.  &lt;code&gt;:setup_shared&lt;/code&gt;&lt;sup&gt;47-50&lt;/sup&gt; is intended to create shared directories or files needed as part of the initial setup.  In this case that's only the &lt;code&gt;assets&lt;/code&gt; directory&lt;sup&gt;49&lt;/sup&gt;, which holds article assets so it's left out of the repository and a single copy is kept and shared between releases.  It needs to exist on initial deployment when it's symlinked&lt;sup&gt;54&lt;/sup&gt; for the first time.   &lt;code&gt;:prepare_shared&lt;/code&gt;&lt;sup&gt;52-57&lt;/sup&gt; is intended for any setup required to prepare the shared path for use.  In this case that just means symlink creation. Tasks like &lt;code&gt;:prepare_shared&lt;/code&gt; are typically done after &lt;code&gt;deploy:update_code&lt;/code&gt;. I chose to do it before &lt;code&gt;deploy:finalize_update&lt;/code&gt;&lt;sup&gt;60&lt;/sup&gt; instead of the usual time after reading a comment in &lt;a href=&quot;http://github.com/37signals/cached_externals/tree/master/recipes%2Fcached_externals.rb&quot;&gt;Cached Externals&lt;/a&gt; about touching order and looking at the &lt;code&gt;:finalize_update&lt;/code&gt; task code.  Doing it right before &lt;code&gt;:finalize_update&lt;/code&gt; will allow &lt;code&gt;:normalize_asset_timestamps&lt;/code&gt; to work properly with anything that needs timestamping in the shared path.  Although it won't matter in this deployment, doing it before &lt;code&gt;:finalize_update&lt;/code&gt; seems like the correct execution order and I expect to reuse this code in other projects where it could make a difference.  Because the &lt;code&gt;database.yml&lt;/code&gt; file contains the production password, I opted to only keep it on the production server.  I'll give instructions about how to create it before it's linked&lt;sup&gt;55&lt;/sup&gt; to later, but if you'd rather just keep your production information in your local &lt;code&gt;database.yml&lt;/code&gt; and copy it up as part of the deployment then insert:
&lt;p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;strong&gt;50&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;top.upload(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;config/database.yml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;shared_path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/config/database.yml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;into &lt;code&gt;:setup_shared&lt;/code&gt;.  This will upload the file whenever you run &lt;code&gt;cap deploy:setup&lt;/code&gt;, which is safe to run anytime.  Alternatively, you could add it to the beginning of &lt;code&gt;:prepare_shared&lt;/code&gt; to upload it with each deployment.
&lt;/p&gt;
&lt;p&gt;That's enough to give us a complete deployment script so it's a good time to commit the changes. And, since were about to deploying a release to production, I'd also recommend tagging it with a version or some other type label:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ git commit -a -m &quot;First customized version of deploy.rb&quot;
[mac]$ git tag -m &quot;First production blog release.&quot; v0.0.1
&lt;/pre&gt;
&lt;h3&gt;Initial Deployment&lt;/h3&gt;
&lt;p&gt;Originally &lt;code&gt;cap deploy:cold&lt;/code&gt; was intended to be a single step initial deployment. It still exists but it is no longer recommended.  It was recognized that generically automating initial deployments for web applications just isn't something that works well.  For example, this blog deployment is pretty simple but &lt;code&gt;db:bootstrap&lt;/code&gt; is used for database and server setup, migrations aren't needed, and I've made a security decision not to automate deployment of the &lt;code&gt;database.yml&lt;/code&gt;.  At the very least &lt;code&gt;deploy:cold&lt;/code&gt; would need to be rewritten to get it to work.  It might be worth exploring whether or not you can get &lt;code&gt;deploy:cold&lt;/code&gt; to work if you have some type of cookie cutter deployment but it's not worth it if the deployment environment varies or for the one time setup of a web application.  As it turns out even without &lt;code&gt;cap deploy:cold&lt;/code&gt; Capistrano makes it easy for a first time deploy.  The first step is to prepare the directory structure on the server:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ cap deploy:setup
&lt;/pre&gt;
&lt;p&gt;I chose to only keep separate &lt;code&gt;database.yml&lt;/code&gt; files on the client and server in order to keep database account settings off the deployment client.  Unless you added the &lt;code&gt;top.upload()&lt;/code&gt; code in &lt;code&gt;:setup_shared&lt;/code&gt; or you did something similar to get your &lt;code&gt;database.yml&lt;/code&gt; file to the server then we'll need to create the database.yml on the server.  It doesn't matter how you get it there, you can edit a yaml file locally and put it on the server then delete it, create it on the server or whatever.  I scp'd the Mephisto example database yaml file and edited on the server with &lt;a href=&quot;http://www.vim.org/&quot;&gt;vim&lt;/a&gt; : 
&lt;/p&gt;
&lt;pre&gt;
[mac]$ scp config/database.example.yml \
&gt; rsblog@robseaman.com:blog.robseaman.com/shared/config/database.yml
[mac]$ ssh rsblog@robseaman.com
[dh]$ cd blog.robseaman.com/shared/config
[dh]$ vim database.yml # edit production settings and save
[dh]$ logout
&lt;/pre&gt;
&lt;p&gt;Your production section contents will vary but my DreamHost version is close to this:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;35&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;38&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;production:&lt;tt&gt;
&lt;/tt&gt;  adapter: mysql&lt;tt&gt;
&lt;/tt&gt;  database: robseaman_mephisto_production&lt;tt&gt;
&lt;/tt&gt;  username: robsblogdbuser&lt;tt&gt;
&lt;/tt&gt;  password: &lt;span class=&quot;co&quot;&gt;YeahSure&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  host:     mysql.robseaman.com&lt;tt&gt;
&lt;/tt&gt;  encoding: utf8&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;BTW: If you did decide to put the &lt;code&gt;top.upload()&lt;/code&gt; code in the &lt;code&gt;:setup_shared&lt;/code&gt; deployment task but ran &lt;code&gt;cap deploy:setup&lt;/code&gt; before updating the production section of your &lt;code&gt;database.yml&lt;/code&gt; then just run &lt;code&gt;cap deploy:setup&lt;/code&gt; again after the &lt;code&gt;database.yml&lt;/code&gt; update is complete.
&lt;/p&gt;
&lt;p&gt;Now move the application to the server with:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ cap deploy:update
&lt;/pre&gt;
&lt;p&gt;At this point the database exists but lacks a schema so it's time for our Mephisto specific task.  Run the task for that:&lt;/p&gt;
&lt;pre&gt;
[mac]$ cap deploy:bootstrap
&lt;/pre&gt;
&lt;p&gt;If you see a line that looks like this:
&lt;pre&gt;
*** [err :: robseaman.com] mkdir -p /home/rsblog/xxxx/releases/20081129044823/log
&lt;/pre&gt;
&lt;p&gt;don't worry about it.  It's occurs because we already created the assets directory.  If you didn't add the &lt;code&gt;deploy:bootstrap&lt;/code&gt; to &lt;code&gt;deploy.rb&lt;/code&gt; then just ssh to the server, change to the current directory and run &lt;code&gt;rake db:bootstrap&lt;/code&gt;.  For other applications this would be the point where you'd usually run &lt;code&gt;rake RAILS_ENV=production db:schema:load&lt;/code&gt;.
&lt;/p&gt;
&lt;p&gt;Now the web application needs to be started.  For DreamHost this means changing the hosting settings for the domain to use Phusion Passenger and to point to the application.  Go to &lt;a href=&quot;https://panel.dreamhost.com/index.cgi?tree=domain.manage&amp;amp;&quot;&gt;Domain &gt; Manage Domains&lt;/a&gt; in your control panel and select &lt;em&gt;Edit&lt;/em&gt; in the &lt;em&gt;Web Hosting&lt;/em&gt; column for the domain. Set the &lt;em&gt;FTP user / CGI-runs-as user&lt;/em&gt; to your application user, for me that was &lt;code&gt;rsblog&lt;/code&gt;. The web directory should default to the domain name, for me it was &lt;em&gt;/home/username/blog.robseaman.com&lt;/em&gt;.  If you used the same &lt;code&gt;:deploy_to&lt;/code&gt; variable in &lt;code&gt;deploy.rb&lt;/code&gt; as me just add &lt;em&gt;/current/public&lt;/em&gt;, for example I ended up with &lt;em&gt;/home/username/blog.robseaman.com/current/public&lt;/em&gt;.  Now check the box next to &lt;em&gt;Ruby on Rails Passenger (mod_rails)?&lt;/em&gt;.  If you want other changes go ahead and make them. When you're done press the &lt;em&gt;Change fully hosting settings now!&lt;/em&gt; button.
&lt;/p&gt;
&lt;p&gt;Give it a minute or two and you should be able to pint your browser to http://your_domain/admin, i.e. http://blog.robseaman.com/admin for me. Login with Login: admin and Password: test, change the password, and change the site settings. I did notice at this point that I needed to go to Settings &gt; Caches (&lt;code&gt;admin/cached_pages&lt;/code&gt;) and clear the cache to see my changes but I'm not yet sure if that's always necessary.  Now you should be able to start blogging.
&lt;/p&gt;
&lt;h3&gt;Subsequent Deploys&lt;/h3&gt;
&lt;p&gt;Subsequent deployments is where Capistrano really shines.  When you want to make a change you can do it in your development environment and after you make sure it works and git commit it you can move it to your web server and restart the application with a single command:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ cap deploy
&lt;/pre&gt;
&lt;p&gt;It's probably a good idea to add a git tag step, like we did before the initial deploy above, before each deploy but that's up to you.  If you can't remember what version you used last, just by type &lt;code&gt;git tag&lt;/code&gt; with no options and you'll get a list.
&lt;h3&gt;Is that it?&lt;/h3&gt;
&lt;p&gt;At this point we have a working maintainable blogging system. The blog software and its templates can be tracked and updated and it's easy to deploy changes from a development machine.  From a workflow standpoint it would be very helpful if it were easy to copy the production database into the development environment to see what impact changes will have on existing content before an update is deployed.  I'll cover that in the &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/2/production-data-to-development&quot;&gt;Production Data to Development&lt;/a&gt;&lt;/em&gt; post.  Once that's in place I'd consider it a  functionally complete working environment but doesn't it seem inefficient that with every update Rails and all that stuff in the vendor directory that hardly ever changes gets compressed and uploaded?  That issue can be addressed using &lt;a href=&quot;http://github.com/37signals/cached_externals/tree/master&quot;&gt;Cached Externals&lt;/a&gt;, which I've covered in &lt;a href=&quot;http://blog.robseaman.com/2008/12/3/cached-externals&quot;&gt;another post&lt;/a&gt;.
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.robseaman.com/">
    <author>
      <name>Rob</name>
    </author>
    <id>tag:blog.robseaman.com,2008-12-01:5</id>
    <published>2008-12-01T02:01:00Z</published>
    <updated>2009-01-15T17:00:24Z</updated>
    <category term="Website Setup"/>
    <category term="dreamhost"/>
    <category term="git"/>
    <category term="mephisto"/>
    <link href="http://blog.robseaman.com/2008/12/1/gitting-started-with-mephisto" rel="alternate" type="text/html"/>
    <title>gitting Started with Mephisto</title>
<summary type="html">&lt;p&gt;&lt;em&gt;Jan. 14, 2009 Update: This post applies to Mephisto 0.8. See &lt;a href=&quot;http://blog.robseaman.com/2009/1/15/upgrading-to-mephisto-0-8-1&quot;&gt;Upgrading to Mephisto 0.8.1&lt;/a&gt; for information about moving to version 0.8.1&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;I took what I bet is a pretty common approach to setting up &lt;a href=&quot;http://mephistoblog.com/&quot;&gt;Mephisto&lt;/a&gt;.  I put a copy on my laptop, played with it just enough to get it to work and then found and followed some fairly simple instructions to install it directly on my DreamHost account.  It was an easy and straight forward approach but in my case by the time I finished my installation I knew I wanted to start over.  The problem was that I quickly found myself modifying too many things to get Mephisto to work and look the way I wanted. I could tell it was going to be easier for me in the long run to get the blog engine in source code control with a development and deployment environment that made it to easy tweak and update from my laptop.  Since Mephisto is a Rails application I went with the common choices: maintaining the blog code in a local &lt;a href=&quot;http://git.or.cz/&quot;&gt;git&lt;/a&gt; repository and deploying it using &lt;a href=&quot;http://www.capify.org/&quot;&gt;Capistrano&lt;/a&gt;.  
&lt;/p&gt;
&lt;p&gt;In this post I cover setting up a custom git branch for Mephisto along with a couple of Mephisto modifications I recommend to prepare it for deployment to a DreamHost account. Actually there's really nothing DreamHost specific here but other hosting services could require additional changes to environment files.  I'll cover deployment to DreamHost using Capistrano in a my &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/1/deploying-mephisto-with-capistrano-to-dreamhost&quot;&gt;next post&lt;/a&gt;&lt;/em&gt;.  If you want to take this approach then I'm assuming you're fairly technical and already have git and Rails and MySQL installed on your computer. The use of git and Rails in this post is basic but going down this maintenance and deployment path is only worthwhile if you're reasonably comfortable with both technologies.</summary><content type="html">
            &lt;p&gt;&lt;em&gt;Jan. 14, 2009 Update: This post applies to Mephisto 0.8. See &lt;a href=&quot;http://blog.robseaman.com/2009/1/15/upgrading-to-mephisto-0-8-1&quot;&gt;Upgrading to Mephisto 0.8.1&lt;/a&gt; for information about moving to version 0.8.1&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;I took what I bet is a pretty common approach to setting up &lt;a href=&quot;http://mephistoblog.com/&quot;&gt;Mephisto&lt;/a&gt;.  I put a copy on my laptop, played with it just enough to get it to work and then found and followed some fairly simple instructions to install it directly on my DreamHost account.  It was an easy and straight forward approach but in my case by the time I finished my installation I knew I wanted to start over.  The problem was that I quickly found myself modifying too many things to get Mephisto to work and look the way I wanted. I could tell it was going to be easier for me in the long run to get the blog engine in source code control with a development and deployment environment that made it to easy tweak and update from my laptop.  Since Mephisto is a Rails application I went with the common choices: maintaining the blog code in a local &lt;a href=&quot;http://git.or.cz/&quot;&gt;git&lt;/a&gt; repository and deploying it using &lt;a href=&quot;http://www.capify.org/&quot;&gt;Capistrano&lt;/a&gt;.  
&lt;/p&gt;
&lt;p&gt;In this post I cover setting up a custom git branch for Mephisto along with a couple of Mephisto modifications I recommend to prepare it for deployment to a DreamHost account. Actually there's really nothing DreamHost specific here but other hosting services could require additional changes to environment files.  I'll cover deployment to DreamHost using Capistrano in a my &lt;em&gt;&lt;a href=&quot;http://blog.robseaman.com/2008/12/1/deploying-mephisto-with-capistrano-to-dreamhost&quot;&gt;next post&lt;/a&gt;&lt;/em&gt;.  If you want to take this approach then I'm assuming you're fairly technical and already have git and Rails and MySQL installed on your computer. The use of git and Rails in this post is basic but going down this maintenance and deployment path is only worthwhile if you're reasonably comfortable with both technologies.

&lt;/p&gt;
&lt;h3&gt;Prep the Blog Application Repository&lt;/h3&gt;
&lt;p&gt;There are a couple of versions of Mephisto out there; the last official release was 0.8 (Drax). I started with the current master branch of the &lt;a href=&quot;http://github.com/technoweenie/mephisto/tree/master&quot;&gt;technoweenie version&lt;/a&gt; from github.  To do the same &lt;code&gt;cd&lt;/code&gt; to some place on your hard drive where you want &lt;code&gt;mephisto&lt;/code&gt; installed and type:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ git clone git://github.com/technoweenie/mephisto.git
[mac]$ cd mephisto
&lt;/pre&gt;
&lt;p&gt;After the download completed, I ended up with a copy that had a last commit SHA1 ID of 14dc7e9b27ceaafa8b26627eaf20e6bafa80b3b1.  If there have been any updates you'll end up with something newer than mine. I'd stick with whatever you clone but if it's newer than mine it does mean there's a chance that a change could impact the instructions in this post. If you decide you want to be sure to have the same version you can reset to that commit:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ git reset --hard 14dc7e9b27ceaafa8b26627eaf20e6bafa80b3b1
&lt;/pre&gt;
&lt;p&gt;At this point you have the Mephisto master branch. Instead of treating my copy as a fork, I set up and switched to a separate branch to keep my changes separate.  If you just want to pull in and merge updates with your code then you can just work from the master.   If you decided to keep your changes in custom branch like I did then you can call it whatever you want. Since my version is intended for my website, I called mine &lt;em&gt;robseaman&lt;/em&gt;:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ git checkout -b robseaman
&lt;/pre&gt;
&lt;p&gt;When I want to apply updates from the master my plan is to switch to the master, pull the updates and then go back to the custom branch and rebase my changes to the updated master, dealing with conflicts as necessary:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ git checkout master
[mac]$ git pull
[mac]$ git checkout robseaman
[mac]$ git rebase master
&lt;/pre&gt;
&lt;p&gt;
Fine, but that's for the future, let's get back to the here and now. After the clone you have a git repository that's ready to use but it's setup to maintain a blogging application for reuse by anyone on the web, independent of themes and deployment information.  While you could make that work, as individual deploying a blog I felt it would be simpler to treat the whole thing as one single Rails application. To customize it that way you'll need to change the &lt;code&gt;.gitignore&lt;/code&gt; file. For example I changed my &lt;code&gt;.gitignore&lt;/code&gt; from:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;.rake_tasks&lt;tt&gt;
&lt;/tt&gt;config/database.yml&lt;tt&gt;
&lt;/tt&gt;config/deploy.rb&lt;tt&gt;
&lt;/tt&gt;log&lt;tt&gt;
&lt;/tt&gt;tmp&lt;tt&gt;
&lt;/tt&gt;themes/*&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;
to:
&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;.DS_Store&lt;tt&gt;
&lt;/tt&gt;config/database.yml&lt;tt&gt;
&lt;/tt&gt;log&lt;tt&gt;
&lt;/tt&gt;tmp&lt;tt&gt;
&lt;/tt&gt;public/assets&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Here are the reasons for my choices:
&lt;ul&gt;
&lt;li&gt;I Deleted &lt;code&gt;.rake_tasks&lt;/code&gt;. It's not something I have, so I didn't leave it in.
&lt;/li&gt;
&lt;li&gt;I added &lt;code&gt;.DS_Store&lt;/code&gt;. These are hidden files containing Mac GUI information.  I'm on a Mac, if you aren't then you don't need this line.
&lt;/li&gt;
&lt;li&gt;Just like the original, I left &lt;code&gt;config/database.yml&lt;/code&gt; out of the repository because it contains private account and password information.  While it makes no sense for the &lt;code&gt;database.yml&lt;/code&gt; to be in the Mephisto master project, for a private blog where the intention is to keep the repository local it's probably OK to check it in, especially if you only have the development and test account information.  All that said, there's nothing here that really needs tracking and I like the idea that the repository can be moved around and shared without having to consider what password information it may contain. 
&lt;/li&gt;
&lt;li&gt;I Added &lt;code&gt;config/deploy.rb&lt;/code&gt;. It contains the Capistrano deployment script. This script is something that changes so tracking it with a source code manager is beneficial.  An exception would be if you end up storing passwords in the &lt;code&gt;deploy.rb&lt;/code&gt;. In that case I'd recommend leaving it out of the repository but I do think you should avoid passwords in  &lt;code&gt;deploy.rb&lt;/code&gt; if possible. For example, if you have a password in the script because you're using it to connect using Capistrano's &lt;code&gt;:password&lt;/code&gt; variable then switch to SSH with public key signatures or put the password in a separate recipe or the &lt;code&gt;~/.caprc&lt;/code&gt; file.  Or, if you're dynamically building the production &lt;code&gt;database.yml&lt;/code&gt; and including a password in your deployment script then consider not automating that part of the deployment and creating the &lt;code&gt;database.yml&lt;/code&gt; on the server or at least consider simply uploading the production &lt;code&gt;database.yml&lt;/code&gt; as a separate file.
&lt;/li&gt;
&lt;li&gt;I added &lt;code&gt;public/assets&lt;/code&gt;. In Mephisto this directory contains things like images for articles, which are more closely aligned with the database than with code.  While it makes sense to maintain code locally, data and assets are created on the production server so they're not things that belong in the repository.
&lt;/li&gt;
&lt;li&gt;I removed &lt;code&gt;themes&lt;/code&gt;.  I wanted to be able make and track changes to themes locally as part of the application and push those changes up to a web server.
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When you're done commit the &lt;code&gt;.gitignore&lt;/code&gt; changes to the new branch:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ git commit .gitignore -m &quot;Changed to track changes for my blog.&quot;
&lt;/pre&gt;
&lt;h3&gt;Put Everything in Vendor&lt;/h3&gt;
&lt;p&gt;Unfortunately Mephisto isn't keeping pace with Rails.  The master branch of the 0.8 version works with Rails 2.0.2.  Many hosting servers have multiple versions of Rails. If yours does and 2.0.2 exists then it's possible to set &lt;code&gt;RAILS_GEM_VERSION&lt;/code&gt; in &lt;code&gt;config/environment.rb&lt;/code&gt; but my preference is more in line with the &lt;a href=&quot;http://errtheblog.com/posts/50-vendor-everything&quot;&gt;vendor everything&lt;/a&gt; camp. Meaning I prefer to keep gems including Rails in the vendor directory to avoid potential environment issues.  Here are the commands to set-up Mephisto for 2.0.2 using the vendor directory:  
&lt;/p&gt;
&lt;pre&gt;
[mac]$ rake rails:freeze:edge RELEASE=2.0.2
[mac]$ git add .
[mac]$ git commit -a -m &quot;Froze to Rails 2.0.2.&quot;
[mac]$ cp vendor/rails/railties/environments/boot.rb config/boot.rb
[mac]$ git commit config/boot.rb -m &quot;Updated to Rails 2.0.2 boot.rb.&quot;
&lt;/pre&gt;
&lt;p&gt;The &lt;a href=&quot;http://tzinfo.rubyforge.org/&quot;&gt;TZInfo&lt;/a&gt; gem is required by Mephisto.  Again, I chose to I install it into the vendor directory:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ sudo gem install tzinfo
[mac]$ cd vendor
[mac]$ gem unpack tzinfo
[mac]$ cd ..
[mac]$ git add .
[mac]$ git commit -a -m &quot;Put tzinfo 0.3.12 in vendor dir.&quot;
&lt;/pre&gt;
&lt;h3&gt;Minor Code Changes&lt;/h3&gt;
&lt;p&gt;The first code change I recommend is to change the session secret in &lt;code&gt;config/environment.rb&lt;/code&gt;.  It's the line that looks like this:
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;37&lt;tt&gt;
&lt;/tt&gt;38&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;config.action_controller.session = { &lt;span class=&quot;sy&quot;&gt;:session_key&lt;/span&gt; =&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;_mephisto_session&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;sy&quot;&gt;:secret&lt;/span&gt; =&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;....big random string....&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; } &lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;:secret&lt;/code&gt; is an application wide key string used for the cookie store and should be set to something fairly long, at least 30 characters, consisting of random numbers and letters.  Rails generates a unique string for each application but since Mephisto is distributed broadly with a common key if you don't change it then Mephisto (like most open source Rails apps) is vulnerable to session hijacking.  There was a &lt;a href=&quot;http://groups.google.com/group/rubyonrails-core/browse_thread/thread/4d43c1fa2485f3e3&quot;&gt;discussion of this in the Ruby on Rails: Core group&lt;/a&gt;. I generated my &lt;code&gt;:secret&lt;/code&gt; replacement by creating a temporary Rails application:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ cd ..
[mac]$ rails temp
&lt;/pre&gt;
&lt;p&gt;and copying the secret from &lt;code&gt;temp/config/environment.rb&lt;/code&gt; into Mephisto's &lt;code&gt;environment.rb&lt;/code&gt;.  After the edit I deleted the temp application and committed the change:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ rm -rf temp
[mac]$ cd mephisto
[mac]$ git commit -a -m &quot;Changed secret from distributed version.&quot;
&lt;/pre&gt;
&lt;p&gt;The only other change I recommend before using Mephisto is to comment out the multi-site enabling line in &lt;code&gt;config/initializers/custom.rb&lt;/code&gt; unless you need multi-site support:
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# Site.multi_sites_enabled = true&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;/p&gt;
&lt;p&gt;The multi-site feature enables a single Mephisto implementation to support multiple blogs. &lt;em&gt;I think&lt;/em&gt; to get it to work properly you need to leave this line uncommented and do some &lt;a href=&quot;http://www.mslater.com/2007/6/1/setting-up-mephisto-for-multiple-sites#comment-form&quot;&gt;additional setup steps&lt;/a&gt;. I phrased this as &lt;em&gt;I think&lt;/em&gt; because it's not completely clear to me what the current state of this feature is.  Originally the enabling line in &lt;code&gt;custom.rb&lt;/code&gt; was commented out by default but that was &lt;a href=&quot;http://github.com/technoweenie/mephisto/commit/3f641bdcc30284decf08cc8962c87e7df93b96de&quot;&gt;changed&lt;/a&gt; for some reason last spring.  I discovered the setting early on while playing with Mephisto on my production server when I noticed image support wasn't working.  When I investigated I found my images existed but were saved in &lt;code&gt;public/assets/unusedfornow.com&lt;/code&gt; instead of in &lt;code&gt;public/assets&lt;/code&gt; as they were on my development server.  As far as I could tell my set-up was the same in both environments, a little investigation led me to this line and after a commenting it out I had thumbnails and consistent behavior.  I was likely tinkering with other things at the same time so I'm not 100% sure if I needed to do more setup or if I had the issue for some unrelated reason but since I had no need multi-site support and commenting this line out worked for me, I never looked back:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ git commit config/initializers/custom.rb -m &quot;Disabled multi-site support.&quot;
&lt;/pre&gt;
&lt;h3&gt;Program and Database Initialization&lt;/h3&gt;
&lt;p&gt;Mephisto leaves it up to you to create your &lt;code&gt;database.yml&lt;/code&gt; but it does have an example intended to provide a starting point:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ cp config/database.example.yml config/database.yml
&lt;/pre&gt;
&lt;p&gt;Edit the &lt;code&gt;database.yml&lt;/code&gt; and change the development database connection settings to something that will work on your local system.  As always the development, test and production databases could use different DBMS software but I made sure to use the same database manager for both.  SQLite may be fine for development but I like to have as much consistency as possible between development and production and I wanted to make sure it would be easy to pull production data down to my development system. DreamHost provides MySQL support so I stuck with the Mephisto's default choice of MySQL and the root user and just changed the password.  
&lt;/p&gt;
&lt;p&gt;You can also set-up the test database configuration as well, I did but haven't used it yet. I don't recommend setting the production settings on your development box, although a it's little more work, it's more secure to only keep this information on the production server.  I'll cover production database set-up for DreamHost in a &lt;a href=&quot;http://blog.robseaman.com/2008/12/1/deploying-mephisto-with-capistrano-to-dreamhost&quot;&gt;separate deployment post&lt;/a&gt;.  Below the production database settings are example connection set-ups and conversion connection templates. I just left them in for reference but you could delete them if you want.  After the edits you can create the development database. The Rails &lt;code&gt;db:create&lt;/code&gt; rake task needs to access the &lt;code&gt;log&lt;/code&gt; directory, which doesn't exist yet, so do it the old fashion way using your DBMS:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ mysqladmin -u root create -p mephisto_development
&lt;/pre&gt;
&lt;p&gt;If you don't have a root password you can leave of the &lt;code&gt;-p&lt;/code&gt;, otherwise respond with your password when prompted.  Mephisto comes with it's own bootstrapping task to create the necessary folders, initialize the database and setup the default theme.  For a first time set-up use this program and forget about migrations.  It generates a lot of files so a git update is also required: 
&lt;/p&gt;
&lt;pre&gt;
[mac]$ rake db:bootstrap
[mac]$ git add .
[mac]$ git commit -a -m &quot;Ran db:bootstrap&quot;
&lt;/pre&gt;
&lt;h3&gt;Go Man Go&lt;/h3&gt;
&lt;p&gt;At this point the Mephisto blogging application is ready to run on your development system.  It's also in a git repository that's ready to be moved to a web hosting service.  It would be a good idea before deploying to make sure it works:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ script/server
&lt;/pre&gt;
&lt;p&gt;Assuming your using Mongrel for your development environment, login to the administration portion of the site at http://localhost:3000/admin with Login: admin and Password: test and play around.
          </content>  </entry>
  <entry xml:base="http://blog.robseaman.com/">
    <author>
      <name>Rob</name>
    </author>
    <id>tag:blog.robseaman.com,2008-11-30:3</id>
    <published>2008-11-30T00:05:00Z</published>
    <updated>2008-12-02T00:40:12Z</updated>
    <category term="Security"/>
    <category term="Website Setup"/>
    <category term="dreamhost"/>
    <category term="leopard"/>
    <category term="ssh"/>
    <link href="http://blog.robseaman.com/2008/11/30/ssh-with-leopard" rel="alternate" type="text/html"/>
    <title>SSH with Leopard</title>
<summary type="html">&lt;p&gt;I recently set-up a secure shell account for a DreamHost shared hosting account that I intend to use for automating deployment and backup tasks from a Mac OS X Leopard client.   While not overly complicated there were a couple of gotchas that I ran into.  This post consolidates my findings and gives you a brief background for what's going on when you set up SSH access. The information applies to Mac OS X 10.5.1 or greater.</summary><content type="html">
            &lt;p&gt;I recently set-up a secure shell account for a DreamHost shared hosting account that I intend to use for automating deployment and backup tasks from a Mac OS X Leopard client.   While not overly complicated there were a couple of gotchas that I ran into.  This post consolidates my findings and gives you a brief background for what's going on when you set up SSH access. The information applies to Mac OS X 10.5.1 or greater.

&lt;/p&gt;
&lt;h3&gt;Secure Shell Access&lt;/h3&gt;
&lt;p&gt;The first step is to make sure you have SSH and/or SFTP access for one of your hosting service accounts.  How you accomplish this will vary from one service to another. For DreamHost it's very easy, go to the &lt;a href=&quot;https://panel.dreamhost.com/?tab=users&amp;amp;subtab=users&quot;&gt;Manage Users &gt; Users&lt;/a&gt; section of your DreamHost web panel, select &lt;em&gt;Add A New User&lt;/em&gt; or &lt;em&gt;Edit&lt;/em&gt; an existing user and fill in the account information.  Be sure the &lt;em&gt;User Account Type&lt;/em&gt; is set to &lt;em&gt;Shell account&lt;/em&gt;, which includes support for both SSH and SFTP.  If you have a shared hosting account then you'll need to make sure the &lt;em&gt;Username&lt;/em&gt; is unique. The error messages should lead you through any issues.  If you want more detail check out the &lt;a href=&quot;http://wiki.dreamhost.com/Enabling_Shell_Access&quot;&gt;DreamHost Enabling Shell Access Wiki&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;For the rest of this post I'll assume your domain is called &lt;em&gt;mydomain.com&lt;/em&gt; and you have an SSH user account named &lt;em&gt;mydom_user&lt;/em&gt;.  Now open &lt;em&gt;Terminal&lt;/em&gt; in OS X and try using SSH.  Here's the typical format for the ssh command:
&lt;/p&gt;
&lt;pre&gt;[mac]$ ssh mydom_user@mydomain.com
&lt;/pre&gt;
&lt;p&gt;You should be prompted for your password.  If you aren't prompted then check your hosting service documentation to see if you need to use something other than the &lt;code&gt;user@hostname&lt;/code&gt; format to connect.  If you are prompted and you enter your password correctly then you should see a greeting followed by the command prompt from your server.  At this point you have secure shell access working.  The main limitation is that the password gets in the way for automated tasks such as deployment scripts and client initiated &lt;a href=&quot;http://en.wikipedia.org/wiki/Cron&quot;&gt;cron&lt;/a&gt; jobs. If you don't mind being prompted for a password when you use SSH and you either don't have automation needs or don't mind setting up your password in automation scripts then congratulations, you're done!
&lt;/p&gt;
&lt;h3&gt;Digital Signature Setup&lt;/h3&gt;
&lt;p&gt;Assuming you don't want to deal with your SSH password then the solution is to use a &lt;a href=&quot;http://en.wikipedia.org/wiki/Public-key_cryptography&quot;&gt;public/private key&lt;/a&gt; pair for authentication.  The first step is to create a directory to hold your Mac's public key on your domain server.  For SSH to work this directory must be named &lt;code&gt;.ssh&lt;/code&gt; and it must have owner only read, write and execute privileges.  If you logged out then log back in to your shell account and type: 
&lt;/p&gt;
&lt;pre&gt;
[dh]$ mkdir .ssh
[dh]$ chmod 700 .ssh
[dh]$ logout
&lt;/pre&gt;
&lt;p&gt;That's it from the server side.  You should be back to your regular OS X prompt.  Unless you already have an existing private/public key pair you'll need to create one and copy the public key to your server.  First check to see if any keys are already defined:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ ls -l ~/.ssh
&lt;/pre&gt;
&lt;p&gt;If you see an &lt;code&gt;id_rsa&lt;/code&gt; and &lt;code&gt;id_rsa.pub&lt;/code&gt; file or an &lt;code&gt;id_dsa&lt;/code&gt; and &lt;code&gt;id_dsa.pub&lt;/code&gt; file then you have a key pair already defined.  For example, I have:
&lt;/p&gt;
&lt;pre&gt;
...
-rw-------@  1 Rob  Rob  1743 Nov 11 15:16 id_rsa
-rw-r--r--@  1 Rob  Rob   405 Nov 11 15:16 id_rsa.pub
...
&lt;/pre&gt;
&lt;p&gt;The file without the extension contains the private key; the file with the &lt;code&gt;.pub&lt;/code&gt; extension is the public key that can be shared.  They don't have to be named &lt;code&gt;id_rsa&lt;/code&gt; or &lt;code&gt;id_dsa&lt;/code&gt; but those are the default names. ID is used because the keys establish an &lt;em&gt;identity&lt;/em&gt;, while  &lt;em&gt;RSA&lt;/em&gt; and &lt;em&gt;DSA&lt;/em&gt; are associated with the two public key signature algorithms that SSH supports.  I'll describe how to generate a key pair later but first I want to cover the situation that I had with existing keys.
&lt;/p&gt;
&lt;p&gt;In my case an RSA key pair already existed but I didn't remember creating it.  At this point creating a new set of keys or overwriting the existing pair may have been a good idea but I didn't want another identity and I didn't want to break something that I'd set up previously but couldn't remember at the moment. So, I decided to try to use the existing key pair.  The first issue I had was with the privilege settings on my private key.  The file should only have owner read, write privileges ( &lt;code&gt;-rw-------&lt;/code&gt;).  Initially, the permissions were wrong on my file. I have no idea why but at some point they got messed up.  When I tried using the key it was ignored and I got the following warning:
&lt;/p&gt;
&lt;pre&gt;
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0622 for '/Users/Rob/.ssh/id_rsa' are too open.
It is recommended that your private key files are NOT accessible by others.
This private key will be ignored.
bad permissions: ignore key: /Users/Rob/.ssh/id_rsa
&lt;/pre&gt;	
If your private key file has &lt;code&gt;-rw-r--r--&lt;/code&gt; or any permissions other than &lt;code&gt;-rw-------&lt;/code&gt;, you'll need to fix it:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ chmod 600 ~/.ssh/id_rsa
&lt;/pre&gt;
&lt;p&gt;The next issue I had was that I was prompted for my &quot;passphrase&quot; and I couldn't remember it.  You can think of a passphrase as a password that's used to protect your private key.  The difference is that spaces and tabs are allowed in passphrases.  If you have a key pair and remember the passphrase you used when you created it then your set.  Since I didn't remember mine, I decided to open the &lt;em&gt;Keychain Access&lt;/em&gt; application in the &lt;em&gt;Applications/Utilities&lt;/em&gt; folder to see if I could find it. If you're in the same situation checking your keychain is probably worth a try. If the passphrase is there you'll find it in the &lt;em&gt;Passwords/Application&lt;/em&gt; Category of the &lt;em&gt;login&lt;/em&gt; Keychains. It'll have a name starting with &lt;em&gt;SSH:&lt;/em&gt;, but don't be surprised if you don't find it.  Passphrases were not stored in the keychain until OS X 10.5.1 and even then only if you chose to store it when you used the key.  You also won't find passphrases in your keychain if you're using the MacPorts OpenSSH implementation. I'll get to MacPorts later but if you don't find your passphrase and want to try a few guesses at it then you can use the &lt;code&gt;ssh-keygen&lt;/code&gt; command with the change password option: 
&lt;/p&gt;	
&lt;pre&gt;
[mac]$ ssh-keygen -f ~/.ssh/id_rsa -p
&lt;/pre&gt;
&lt;p&gt;Ultimately, if you can't remember or find your passphrase then you'll need to generate a new key pair or overwrite your existing pair.  Generating new keys or overwriting existing keys can be accomplished the same way:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ ssh-keygen
&lt;/pre&gt;
&lt;p&gt;will generate an RSA key and prompt you for a passphrase. It will also prompt for a file name, defaulting to &lt;em&gt;~/.ssh/id_rsa&lt;/em&gt;. If you have an existing key pair with the same name it'll make sure it's OK with you before overwriting an existing key pairs.  RSA is the default, if you want DSA then add the &lt;code&gt;-t dsa&lt;/code&gt; option when you run &lt;code&gt;ssh-keygen&lt;/code&gt;.
&lt;/p&gt;
&lt;p&gt;The passphrase is optional and if you just hit enter twice when prompted for it then you won't set one. Don't do that.  It may seem that having a passphrase gets you back to square one with a password prompt but that's an easy limitation to get around, especially with Leopard.  For now take my word for it and enter a passphrase. You should also pick something different than your password.  I don't want to get too sidetracked with why a passphrase is so important but keep in mind that your private key is stored in a text file on disk and without a passphrase for protection anyone who gets your key could access anything that key is used for. 
&lt;/p&gt;
&lt;p&gt;At this point you should have a private/public key pair and a known passphrase.  I'll assume your private key is named &lt;code&gt;id_rsa&lt;/code&gt; but you can make substitutions if you chose another name.   Now you need to copy the public key to your server.  You should also make sure it just has owner read, write privileges if it's a new file:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ cat ~/.ssh/id_rsa.pub | ssh mydom_user@mydomain.com \
&gt; &quot;cat &gt;&gt;  ~/.ssh/authorized_keys; chmod 600 .ssh/authorized_keys&quot;
&lt;/pre&gt;
&lt;p&gt;If you enter your password correctly then the copy should work.  I should note that instructions from other sites will often say to use &lt;code&gt;authorized_keys2&lt;/code&gt; instead of &lt;code&gt;authorized_keys&lt;/code&gt;, that's fine but &lt;code&gt;authorized_keys2&lt;/code&gt; has been depreciated so I went with &lt;code&gt;authorized_keys&lt;/code&gt;. You'll also see a lot of instructions using the secure copy (&lt;code&gt;scp&lt;/code&gt;) command to move the file but I like the &lt;code&gt;cat&lt;/code&gt; with the pipe and redirection format because it makes it clear how to append new public keys.  Now it's time to give your public key signature a try:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ ssh mydom_user@mydomain.com
&lt;/pre&gt;
&lt;p&gt;If you're luckly you'll be prompted for your passcode with a dialog prompt like this:&lt;br /&gt;

&lt;br /&gt;If you get the dialog just enter the passphrase and check the box to save it in your keychain.  From now on you should be able to use SSH without being prompted. You're done!
&lt;/p&gt;
&lt;h3&gt;Don't Blame Apple&lt;/h3&gt;
&lt;p&gt;If you're still reading then I'm assuming things didn't go according to plan.  Perhaps you got the following error:
&lt;/p&gt;
&lt;pre&gt;
percent_expand: NULL replacement 
&lt;/pre&gt;
&lt;p&gt;or, instead of being prompted by a GUI dialog box you get prompted for your passphrase on the command line:
&lt;pre&gt;
Enter passphrase for key '/Users/Rob/.ssh/id_rsa':
&lt;/pre&gt;
&lt;p&gt;These issues typically occur because you're not using the Leopard version of the &lt;code&gt;ssh&lt;/code&gt; program.  First, verify that's the problem:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ which ssh
&lt;/pre&gt;
&lt;p&gt;If you get back &lt;code&gt;/usr/bin/ssh&lt;/code&gt; then you're using the Leopard version of &lt;code&gt;ssh&lt;/code&gt; and I don't know what's wrong so you'll need to look elsewhere for a solution.  On the other hand, if you get back&lt;code&gt;/opt/local/bin/ssh&lt;/code&gt; then you're running the MacPorts version of &lt;code&gt;ssh&lt;/code&gt; and I'll walk you through a solution.  If you get a different path then there's still a good chance you're using the MacPorts &lt;code&gt;ssh&lt;/code&gt; but it was installed somewhere other than the default location.  The  following instructions will probably still work but you'll need to adjust the paths.
&lt;/p&gt;
&lt;p&gt;OK, at this point I'm assuming you're using the OpenSSH implementation from MacPorts and your either getting the &lt;code&gt;percent_expand: NULL replacement&lt;/code&gt; error or your continuing to see passphrase prompts when you use &lt;code&gt;ssh&lt;/code&gt;.  If so, the easiest solution is just to switch to Leopard's SSH commands.  Just renaming the MacPorts SSH commands so the Leopard version is found instead will work but I like this technique taken from &lt;a href=&quot;http://github.com/guides/percent_expand-null-replacement-bug&quot;&gt;from github&lt;/a&gt; better:
&lt;/p&gt;
&lt;pre&gt;
[mac]$ sudo -s # To get a root prompt
bash-3.2# cd /opt/local/bin
bash-3.2# mv ssh{,_macports}
bash-3.2# ln -s /usr/bin/ssh ssh
bash-3.2# exit
&lt;/pre&gt;
&lt;p&gt;
It renames &lt;code&gt;ssh&lt;/code&gt; and leaves a symbolic link behind allowing any software that looks specifically for the program in the MacPorts directory to find them.  The github guide, and every other Internet post I've seen, renames &lt;code&gt;scp&lt;/code&gt; as well but as far as I can tell that's not necessary. At least on my Mac only &lt;code&gt;ssh&lt;/code&gt; has problems, &lt;code&gt;scp&lt;/code&gt; and &lt;code&gt;sftp&lt;/code&gt; don't exhibit the &lt;em&gt;NULL replacement&lt;/em&gt; problem and the Leopard version of &lt;code&gt;ssh-agent&lt;/code&gt; is automatically launched to take care of the passphrases.  That said, you could also use the same renaming technique for &lt;code&gt;scp&lt;/code&gt;, &lt;code&gt;sftp&lt;/code&gt; and any other SSH commands that you want.  For example, the Leopard version of &lt;code&gt;ssh-add&lt;/code&gt; has additional options for keychain support that don't exist in the MacPorts version.  Anyway, after you're done with renaming then when you use the &lt;code&gt;ssh&lt;/code&gt; command you should get the desired Leopard dialog box and behavior described above. 
&lt;/p&gt;
&lt;h3&gt;Other Ideas and Resources&lt;/h3&gt;
&lt;p&gt;While I prefer switching to the Leopard &lt;code&gt;ssh&lt;/code&gt;, if for some reason you want to stick with the MacPorts version then you may be able to solve the &lt;code&gt;percent_expand: NULL replacement&lt;/code&gt; error by updating to the &quot;openssh 5.0p1_0+darwin_9&quot; version of MacPorts SSH (see bottom of &lt;a href=&quot;http://github.com/guides/percent_expand-null-replacement-bug&quot;&gt;this&lt;/a&gt;). I haven't tried the update so I'm not sure if it works. Even if it doesn't you can definitely work around the problem by creating/updating your &lt;code&gt;~/.ssh/config&lt;/code&gt; file (see &lt;a href=&quot;http://www.nabble.com/ssh%3A-percent_expand%3A-NULL-replacement-td13439207.html&quot;&gt;here&lt;/a&gt;). To avoid the continuous passphrase prompting, you could just run &lt;code&gt;sftp&lt;/code&gt; or the Leopard version of &lt;code&gt;ssh&lt;/code&gt; once to cause Leopards &lt;code&gt;ssh-agent&lt;/code&gt; to save it in your keychain.  I suppose it would also be possible to switch over to the MacPorts &lt;code&gt;ssh-agent&lt;/code&gt; and use it along with a utility such as &lt;a href=&quot;http://www.mothersruin.com/software/SSHChain/&quot;&gt;SSHChain&lt;/a&gt; or &lt;a href=&quot;http://www.sshkeychain.org/&quot;&gt;SSHKeychain&lt;/a&gt;. You can also find plenty of generic Unix passphrase prompting solutions by googling for &lt;em&gt;ssh-agent&lt;/em&gt;.  Many of them aren't Mac compatible but I'm sure you can find something that works.
&lt;/p&gt;
&lt;p&gt;If you want to dig more into SSH on the Mac then &lt;a href=&quot;http://www.dribin.org/dave/blog/&quot;&gt;Dave Dribin's&lt;/a&gt; has a couple of great blogs. As a starting point take a look at his &lt;em&gt;&lt;a href=&quot;http://www.dribin.org/dave/blog/archives/2007/11/28/ssh_agent_leopard/&quot;&gt;ssh-agent on Mac OS X 10.5 (Leopard)&lt;/a&gt;&lt;/em&gt; article where he describes, among other things, how the Leopard version of &lt;code&gt;ssh-agent&lt;/code&gt; is automatically launched as necessary.
&lt;/p&gt;
          </content>  </entry>
</feed>
