<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
 
 <title>Jesse Storimer</title>
 
 <link href="http://jstorimer.com/" />
 <updated>2012-05-11T07:55:51-04:00</updated>
 <id>http://jstorimer.com/</id>
 <author>
   <name>Jesse Storimer</name>
   <email>jesse@jstorimer.com</email>
 </author>

 
 <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/jstorimer" /><feedburner:info uri="jstorimer" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>jstorimer</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><entry>
   <title>Passing Open Files Between Processes with UNIX Sockets</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/V2qEOTFa-DY/passing-open-files-over-unix-sockets.html" />
   <updated>2012-05-07T00:00:00-04:00</updated>
   <id>http://jstorimer.com/2012/05/07/passing-open-files-over-unix-sockets</id>
   <content type="html">&lt;p&gt;I want to share with you today a neat little technique I learned involving UNIX sockets.&lt;/p&gt;

&lt;p&gt;In the land of Unix &lt;a href="http://ph7spot.com/musings/in-unix-everything-is-a-file"&gt;everything is a file&lt;/a&gt;. This is faithfully mirrored in Ruby with the &lt;code&gt;IO&lt;/code&gt; class. The &lt;code&gt;IO&lt;/code&gt; class models any so-called files on a Unix system. This includes stuff like &lt;code&gt;File&lt;/code&gt;, &lt;code&gt;TCPSocket&lt;/code&gt;, &lt;code&gt;UDPSocket&lt;/code&gt;, all of which are subclasses of &lt;code&gt;IO&lt;/code&gt;. Since these classes all share a common parent they also share a common API, as they should.&lt;/p&gt;

&lt;p&gt;Here's a quick example:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;socket&amp;#39;&lt;/span&gt;

&lt;span class="c1"&gt;# open 3 different IO objects&lt;/span&gt;
&lt;span class="n"&gt;file&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/etc/passwd&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;tcp_socket&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TCPSocket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;google.com&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;pipe&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pipe&lt;/span&gt;

&lt;span class="c1"&gt;# write some data to the tcp socket and close&lt;/span&gt;
&lt;span class="c1"&gt;# the writing stream afterwards&lt;/span&gt;
&lt;span class="n"&gt;tcp_socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;GET / HTTP/1.1&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;tcp_socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close_write&lt;/span&gt;

&lt;span class="c1"&gt;# write some data to the pipe and close&lt;/span&gt;
&lt;span class="c1"&gt;# the writable IO afterwards&lt;/span&gt;
&lt;span class="n"&gt;pipe&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;some test data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;pipe&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;close_write&lt;/span&gt;

&lt;span class="c1"&gt;# read from all the IO objects in the&lt;/span&gt;
&lt;span class="c1"&gt;# same way. Yay for polymorphism and&lt;/span&gt;
&lt;span class="c1"&gt;# duck typing!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tcp_socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pipe&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]].&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;
  &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This example shows how different subclasses of &lt;code&gt;IO&lt;/code&gt; can be treated in a similar way. &lt;em&gt;But&lt;/em&gt;, each subclass also implements some of its own methods. In some cases it overwrites the parent implementation, but some of the subclasses can do things that others can't. Enter &lt;code&gt;UNIXSocket&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;UNIX Sockets are Local&lt;/h2&gt;

&lt;p&gt;UNIX sockets have (almost) the exact same API as TCP sockets. The defining difference is that while TCP sockets can connect any two endpoints on the same network, UNIX sockets can only connect to other UNIX sockets &lt;em&gt;on the same physical domain&lt;/em&gt;, ie. on the same machine. As such, the kernel can take some shortcuts and ensure that UNIX sockets are much faster than TCP sockets because they skip the entire networking layer.&lt;/p&gt;

&lt;p&gt;Since UNIX Sockets are local and fast they make a great candidate for &lt;a href="http://jstorimer.com/2012/04/19/intro-to-ruby-ipc.html"&gt;IPC&lt;/a&gt;. Besides sharing plain text data between processes you can also &lt;em&gt;share open file descriptors between unrelated processes using UNIX Sockets&lt;/em&gt;. The most important word in the last sentence is &lt;em&gt;unrelated&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;Related Processes Share Open Files By Default&lt;/h2&gt;

&lt;p&gt;When I say &lt;em&gt;related&lt;/em&gt;, I'm talking about a hierarchichal relationship. One process is related to another when it has a parent/child or parent/grandchild, etc., relationship.&lt;/p&gt;

&lt;p&gt;I've written previously about &lt;a href="http://jstorimer.com/2012/03/18/a-unix-shell-in-ruby-pipes.html"&gt;how open files are shared between parent/child processes when forking&lt;/a&gt;. Related processes share file descriptors through the semnatics of fork(2). Even if the child process decides to exec(2) and become a totally different process it can still access any shared file descriptors.&lt;/p&gt;

&lt;p&gt;But what if you want to pass a file descriptor to a totally unrelated process? You can! Using UNIX sockets.&lt;/p&gt;

&lt;h2&gt;Sharing File Descriptors Between Unrelated Processes&lt;/h2&gt;

&lt;p&gt;Let's imagine that I have a Ruby daemon process that listens on a UNIX socket. It listens on that socket to receive open TCP connections. When it gets one it will respond in its own special way. I could distribute this daemon as a rubygem, at which point developers could write clients that interact with it by sending open connections over the UNIX socket. By 'open' I mean that the client would accept a new connection, then pass it to the daemon over a UNIX socket and the daemon would write a response and close the connection. Fun!&lt;/p&gt;

&lt;p&gt;The daemon could look like this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;socket&amp;#39;&lt;/span&gt;

&lt;span class="c1"&gt;# This sockets listens for local connections.&lt;/span&gt;
&lt;span class="n"&gt;listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;UNIXServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/tmp/pingback.sock&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;accept&lt;/span&gt;

&lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# This is where an open connection is received.&lt;/span&gt;
  &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recv_io&lt;/span&gt;

  &lt;span class="c1"&gt;# An exciting response. Echo!&lt;/span&gt;
  &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Stick that code into a file and run it. Then it can be interacted with using a client like:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;socket&amp;#39;&lt;/span&gt;

&lt;span class="c1"&gt;# This socket listens for connections from the outside world.&lt;/span&gt;
&lt;span class="n"&gt;listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TCPServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;0.0.0.0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4481&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# This socket connects up to the local daemon.&lt;/span&gt;
&lt;span class="n"&gt;receiver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;UNIXSocket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/tmp/pingback.sock&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="no"&gt;Socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;accept_loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="c1"&gt;# When it gets a new connection it passes it right to the&lt;/span&gt;
  &lt;span class="c1"&gt;# daemon process.&lt;/span&gt;
  &lt;span class="n"&gt;receiver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_io&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Passing the connection to the daemon made a copy of it,&lt;/span&gt;
  &lt;span class="c1"&gt;# so now there are two open connections. If we didn&amp;#39;t close&lt;/span&gt;
  &lt;span class="c1"&gt;# it here then the connection would remain open even after&lt;/span&gt;
  &lt;span class="c1"&gt;# it was closed by the daemon.&lt;/span&gt;
  &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;If you run both the daemon and the client you can test drive the two pieces using netcat:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; &lt;span class="nb"&gt;echo &lt;/span&gt;boofar | nc localhost 4481
&lt;span class="go"&gt;    boofar&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The response is pretty unexciting, it's just an echo server. But realize what's happening: you're initiating a TCP connection to the client which passes that connection to the daemon, and it's the daemon that actually writes the response back to you.&lt;/p&gt;

&lt;p&gt;Note that these two processes are started up independently and are &lt;em&gt;unrelated&lt;/em&gt;. There's no forking semantics at play here.&lt;/p&gt;

&lt;p&gt;Can't handle multiple clients atm.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;So the important methods here were &lt;code&gt;UNIXServer#send_io&lt;/code&gt; and &lt;code&gt;UNIXServer#recv_io&lt;/code&gt;. The first sends an open file, the second receives one.&lt;/p&gt;

&lt;p&gt;You could use this to pass open files between &lt;em&gt;any&lt;/em&gt; two processes on your system. And you don't need to restrict yourself to two Ruby processes. Thanks to the fact that most modern languages support UNIX sockets you could write a client to interact with the Ruby daemon in Python, or even in C. I'll leave that as an exercise for the reader :)&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/I7jwXbhBhzAsXD_JHFNKtSz1Zno/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/I7jwXbhBhzAsXD_JHFNKtSz1Zno/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/I7jwXbhBhzAsXD_JHFNKtSz1Zno/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/I7jwXbhBhzAsXD_JHFNKtSz1Zno/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/V2qEOTFa-DY" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2012/05/07/passing-open-files-over-unix-sockets.html</feedburner:origLink></entry>
 
 <entry>
   <title>4 Months of ebook Sales</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/moc36ttzMEo/4-months-of-ebook-sales.html" />
   <updated>2012-04-20T00:00:00-04:00</updated>
   <id>http://jstorimer.com/2012/04/20/4-months-of-ebook-sales</id>
   <content type="html">&lt;p&gt;Four months ago, to the day, I launched &lt;a href="http://workingwithunixprocesses.com"&gt;an ebook about Unix programming for Ruby developers&lt;/a&gt;. Here I'll share how it came to be and some sales numbers.&lt;/p&gt;

&lt;h2&gt;Backstory&lt;/h2&gt;

&lt;p&gt;I've been interested in writing an ebook for a while. The first time I tried I didn't finish because I couldn't stay motivated. This time around I was able to stay motivated because &lt;em&gt;I put up a fake sales page to test the idea before I even started writing&lt;/em&gt;. This is the same technique that Tim Ferriss talks about in the 4HWW. The validation this provided was what I needed to see it through.&lt;/p&gt;

&lt;p&gt;Just as I was ready to start writing the book I left for a wilderness retreat. My family and I spent 2 and 1/2 weeks in the wilderness with no electricity or electronics of any kind. I expected to feel frustrated that I couldn't get started on the book, but it was the total opposite. &lt;em&gt;Spending time away from everyday distractions allowed me to do some productive planning for the book&lt;/em&gt;, as well as have a great time. By the time I went home I had a good outline of what I wanted to write about.&lt;/p&gt;

&lt;p&gt;Over the next few months I spent many late nights writing. I didn't take time off from my day job or have anyone working with me. I didn't work on it every night but usually several nights per week for ~2 hours.. &lt;em&gt;After about 2 and 1/2 months of writing I had something I was pretty happy with&lt;/em&gt;. I basically wrote the book that I had wanted to read a year or two earlier, before I went ahead and &lt;a href="http://jstorimer.com/2012/02/10/learning-unix-programming.html"&gt;learned the hard way&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Launch&lt;/h2&gt;

&lt;p&gt;I did zero promotion before launching the book. Literally no one knew about it besides me, my wife, and a few friends. The book is fully self-published so there was &lt;em&gt;no publisher involved, no copyeditor, no technical editor, just me&lt;/em&gt;. I'm really grateful to the few people that I reached out to who provided valuable advice and reviews. Without their interaction I wouldn't have known what I had. If I were to do this again I would certainly offer a pre-launch mailing list to let people follow along as I worked on the book.&lt;/p&gt;

&lt;p&gt;I was very nervous about putting something out there with my name on it and asking people to pay money for it. Once the book was 'done' I deliberated for a month on whether or not I would release it. After putting together a web site for the book (with the help of &lt;a href="http://copywritingforgeeks.com/"&gt;Copywriting for Geeks&lt;/a&gt;) and showing it to one more person who gave really positive feedback I decided to bite the bullet and see what would happen. I treated the whole thing as an experiment and had no idea what to expect.&lt;/p&gt;

&lt;p&gt;Someone close to me asked what I would consider to be a successful outcome after launching the book. At first I said that &lt;em&gt;if I can create something, put it online, and get even one person to pay for it then that's a huge accomplishment&lt;/em&gt;. After some thought I said that if the revenue were $1,000 in the first month (about 1 sale per day) I would consider it a success. To my surprise revenue was just over $1,000 on launch day alone. The only launch announcement I made was via Twitter.&lt;/p&gt;

&lt;h2&gt;Numbers&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;h3&gt;Total Revenue: $17,992 USD&lt;/h3&gt;&lt;/li&gt;
&lt;li&gt;&lt;h3&gt;Total # of Sales: 746&lt;/h3&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;a href="/images/wwup-sales-orig.png"&gt;&lt;img src="/images/wwup-sales.png" alt="WWUP sales to date" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the image to see a high res version. This chart is straight from &lt;a href="http://sumall.com"&gt;SumAll&lt;/a&gt;. Keep in mind that these numbers do not include processing fees or expenses, but discounts have been deducted.&lt;/p&gt;

&lt;p&gt;The data points are all daily, so you can see there are highs and lows. The initial spike is simply my twitter announcement and friendly folks retweeting. The spike on day 3 happened when the book was linked in &lt;a href="http://rubyweekly.com/"&gt;Ruby Weekly&lt;/a&gt;. The other two big spikes on the chart were the result of discount promotions I ran. All of the other smallish spikes are invariably two things: 1) Someone recommends the book on twitter, or 2) I publish content on my blog. You'll notice fewer sales in the last few weeks, certainly due in part to the fact that I haven't published to my blog.&lt;/p&gt;

&lt;p&gt;I'm ecstatic with the results so far, but I have no idea how they compare. A pair of &lt;a href="http://blog.asmartbear.com/perfect-pricing.html"&gt;design&lt;/a&gt; &lt;a href="http://blog.asmartbear.com/higher-pricing.html"&gt;ebook&lt;/a&gt; authors recently shared their launch numbers which were much higher. But they're in a different space selling to a different audience. I still haven't a clue how my results compare to other (e)books for programmers.&lt;/p&gt;

&lt;h2&gt;Aftermath&lt;/h2&gt;

&lt;p&gt;Anyone who has ever launched their own product will tell that they didn't just kick their feet back and watch the money come in. There's lots to do. Between answering emails, producing content to market the book, and adding new content to the book itself, I've continued to invest late night hours into the project at least a few nights per week.&lt;/p&gt;

&lt;p&gt;On that note, there is a new chapter for the book as of today. If you've already purchased the book then you should already have gotten the email. If you haven't purchased the book then you can &lt;a href="http://jstorimer.com/2012/04/19/intro-to-ruby-ipc.html"&gt;read the new chapter for free&lt;/a&gt;. If you learn something then I encourage you to &lt;a href="http://workingwithunixprocesses.com"&gt;check out the book&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Inspiration&lt;/h2&gt;

&lt;p&gt;So why am I sharing this info instead of just keeping quiet? I was always inspired when people who launched their own products shared their story. I promised myself that if I ever got anything off the ground I would do the same. This is me delivering on that promise and hoping that I might inspire just one person down the line to build that thing they really want to build.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/gmXGZVgijfBxkvSMTDJEKcfMV4E/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/gmXGZVgijfBxkvSMTDJEKcfMV4E/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/gmXGZVgijfBxkvSMTDJEKcfMV4E/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/gmXGZVgijfBxkvSMTDJEKcfMV4E/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/moc36ttzMEo" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2012/04/20/4-months-of-ebook-sales.html</feedburner:origLink></entry>
 
 <entry>
   <title>Introduction to IPC in Ruby</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/rTaMYmnFhmM/intro-to-ruby-ipc.html" />
   <updated>2012-04-19T00:00:00-04:00</updated>
   <id>http://jstorimer.com/2012/04/19/intro-to-ruby-ipc</id>
   <content type="html">&lt;p&gt;This is a sample chapter from my book &lt;em&gt;Working With Unix Processes&lt;/em&gt;. Learning how stuff works under the hood is one of the most important things you can do as a developer. If this article pushes you in that direction then I encourage you to &lt;a href="http://workingwithunixprocesses.com"&gt;learn more about the book&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;




&lt;p&gt;Up until now we've looked at related processes that share memory and share open resources. But what about communicating information between multiple processes?&lt;/p&gt;




&lt;p&gt;This is part of a whole field of study called Inter-process communication (IPC for short). There are many different ways to do IPC but I'm going to cover two commonly useful method: pipes and socket pairs.&lt;/p&gt;




&lt;h2 id="our-first-pipe"&gt;Our First Pipe&lt;/h2&gt;




&lt;p&gt;A pipe is a uni-directional stream of data. In other words you can open a pipe, one process can 'claim' one end of it and another process can 'claim' the other end. Then data can be passed along the pipe but only in one direction. So if one process 'claims' the position of reader, rather than writer, it &lt;em&gt;will not&lt;/em&gt; be able to write to the pipe. And vice versa.&lt;/p&gt;




&lt;p&gt;Before we involve multiple processes let's just look at how to create a pipe and what we get from that:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pipe&lt;/span&gt; &lt;span class="c1"&gt;#=&amp;gt; [#&amp;lt;IO:fd 5&amp;gt;, #&amp;lt;IO:fd 6&amp;gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;&lt;code&gt;IO.pipe&lt;/code&gt; returns an array with two elements, both of which are &lt;code&gt;IO&lt;/code&gt; objects. Ruby's &lt;a href="http://librelist.com/browser//usp.ruby/2011/9/17/the-ruby-io-class/"&gt;amazing IO class&lt;/a&gt;  is the superclass to &lt;code&gt;File&lt;/code&gt;, &lt;code&gt;TCPSocket&lt;/code&gt;, &lt;code&gt;UDPSocket&lt;/code&gt;, and others. As such, all of these resources have a common interface.&lt;/p&gt;




&lt;p&gt;The &lt;code&gt;IO&lt;/code&gt; objects returned from &lt;code&gt;IO.pipe&lt;/code&gt; can be thought of something like anonymous files. You can basically treat them the same way you would a &lt;code&gt;File&lt;/code&gt;. You can call &lt;code&gt;#read&lt;/code&gt;, &lt;code&gt;#write&lt;/code&gt;, &lt;code&gt;#close&lt;/code&gt;, etc. But this object won't respond to &lt;code&gt;#path&lt;/code&gt; and won't have a location on the filesystem.&lt;/p&gt;




&lt;p&gt;Still holding back from bringing in multiple processes let's demonstrate communication with a pipe:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pipe&lt;/span&gt;
&lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Into the pipe I go..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;outputs&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="go"&gt;Into the pipe I go...&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;Pretty simple right? Notice that I had to close the writer after I wrote to the pipe? That's because when the reader calls &lt;code&gt;IO#read&lt;/code&gt; it will continue trying to read data until it sees an EOF (aka. &lt;a href="http://en.wikipedia.org/wiki/End-of-file"&gt;end-of-file marker&lt;/a&gt;). This tells the reader that no more data will be available for reading.&lt;/p&gt;




&lt;p&gt;So long as the writer is still open the reader might see more data, so it waits. By closing the writer before reading it puts an EOF on the pipe so the reader stops reading after it gets the initial data. If you skip closing the writer then the reader will block and continue trying to read indefinitely.&lt;/p&gt;




&lt;h2 id="pipes-are-one-way-only"&gt;Pipes Are One-Way Only&lt;/h2&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pipe&lt;/span&gt;
&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Trying to get the reader to write something"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;outputs&lt;/p&gt;




&lt;p&gt;&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="go"&gt; &amp;gt;&amp;gt; reader.write("Trying to get the reader to write something")&lt;/span&gt;
&lt;span class="go"&gt;IOError: not opened for writing&lt;/span&gt;
&lt;span class="go"&gt;        from (irb):2:in `write'&lt;/span&gt;
&lt;span class="go"&gt;        from (irb):2&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;The &lt;code&gt;IO&lt;/code&gt; objects returned by &lt;code&gt;IO.pipe&lt;/code&gt; can only be used for uni-directional communication. So the reader can &lt;em&gt;only&lt;/em&gt; read and the writer can &lt;em&gt;only&lt;/em&gt; write.&lt;/p&gt;




&lt;p&gt;Now let's introduce processes into the mix.&lt;/p&gt;




&lt;h2 id="sharing-pipes"&gt;Sharing Pipes&lt;/h2&gt;




&lt;p&gt;In the chapter on forking I described how open resources are shared, or copied, when a process forks a child. Pipes are considered a resource, they get their own file descriptors and everything, so they are shared with child processes.&lt;/p&gt;




&lt;p&gt;Here's a simple example of using a pipe to communicate between a parent and child process. The child indicates to the parent that it has finished an iteration of work by writing to the pipe:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pipe&lt;/span&gt;

&lt;span class="nb"&gt;fork&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;
  
  &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# heavy lifting&lt;/span&gt;
    &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Another one bites the dust"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gets&lt;/span&gt;
  &lt;span class="vg"&gt;$stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;outupts &lt;code&gt;Another one bites the dust&lt;/code&gt; ten times.&lt;/p&gt;




&lt;p&gt;Notice that, like above, the unused ends of the pipe are closed so as not to interfere with EOF being sent. There's actually one more layer when considering EOF now that two processes are involved. Since the file descriptors were copied there's now 4 instances floating around. Since only two of them will be used to communicate the other 2 instances must be closed. Hence the extra instances of closing.&lt;/p&gt;




&lt;p&gt;Since the ends of the pipe are &lt;code&gt;IO&lt;/code&gt; objects we can call any &lt;code&gt;IO&lt;/code&gt; methods on them, not just &lt;code&gt;#read&lt;/code&gt; and &lt;code&gt;#write&lt;/code&gt;. In this example I use &lt;code&gt;#puts&lt;/code&gt; and &lt;code&gt;#gets&lt;/code&gt; to read and write a &lt;code&gt;String&lt;/code&gt; delimited with a newline. I actually used those here to simplify one aspect of pipes: pipes hold a stream of data.&lt;/p&gt;




&lt;h2 id="streams-vs-messages"&gt;Streams vs. Messages&lt;/h2&gt;




&lt;p&gt;When I say stream I mean that when writing and reading data to a pipe there's no concept of beginning and end. When working with an IO stream, like pipes or TCP sockets, you write your data to the stream followed by some protocol-specific delimiter. For example, HTTP uses a series of newlines to specify delimit the headers from the body.&lt;/p&gt;




&lt;p&gt;Then when reading data from that IO stream you read it in one chunk at a time, stopping when you come across the delimiter. &lt;em&gt;That's&lt;/em&gt; why I used &lt;code&gt;#puts&lt;/code&gt; and &lt;code&gt;#gets&lt;/code&gt; in the last example: it used a newline as the delimiter for me.&lt;/p&gt;




&lt;p&gt;As you may have guessed it's possible to communicate via messages instead of streams. We can't do it with pipe, but we can do it with Unix sockets. Without going into too much detail, Unix sockets are a type of socket that can only communicate on the same physical machine. As such it's much faster than TCP sockets and is a great fit for IPC.&lt;/p&gt;




&lt;p&gt;Here's an example where we create a pair of Unix sockets that can communicate via messages:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'socket'&lt;/span&gt;
&lt;span class="no"&gt;Socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:UNIX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:DGRAM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#=&amp;gt; [#&amp;lt;Socket:fd 15&amp;gt;, #&amp;lt;Socket:fd 16&amp;gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;This creates a pair of UNIX sockets these sockets that are already connected up to each other. These sockets communicate using datagrams, rather than a stream. In this way you write a &lt;em&gt;whole&lt;/em&gt; message to one of the sockets and read a &lt;em&gt;whole&lt;/em&gt; message from the other socket. No delimiters required.&lt;/p&gt;




&lt;p&gt;Here's a slightly more complex version of the pipe example where the child process actually waits for the parent to tell it what to work on, then it reports back to the parent once it's finished the work:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'socket'&lt;/span&gt;

&lt;span class="n"&gt;child_socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parent_socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:UNIX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:DGRAM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;maxlen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;

&lt;span class="nb"&gt;fork&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;parent_socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;
  
  &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;instruction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;child_socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxlen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;child_socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;instruction&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; accomplished!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt; 
&lt;span class="k"&gt;end&lt;/span&gt; 
&lt;span class="n"&gt;child_socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;

&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;parent_socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Heavy lifting"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt; 
&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;parent_socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Feather lifting"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt; 

&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="vg"&gt;$stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;parent_socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxlen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt; 
&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;So whereas pipes provide uni-directional communication, a socket pair provides bi-directional communication. The parent socket can both read and write to the child socket, and vice versa.&lt;/p&gt;




&lt;h2 id="remote-ipc"&gt;Remote IPC?&lt;/h2&gt;




&lt;p&gt;IPC implies communication between processes running on the same machine. If you're interested in scaling up from one machine to many machines while still doing something resembling IPC there are a few things to look into. The first one would simply be to communicate via TCP sockets. This option would require more boilerplate code than the others for a non-trivial system. Other plausible solutions would be &lt;a href="http://en.wikipedia.org/wiki/Remote_procedure_call"&gt;RPC&lt;/a&gt; (remote procedure call),  a messaging system like &lt;a href="http://www.zeromq.org/"&gt;ZeroMQ&lt;/a&gt;, or the general body of &lt;a href="http://en.wikipedia.org/wiki/Distributed_computing"&gt;distributed systems&lt;/a&gt;.&lt;/p&gt;




&lt;h2 id="in-the-real-world-11"&gt;In the Real World&lt;/h2&gt;




&lt;p&gt;Both pipes and socket pairs are useful abstractions for communicating between processes. They're fast and easy. They're often used as a communication channel instead of a more brute force approach such as a shared database or log file. &lt;/p&gt;




&lt;p&gt;As for which method to use: it depends on your needs. Keep in mind that pipes are uni-directional and socket pairs are bi-directional when weighing your decision.&lt;/p&gt;




&lt;p&gt;For a more in-depth example have a look at the Spyglass Master class in the included Spyglass project. It uses a more involved example of the code you saw above where many child processes communicate over a single pipe with their parent process.&lt;/p&gt;




&lt;h2 id="system-calls-10"&gt;System Calls&lt;/h2&gt;




&lt;p&gt;Ruby's &lt;code&gt;IO.pipe&lt;/code&gt; maps to pipe(2), &lt;code&gt;Socket.pair&lt;/code&gt; maps to socketpair(2). &lt;code&gt;Socket.recv&lt;/code&gt; maps to recv(2) and &lt;code&gt;Socket.send&lt;/code&gt; maps to send(2).&lt;/p&gt;




&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/QgEOf_g4b5TxkvEMLlEkCtfX-j0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QgEOf_g4b5TxkvEMLlEkCtfX-j0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/QgEOf_g4b5TxkvEMLlEkCtfX-j0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QgEOf_g4b5TxkvEMLlEkCtfX-j0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/rTaMYmnFhmM" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2012/04/19/intro-to-ruby-ipc.html</feedburner:origLink></entry>
 
 <entry>
   <title>Daemon Processes in Ruby</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/83pJ1IavxY8/daemon-processes-in-ruby.html" />
   <updated>2012-04-19T00:00:00-04:00</updated>
   <id>http://jstorimer.com/2012/04/19/daemon-processes-in-ruby</id>
   <content type="html">&lt;p&gt;This is a sample chapter from my book &lt;em&gt;Working With Unix Processes&lt;/em&gt;. Learning how stuff works under the hood is one of the most important things you can do as a developer. If this article pushes you in that direction then I encourage you to &lt;a href="http://workingwithunixprocesses.com"&gt;learn more about the book&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;




&lt;div class="chapter"&gt;
  &lt;p&gt;Daemon processes are processes that run in the background, rather than under the control of a user at a terminal. Common examples of daemon processes are things like web servers, or database servers which will always be running in the background in order to serve requests.&lt;/p&gt;
  &lt;p&gt;Daemon processes are also at the core of your operating system. There are many processes that are constantly running in the background that keep your system functioning normally. These are things like the window server on a GUI system, printing services or audio services so that your speakers are always ready to play that annoying 'ding' notification.&lt;/p&gt;
  &lt;h2 id="the-first-process"&gt;The First Process&lt;/h2&gt;
  &lt;p&gt;There is one daemon process in particular that has special significance for your operating system. We talked in a previous chapter about every process having a parent process. Can that be true for all processes? What about the very first process on the system?&lt;/p&gt;
  &lt;p&gt;This is a classic who-created-the-creator kind of problem, and it has a simple answer. When the kernel is bootstrapped it spawns a process called the &lt;code&gt;init&lt;/code&gt; process. This process has a ppid of &lt;code&gt;0&lt;/code&gt; and is the 'grandparent of all processes'. It's the first one and it has no ancestor. Its pid is &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;
  &lt;h2 id="creating-your-first-daemon-process"&gt;Creating Your First Daemon Process&lt;/h2&gt;
  &lt;p&gt;What do we need to get started? Not much. Any process can be made into a daemon process.&lt;/p&gt;
  &lt;p&gt;Let's look to the &lt;a href="http://github.com/rack/rack"&gt;rack project&lt;/a&gt; for an example here. Rack ships with a &lt;code&gt;rackup&lt;/code&gt; command to serve applications using different rack supported web servers. Web servers are a great example of a process that will never end; so long as your application is active you'll need a server listening for connections.&lt;/p&gt;
  &lt;p&gt;The &lt;code&gt;rackup&lt;/code&gt; command includes an option to daemonize the server and run it in the background. Let's have a look at what that does.&lt;/p&gt;
  &lt;h2 id="diving-into-rack"&gt;Diving into Rack&lt;/h2&gt;
  &lt;div class="highlight"&gt;
&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;daemonize_app&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;RUBY_VERSION&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"1.9"&lt;/span&gt;
    &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;fork&lt;/span&gt;
    &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setsid&lt;/span&gt;
    &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;fork&lt;/span&gt;
    &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chdir&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt; 
    &lt;span class="no"&gt;STDIN&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reopen&lt;/span&gt; &lt;span class="s2"&gt;"/dev/null"&lt;/span&gt;
    &lt;span class="no"&gt;STDOUT&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reopen&lt;/span&gt; &lt;span class="s2"&gt;"/dev/null"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"a"&lt;/span&gt; 
    &lt;span class="no"&gt;STDERR&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reopen&lt;/span&gt; &lt;span class="s2"&gt;"/dev/null"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"a"&lt;/span&gt; 
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;daemon&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt; 
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;  &lt;/div&gt;
  &lt;p&gt;Lots going on here. Let's first jump to the &lt;code&gt;else&lt;/code&gt; block. Ruby 1.9.x ships with a method called &lt;code&gt;Process.daemon&lt;/code&gt; that will daemonize the current process! How convenient!&lt;/p&gt;
  &lt;p&gt;But don't you want to know how it works under the hood? I knew ya did! The truth is that if you look at the &lt;a href="https://github.com/ruby/ruby/blob/c852d76f46a68e28200f0c3f68c8c67879e79c86/process.c#L4817-4860"&gt;MRI source for &lt;code&gt;Process.daemon&lt;/code&gt;&lt;/a&gt; and stumble through the C code it ends up doing the exact same thing that Rack does in the &lt;code&gt;if&lt;/code&gt; block above. &lt;/p&gt;
  &lt;p&gt;So let's continue using that as an example. We'll break down the code line by line.&lt;/p&gt;
  &lt;h2 id="daemonizing-a-process-step-by-step"&gt;Daemonizing a Process, Step by Step&lt;/h2&gt;
  &lt;div class="highlight"&gt;
  &lt;pre&gt;&lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;fork&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
  &lt;p&gt;This line of code makes intelligent use of the return value of the &lt;code&gt;fork&lt;/code&gt; method. Recall from the forking chapter that &lt;code&gt;fork&lt;/code&gt; returns twice, once in the parent process and once in the child process. In the parent process it returns the child's pid and in the child process it returns nil.&lt;/p&gt;
  &lt;p&gt;As always, the return value will be truth-y for the parent and false-y for the child. This means that the parent process will exit, and as we know, orphaned child processes carry on as normal.&lt;/p&gt;
  &lt;div class="info-block notice"&gt;
    &lt;p&gt;If a process is orphaned then what happens when you ask for &lt;code&gt;Process.ppid&lt;/code&gt;?&lt;/p&gt;
    &lt;p&gt;This is where knowledge of the &lt;code&gt;init&lt;/code&gt; process becomes relevant. The ppid of orphaned processes is always &lt;code&gt;1&lt;/code&gt;. This is the only process that the kernel can be sure is active at all times.&lt;/p&gt;
&lt;/div&gt;
  &lt;p&gt;This step is imperative when creating a daemon because it causes the terminal that invoked this script to think the command is done, returning control to the terminal and taking it out of the equation.&lt;/p&gt;
  &lt;div class="highlight"&gt;
  &lt;pre&gt;&lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setsid&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
  &lt;p&gt;Calling &lt;code&gt;Process.setsid&lt;/code&gt; does three things:&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;The process becomes a session leader of a new session&lt;/li&gt;
    &lt;li&gt;The process becomes the process group leader of a new process group&lt;/li&gt;
    &lt;li&gt;The process has no controlling terminal&lt;/li&gt;
&lt;/ol&gt;
  &lt;p&gt;To understand exactly what effect these three things have we need to step out of the context of our Rack example for a moment and look a little deeper.&lt;/p&gt;
  &lt;h2 id="process-groups-and-session-groups"&gt;Process Groups and Session Groups&lt;/h2&gt;
  &lt;p&gt;Process groups and session groups are all about job control. By 'job control' I'm referring to the way that processes are handled by the terminal.&lt;/p&gt;
  &lt;p&gt;We begin with process groups.&lt;/p&gt;
  &lt;p&gt;Each and every process belongs to a group, and each group has a unique integer id. A process group is just a collection of related processes, typically a parent process and its children. However you can also group your processes arbitrarily by setting their group id using &lt;code&gt;Process.setpgrp(new_group_id)&lt;/code&gt;.&lt;/p&gt;
  &lt;p&gt;Have a look at the output from the following snippet.&lt;/p&gt;
  &lt;div class="highlight"&gt;
  &lt;pre&gt;&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class=
"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getpgrp&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
  &lt;p&gt;If you ran that code in an &lt;code&gt;irb&lt;/code&gt; session then those two values will be equal. Typically the process group id will be the same as the pid of the process group leader. The process group leader is the 'originating' process of a terminal command. ie. If you start an &lt;code&gt;irb&lt;/code&gt; process at the terminal it will become the group leader of a new process group. Any child processes that it creates will be made part of the same process group.&lt;/p&gt;
  &lt;p&gt;Try out the following example to see that process groups are inherited.&lt;/p&gt;
  &lt;div class="highlight"&gt;
  &lt;pre&gt;&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getpgrp&lt;/span&gt;

&lt;span class="nb"&gt;fork&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getpgrp&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
  &lt;p&gt;You can see that although the child process gets a unique pid it inherits the group id from its parent. So these two processes are part of the same group.&lt;/p&gt;
  &lt;p&gt;You'll recall that we looked previously at Orphaned Processes. In that section I said that child processes are not given special treatment by the kernel. Exit a parent process and the child will continue on. This is the behaviour when a parent process exits, but the behaviour is a bit different when the parent process is being controlled by a terminal and is killed by a signal.&lt;/p&gt;
  &lt;p&gt;Consider for a moment: a Ruby script that shells out to a long-running shell command, eg. a long backup script. What happens if you kill the Ruby script with a Ctrl-C?&lt;/p&gt;
  &lt;p&gt;If you try this out you'll notice that the long-running backup script is not orphaned, it &lt;em&gt;does not&lt;/em&gt; continue on when its parent is killed. We haven't set up any code to forward the signal from the parent to the child, so how is this done?&lt;/p&gt;
  &lt;p&gt;The terminal receives the signal and forwards it on to any process in the foreground process group. In this case, both the Ruby script and the long-running shell command would part of the same process group, so they would both be killed by the same signal.&lt;/p&gt;
  &lt;p&gt;And then session groups...&lt;/p&gt;
  &lt;p&gt;A session group is one level of abstraction higher up, a collection of process groups. Consider the following shell command:&lt;/p&gt;
  &lt;div class="highlight"&gt;
  &lt;pre&gt;&lt;span class="go"&gt;git log | grep shipped | less&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
  &lt;p&gt;In this case each command will get its own process group, since each may be creating child processes but none is a child process of another. Even though these commands are not part of the same process group one Ctrl-C will kill them all. &lt;/p&gt;
  &lt;p&gt;These commands are part of the same session group. Each invocation from the shell gets its own session group. An invocation may be a single command or a string of commands joined by pipes.&lt;/p&gt;
  &lt;p&gt;Like in the above example, a session group may be attached to a terminal. It might also not be attached to any terminal, as in the case of a daemon.&lt;/p&gt;
  &lt;p&gt;Again, your terminal handles session groups in a special way: sending a signal to the session leader will forward that signal to all the process groups in that session, which will forward it to all the processes in those process groups. Turtles all the way down :)&lt;/p&gt;
  &lt;p&gt;There is a system call for retrieving the current session group id, getsid(2), but Ruby's core library has no interface to it. Using &lt;code&gt;Process.setsid&lt;/code&gt; will return the id of the new sesssion group it creates, you can store that if you need it.&lt;/p&gt;
  &lt;p&gt;So, getting back to our Rack example, in the first line a child process was forked and the parent exited. The originating terminal recognized the exit and returned control to the user, but the forked process still has the inherited group id and session id from its parent. At the moment this forked process is neither a session leader nor a group leader.&lt;/p&gt;
  &lt;p&gt;So the terminal still has a link to our forked process, if it were to send a signal to its session group the forked process would receive it, but we want to be fully detached from a terminal.&lt;/p&gt;
  &lt;p&gt;&lt;code&gt;Process.setsid&lt;/code&gt; will make this forked process the leader of a new process group and a new session group. Note that &lt;code&gt;Process.setsid&lt;/code&gt; will fail in a process that is already a process group leader, it can only be run from child processes.&lt;/p&gt;
  &lt;p&gt;This new session group does not have a controlling terminal, but technically one could be assigned.&lt;/p&gt;
  &lt;div class="highlight"&gt;
  &lt;pre&gt;&lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;fork&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
  &lt;p&gt;The forked process that had just become a process group and session group leader forks again and then exits.&lt;/p&gt;
  &lt;p&gt;This newly forked process is no longer a process group leader nor a session leader. Since the previous session leader had no controlling terminal, and this process is not a session leader, it's guaranteed that this process can never have a controlling terminal. Terminals can only be assigned to session leaders.&lt;/p&gt;
  &lt;p&gt;This dance ensures that our process is now fully detached from a controlling terminal and will run to its completion.&lt;/p&gt;
  &lt;div class="highlight"&gt;
  &lt;pre&gt;&lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chdir&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt; 
&lt;/pre&gt;
&lt;/div&gt;
  &lt;p&gt;This changes the current working directory to the root directory for the system. This isn't strictly necessary but it's an extra step to ensure that current working directory of the daemon doesn't disappear during it's execution.&lt;/p&gt;
  &lt;p&gt;This avoids problems where the directory that the daemon was started from gets deleted or unmounted for any reason.&lt;/p&gt;
  &lt;div class="highlight"&gt;
  &lt;pre&gt;&lt;span class="no"&gt;STDIN&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reopen&lt;/span&gt; &lt;span class="s2"&gt;"/dev/null"&lt;/span&gt;
&lt;span class="no"&gt;STDOUT&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reopen&lt;/span&gt; &lt;span class="s2"&gt;"/dev/null"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"a"&lt;/span&gt; 
&lt;span class="no"&gt;STDERR&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reopen&lt;/span&gt; &lt;span class="s2"&gt;"/dev/null"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"a"&lt;/span&gt; 
&lt;/pre&gt;
&lt;/div&gt;
  &lt;p&gt;This sets all of the standard streams to go to &lt;code&gt;/dev/null&lt;/code&gt;, a.k.a. to be ignored. Since the daemon is no longer attached to a terminal session these are of no use anyway. They can't simply be closed because some programs expect them to always be available. Redirecting them to &lt;code&gt;/dev/null&lt;/code&gt; ensures that they're still available to the program but have no effect.&lt;/p&gt;
  &lt;h2 id="in-the-real-world-8"&gt;In the Real World&lt;/h2&gt;
  &lt;p&gt;As mentioned, the &lt;code&gt;rackup&lt;/code&gt; command ships with a command line option for daemonizing the process. Same goes with any of the popular Ruby web servers.&lt;/p&gt;
  &lt;p&gt;If you want to dig in to more internals of daemon processes you should look at the &lt;a href="http://rubygems.org/gems/daemons"&gt;&lt;code&gt;daemons&lt;/code&gt; rubygem&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;If you think you want to create a daemon process you should ask yourself one basic question: Does this process need to stay responsive forever? &lt;/p&gt;
  &lt;p&gt;If the answer is no then you probably want to look at a cron job or background job system. If the answer is yes, then you probably have a good candidate for a daemon process.&lt;/p&gt;
  &lt;h2 id="system-calls-8"&gt;System Calls&lt;/h2&gt;
  &lt;p&gt;Ruby's &lt;code&gt;Process.setsid&lt;/code&gt; maps to setsid(2), &lt;code&gt;Process.getpgrp&lt;/code&gt; maps to getpgrp(2). Other system calls mentioned in this chapter were covered in detail in previous chapters.&lt;/p&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/YW-8zE0DtMyTAtcbBtal0dRGWqo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/YW-8zE0DtMyTAtcbBtal0dRGWqo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/YW-8zE0DtMyTAtcbBtal0dRGWqo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/YW-8zE0DtMyTAtcbBtal0dRGWqo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/83pJ1IavxY8" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2012/04/19/daemon-processes-in-ruby.html</feedburner:origLink></entry>
 
 <entry>
   <title>How to Give a Good Tech Talk</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/71bMlIHhC2k/how-to-give-a-tech-talk.html" />
   <updated>2012-04-12T00:00:00-04:00</updated>
   <id>http://jstorimer.com/2012/04/12/how-to-give-a-tech-talk</id>
   <content type="html">&lt;p&gt;So I'm giving a talk next week. My first.&lt;/p&gt;

&lt;p&gt;It's an internal talk at Shopify, and I want it to be good. But I have no idea what I'm doing, I've never done this before.&lt;/p&gt;

&lt;p&gt;So what did I do? I turned to the internet and found a bunch of great resources. While preparing the talk this week I've been looking over them and getting some great advice about how to go about giving and preparing talks. Without further ado here's the list:&lt;/p&gt;

&lt;p&gt;p.s. I've personally consumed all of these resources and definitely recommend them.&lt;/p&gt;

&lt;h2&gt;Free&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.ted.com/talks/nancy_duarte_the_secret_structure_of_great_talks.html"&gt;The secret structure of great talks&lt;/a&gt; - Really enlightening TED video. See the structure underlying both 'I Have a Dream' and the 2007 iPhone launch announcement.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.walkingpaper.org/695"&gt;HOWTO Give a Good Presentation&lt;/a&gt; - Good tips to keep in mind.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://zachholman.com/posts/slide-design-for-developers/"&gt;Slide Design for Developers&lt;/a&gt; - Make your slides have an impact but support what you're saying, rather than sayint it for you.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nubyonrails.com/articles/improve-your-technical-slides"&gt;Improve Your Technical Slides&lt;/a&gt; - Nine easy tips that will help you communicate better at your next conference.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Paid&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.speakingforhackers.com/"&gt;Speaking for Hackers&lt;/a&gt; - An in-progress ebook of tips. Covers end-to-end from proposing to planning to speaking.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://tekpub.com/productions/ft_speaker"&gt;The Art of Speaking&lt;/a&gt; - Watch a respected speaker prepare a talk from scratch in 90 mins. Lots of great advice.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Exemplary Talks&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.confreaks.com/videos/706-rubyconf2011-how-github-uses-github-to-build-github"&gt;How Github uses Github to Build Github&lt;/a&gt; - Great talk, great slides. Follows the pattern revealed in the TED talk.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.confreaks.com/videos/763-rubymidwest2011-confident-code"&gt;Confident Code&lt;/a&gt; - The example code used in this one is particularly compelling. Also conforms to the pattern from the TED talk.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Let me know if I'm missing any other great resources. I'll continue to update this post as I come across more.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/RohQZ-MRo787SOhmJcotevHv3kU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/RohQZ-MRo787SOhmJcotevHv3kU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/RohQZ-MRo787SOhmJcotevHv3kU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/RohQZ-MRo787SOhmJcotevHv3kU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/71bMlIHhC2k" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2012/04/12/how-to-give-a-tech-talk.html</feedburner:origLink></entry>
 
 <entry>
   <title>Put Your Inbox in the Upstairs Bathroom</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/QhO083gsu5c/put-your-inbox-in-the-upstairs-bathroom.html" />
   <updated>2012-03-22T00:00:00-04:00</updated>
   <id>http://jstorimer.com/2012/03/22/put-your-inbox-in-the-upstairs-bathroom</id>
   <content type="html">&lt;p&gt;My house has two bathrooms.&lt;/p&gt;

&lt;p&gt;One is upstairs and one is downstairs. In order to understand the story you need to know that the bedroom and main bathroom are upstairs. Downstairs is just a half bath, as they say. I work from home and spend most of my day downstairs. When I have to use the bathroom, I use the downstairs one; no surprise there.&lt;/p&gt;

&lt;p&gt;A few weeks ago a peculiar thing happened: my wife took our toothbrushes, which usually reside in the upstairs bathroom, and put them in the downstairs bathroom. I can usually manage to brush my teeth twice a day: once in the morning after I get up and once at night before I go to bed. I'd really like to brush my teeth after every meal. I'm currently eating tons of fresh fruit and vegetables which really takes its toll on teeth, so I really should be brushing several times per day.&lt;/p&gt;

&lt;p&gt;Alas, when the toothbrush is upstairs it's out of sight and out of mind. As such, I rarely venture upstairs in the middle of the day simply to brush my teeth and return downstairs.&lt;/p&gt;

&lt;p&gt;However, when my toothbrush was brought downstairs I found myself brushing my teeth far more often. I was reminded of its presence every time I went to the bathroom and found it far easier to take an extra few minutes to brush my teeth several times per day.&lt;/p&gt;

&lt;p&gt;So going forward I'm going to keep my toothbrush in the downstairs bathroom. My email inbox, however, will be moved to the upstairs bathroom.&lt;/p&gt;

&lt;p&gt;For the longest time I kept my inbox in the downstairs bathroom. I'll stop mincing words and say that I checked my inbox too often. Why is this a problem? Checking email is a really great way for me to break my concentration, reduce my motivation, and totally switch contexts.&lt;/p&gt;

&lt;p&gt;So why was I checking so often? There are certainly psychological factors, wanting to respond quickly to coworkers, procrastination, but one of the biggest factors was that &lt;strong&gt;checking my inbox was just too plain easy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I was using a nice GUI email client. It wanted to send me growl notifications whenever I got a new message and show me how many unread messages I had on its Dock icon. Needless to say, I turned off these features. However, this made no difference, it was still too easy to check. Anytime I was programming I could quickly press Cmd-Tab and just have a peek at my inbox. This quickly became a reflex action. I was checking my inbox every minute or so as I waited for a test run. It was literally optimized down to a sub-second operation.&lt;/p&gt;

&lt;p&gt;So how did I remedy this? I now read my email using mutt(1).&lt;/p&gt;

&lt;p&gt;There are a few things that make this better. The main thing is when I want to check my inbox I perform the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open a new terminal session.&lt;/li&gt;
&lt;li&gt;Launch mutt.&lt;/li&gt;
&lt;li&gt;Watch in detail as mutt makes the initial connection, authenticates, and pulls down new messages.&lt;/li&gt;
&lt;li&gt;Read email.&lt;/li&gt;
&lt;li&gt;Close mutt.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;I've found this technique very effective in clobbering my addiction to checking my inbox. Why is it so effective? &lt;strong&gt;My mail is never just sitting there waiting for me&lt;/strong&gt;. If I want to check my inbox it takes about 15 seconds of my time from having the idea to seeing my new mail. Believe it or not, this is often enough to prevent me from even getting started with checking my inbox. A sub-second operation became a 15-second operation.&lt;/p&gt;

&lt;p&gt;My email inbox used to be even closer than the downstairs bathroom. It was akin to keeping my toothbrush proppped up on my shoulder in case I felt like I had an extra few seconds to brush my teeth. Now my inbox is at a safe distance. About 15 seconds away. About the same distance as my upstairs bathroom.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/4xPnsKYqPhbMZZOQ7nOfaCyG9-U/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4xPnsKYqPhbMZZOQ7nOfaCyG9-U/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/4xPnsKYqPhbMZZOQ7nOfaCyG9-U/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4xPnsKYqPhbMZZOQ7nOfaCyG9-U/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/QhO083gsu5c" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2012/03/22/put-your-inbox-in-the-upstairs-bathroom.html</feedburner:origLink></entry>
 
 <entry>
   <title>A Unix Shell in Ruby - Part 4: Pipes</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/CLsEJ8N1fQg/a-unix-shell-in-ruby-pipes.html" />
   <updated>2012-03-18T00:00:00-04:00</updated>
   <id>http://jstorimer.com/2012/03/18/a-unix-shell-in-ruby-pipes</id>
   <content type="html">&lt;p&gt;In this article we'll investigate a peculiarity. It will reveal an impostor and eventually lead to implementing shell pipelines. You may want to read &lt;a href="/2012/02/16/a-unix-shell-in-ruby.html"&gt;part 1&lt;/a&gt;, &lt;a href="/2012/02/21/a-unix-shell-in-ruby-builtins.html"&gt;part 2&lt;/a&gt;, or &lt;a href="/2012/03/10/a-unix-shell-in-ruby-search-path.html"&gt;part 3&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;First, the Peculiarity&lt;/h2&gt;

&lt;p&gt;Observe these interactions with the &lt;code&gt;shirt&lt;/code&gt; shell:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; ./shirt 
&lt;span class="gp"&gt;$&lt;/span&gt; ls
&lt;span class="go"&gt;LICENSE README shirt&lt;/span&gt;
&lt;span class="gp"&gt;$&lt;/span&gt; ls | grep README
&lt;span class="go"&gt;README&lt;/span&gt;
&lt;span class="gp"&gt;$&lt;/span&gt; ls &amp;gt; output.txt
&lt;span class="gp"&gt;$&lt;/span&gt; cat output.txt &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;win&amp;#39;&lt;/span&gt;
&lt;span class="go"&gt;LICENSE&lt;/span&gt;
&lt;span class="go"&gt;README&lt;/span&gt;
&lt;span class="go"&gt;output.txt&lt;/span&gt;
&lt;span class="go"&gt;shirt&lt;/span&gt;
&lt;span class="go"&gt;win&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;These are typical shell interactions, except that &lt;code&gt;shirt&lt;/code&gt; hasn't implemented these features yet. There's no code in the project to handle features such as pipes, output redirection, conditional execution, etc. These things are basically syntactic sugar that the shell provides on top of the system capabilities, so it's up to &lt;code&gt;shirt&lt;/code&gt; to implement it. So where does this peculiarity come from?&lt;/p&gt;

&lt;p&gt;If you look at the &lt;code&gt;shirt&lt;/code&gt; &lt;a href="https://github.com/jstorimer/shirt/blob/third/shirt#L10-18"&gt;source&lt;/a&gt; it's not too hard to figure out. There are only two code paths that a command can take at the moment, either it's a builtin command or it gets sent to &lt;code&gt;exec&lt;/code&gt;. None of the commands we used in the example session above were builtins so the strange behaviour must be coming from &lt;code&gt;exec&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Before I unearth the mystery I want to make clear the expected behaviour of &lt;code&gt;exec&lt;/code&gt; and then I'll do the big reveal.&lt;/p&gt;

&lt;h2&gt;The Base Case&lt;/h2&gt;

&lt;p&gt;In &lt;a href="/2012/02/16/a-unix-shell-in-ruby.html"&gt;part 1&lt;/a&gt; I explained the semantics of exec(2). It transforms the current process into a new process based on the command given as input.&lt;/p&gt;

&lt;p&gt;That makes perfect sense when you do something like &lt;code&gt;exec('ls')&lt;/code&gt;. The current process becomes an instance of &lt;code&gt;ls&lt;/code&gt;. But what about something like &lt;code&gt;exec('ls | grep README')&lt;/code&gt;? Based on my description this method invocation doesn't really make sense. There are actually two programs specified in that command joined by a pipe. The current process can't become two other processes, so there must be something else at play here.&lt;/p&gt;

&lt;p&gt;Before we look at the source for a Ruby VM I want to show what is happening with the processes visually. This is output from a tool called pstree(1). It prints a textual representation of the process hierarchy clearly showing child processes of a given process, for instance&lt;sup&gt;1.&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;The following &lt;code&gt;shirt&lt;/code&gt; session:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; ./shirt
&lt;span class="gp"&gt;$&lt;/span&gt; ls
&lt;span class="go"&gt;LICENSE README shirt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;yields this from pstree(1):&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="go"&gt;-+= 24853 jessestorimer ruby ./shirt&lt;/span&gt;
&lt;span class="go"&gt; \--- 31837 jessestorimer ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This is exactly what we expected. We have a &lt;code&gt;shirt&lt;/code&gt; process with one child, an &lt;code&gt;ls&lt;/code&gt; process. This comes about because we created a child process with &lt;code&gt;fork&lt;/code&gt;, then used &lt;code&gt;exec&lt;/code&gt; to transform that to an &lt;code&gt;ls&lt;/code&gt; process. So far so good.&lt;/p&gt;

&lt;h2&gt;An Impostor in the Lineage&lt;/h2&gt;

&lt;p&gt;The following &lt;code&gt;shirt&lt;/code&gt; session:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; ./shirt
&lt;span class="gp"&gt;$&lt;/span&gt; ls | grep README
&lt;span class="go"&gt;README&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;yields this from pstree(1):&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="go"&gt;-+= 57816 jessestorimer ruby ./shirt&lt;/span&gt;
&lt;span class="go"&gt; \-+- 58082 jessestorimer sh -c ls | grep README&lt;/span&gt;
&lt;span class="go"&gt;   |--- 58083 jessestorimer ls&lt;/span&gt;
&lt;span class="go"&gt;   \--- 58084 jessestorimer grep README&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;That one looks different. The first child of &lt;code&gt;shirt&lt;/code&gt; is &lt;code&gt;sh&lt;/code&gt;! &lt;code&gt;sh&lt;/code&gt;, often referred to as &lt;code&gt;/bin/sh&lt;/code&gt; is the &lt;a href="http://en.wikipedia.org/wiki/Bourne_shell"&gt;Bourne shell&lt;/a&gt;, predecessor to Bash (a.k.a Bourne-Again SHell). It's the inspiration for the syntax and functionality of most modern shells and is available on most any Unix system. But let's go back and understand the pstree(1) output.&lt;/p&gt;

&lt;p&gt;So the first child of &lt;code&gt;shirt&lt;/code&gt; is &lt;code&gt;sh&lt;/code&gt;. Then &lt;code&gt;sh&lt;/code&gt; has two children in &lt;code&gt;ls&lt;/code&gt; and &lt;code&gt;grep&lt;/code&gt;. So that's how all of the commands I showed above are working: &lt;code&gt;exec&lt;/code&gt; is actually sending that input to a different shell. This is certainly against the spirit of our project here and we want to implement everything that would otherwise be implemented by a shell like &lt;code&gt;sh&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;The Big Reveal&lt;/h2&gt;

&lt;p&gt;Let's look at the Rubinius source code for &lt;code&gt;exec&lt;/code&gt; and see where it decides to use a subshell:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="lineno"&gt; 1&lt;/span&gt;     &lt;span class="c1"&gt;# kernel/common/process.rb&lt;/span&gt;
&lt;span class="lineno"&gt; 2&lt;/span&gt; 
&lt;span class="lineno"&gt; 3&lt;/span&gt;     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt; 4&lt;/span&gt;       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty?&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kind_of?&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
&lt;span class="lineno"&gt; 5&lt;/span&gt;         &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;Errno&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ENOENT&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty?&lt;/span&gt;
&lt;span class="lineno"&gt; 6&lt;/span&gt;         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sr"&gt;/([*?{}\[\]&amp;lt;&amp;gt;()~&amp;amp;|$;&amp;#39;`&amp;quot;\n\s]|[^\w-])/o&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt; 7&lt;/span&gt;           &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;perform_exec&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/bin/sh&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;sh&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;-c&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="lineno"&gt; 8&lt;/span&gt;         &lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="lineno"&gt; 9&lt;/span&gt;           &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;perform_exec&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="lineno"&gt;10&lt;/span&gt;         &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;11&lt;/span&gt;       &lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="lineno"&gt;12&lt;/span&gt;         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kind_of?&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;
&lt;span class="lineno"&gt;13&lt;/span&gt;           &lt;span class="n"&gt;prog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="lineno"&gt;14&lt;/span&gt;           &lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="lineno"&gt;15&lt;/span&gt;         &lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="lineno"&gt;16&lt;/span&gt;           &lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;
&lt;span class="lineno"&gt;17&lt;/span&gt;         &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;18&lt;/span&gt; 
&lt;span class="lineno"&gt;19&lt;/span&gt;         &lt;span class="n"&gt;argv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="lineno"&gt;20&lt;/span&gt;         &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="lineno"&gt;21&lt;/span&gt;           &lt;span class="n"&gt;argv&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_s&lt;/span&gt;
&lt;span class="lineno"&gt;22&lt;/span&gt;         &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;23&lt;/span&gt; 
&lt;span class="lineno"&gt;24&lt;/span&gt;         &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;perform_exec&lt;/span&gt; &lt;span class="n"&gt;prog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;
&lt;span class="lineno"&gt;25&lt;/span&gt;       &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;26&lt;/span&gt;     &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;27&lt;/span&gt;     &lt;span class="kp"&gt;module_function&lt;/span&gt; &lt;span class="ss"&gt;:exec&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The most relevant lines for our purposes are #4 and #6. On line #4 it enters the first &lt;code&gt;if&lt;/code&gt; block if it's given only a String as an argument. You can see that line #6 has a gnarly regex which, if matched, will cause &lt;code&gt;exec&lt;/code&gt; to actually create an instance of &lt;code&gt;/bin/sh&lt;/code&gt; and pass the string along to it. How can we prevent this from happening in &lt;code&gt;shirt&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;The simplest way is: never pass a string of input directly in to &lt;code&gt;exec&lt;/code&gt;. You can see that, in that case, we'd enter the outer &lt;code&gt;else&lt;/code&gt; block where there's no chance of shelling out to a different shell. The only exception to the rule is if you pass a 'plain' string to &lt;code&gt;exec&lt;/code&gt;. This is something like &lt;code&gt;exec('ls')&lt;/code&gt;. In that case it won't match the gnarly regex and will hit line #9 which does an &lt;code&gt;exec&lt;/code&gt; on that command without a subshell.&lt;/p&gt;

&lt;p&gt;So, the first argument given to &lt;code&gt;exec&lt;/code&gt; should be the name of the program to be executed, while the rest of the arguments will be treated as a list of the command-line arguments to that program. In Ruby we know this as &lt;code&gt;ARGV&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's the simple change we can make to &lt;code&gt;shirt&lt;/code&gt; so that it won't end up invoking the Bourne shell:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fork&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Previously we had just passed the &lt;code&gt;line&lt;/code&gt; into &lt;code&gt;exec&lt;/code&gt; here. The &lt;code&gt;line&lt;/code&gt; being a string of input from the user.&lt;/p&gt;

&lt;h2&gt;Aftermath&lt;/h2&gt;

&lt;p&gt;This is great, now we can be sure that &lt;code&gt;shirt&lt;/code&gt; isn't leaning on &lt;code&gt;/bin/sh&lt;/code&gt; for features. The downside is that the stuff we were doing at the beginning doesn't work any more. Let's try a pipeline:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; ./shirt
&lt;span class="gp"&gt;$&lt;/span&gt; ls | grep README
&lt;span class="go"&gt;ls: grep: No such file or directory&lt;/span&gt;
&lt;span class="go"&gt;ls: |: No such file or directory&lt;/span&gt;
&lt;span class="go"&gt;README&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;That's some pretty strange output. In this case &lt;code&gt;ls&lt;/code&gt; is being sent to &lt;code&gt;exec&lt;/code&gt; as the command to execute and the rest of the line is being treated as the argument list for &lt;code&gt;ls&lt;/code&gt;. Since &lt;code&gt;ls&lt;/code&gt; expects its arguments to be names of files or directories it's telling us that its first two arguments don't exist on the filesystem. Notice that it successfully printed the last entry? That's because it's in a directory that actually contains a README file, so that one does work correctly.&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;shirt&lt;/code&gt; needs pipes. Time to start plumbing.&lt;/p&gt;

&lt;h2&gt;Shell Pipelines Demystified&lt;/h2&gt;

&lt;p&gt;I think shell pipelines are misunderstood. For the longest time I had no idea how they worked. More than once I read someone casually tossing up something like:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Yeah, the shell just uses the pipe(2) system call to hook up the stdout from one process to the stdin of the other.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Oh?&lt;/p&gt;

&lt;p&gt;I had some idea what stdin and stdout was, but I didn't know anything about a pipe(2) system call. It was certainly harder to understand than the simplicity of using pipes in my shell.&lt;/p&gt;

&lt;p&gt;The reason I'm telling you this is because I want you to understand that there's no mystery behind pipes in the shell. Going forward I'm going to refer to pipes in the shell as 'shell pipelines' or just 'pipelines'. When I say 'pipe' I'm going to be referring to the programmatic concept of the pipe, which is used to implement shell pipelines but can also be used for a myriad of other things.&lt;/p&gt;

&lt;h2&gt;The Shell Pipeline&lt;/h2&gt;

&lt;p&gt;First things first, we know we're going to need a 'pipe'. What does that look like? Let's ask &lt;code&gt;irb&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pipe&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="c1"&gt;#&amp;lt;IO:fd 5&amp;gt;, #&amp;lt;IO:fd 6&amp;gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;In Ruby, &lt;code&gt;IO.pipe&lt;/code&gt; will create a pipe using the pipe(2) system call. It returns an array with two &lt;code&gt;IO&lt;/code&gt; objects. These &lt;code&gt;IO&lt;/code&gt; objects are a bit like anonymous files. They can read from them and written to like files, but they have no location on the filesystem.&lt;/p&gt;

&lt;p&gt;Something else about the pipe: Although it returns two IO objects &lt;strong&gt;the pipe only allows for a uni-directional stream of data&lt;/strong&gt;. So the first &lt;code&gt;IO&lt;/code&gt; object in that array is &lt;em&gt;read-only&lt;/em&gt;, the second &lt;code&gt;IO&lt;/code&gt; object is &lt;em&gt;write-only&lt;/em&gt;. In this way data can travel only one way along the pipe.&lt;/p&gt;

&lt;p&gt;So, step one in creating a shell pipeline is to create the pipe. Let's represent this with a diagram. This is a &lt;code&gt;shirt&lt;/code&gt; process:&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/pipes/shirt-with-pipes.png" alt="Shirt after creating a pipe" /&gt;&lt;/p&gt;

&lt;p&gt;So our shell now has a pipe. Let's say, for example, that we're going to be creating the following pipeline: &lt;code&gt;ls | grep README&lt;/code&gt;. There are two processes there so &lt;code&gt;shirt&lt;/code&gt; must fork two child processes.&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/pipes/shirt-with-two-children.png" alt="Shirt after forking two child processes" /&gt;&lt;/p&gt;

&lt;p&gt;Remember that &lt;code&gt;fork&lt;/code&gt; creates an exact copy of the calling process. So the child processes got their own copy of the pipe that the parent process created.&lt;/p&gt;

&lt;p&gt;Eventually the left child will become &lt;code&gt;ls&lt;/code&gt; and the right will become &lt;code&gt;grep&lt;/code&gt;. But first we need to set up the pipe.&lt;/p&gt;

&lt;p&gt;We're going to tell the left child (the one that will become &lt;code&gt;ls&lt;/code&gt;) that it should redirect its &lt;code&gt;$stdout&lt;/code&gt; to the write-only &lt;code&gt;IO&lt;/code&gt; object. In this way anything that &lt;code&gt;ls&lt;/code&gt; writes to its &lt;code&gt;$stdout&lt;/code&gt; will fill up the pipe and wait there for the &lt;code&gt;grep&lt;/code&gt; process to read it.&lt;/p&gt;

&lt;p&gt;Similarly we'll tell the right child (the one that will become &lt;code&gt;grep&lt;/code&gt;) that it should read its &lt;code&gt;$stdin&lt;/code&gt; from the read-only &lt;code&gt;IO&lt;/code&gt; object. This will be the receiving end of whatever the &lt;code&gt;ls&lt;/code&gt; process writes to the pipe. That might look something like this:&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/pipes/shirt-with-pipe-hooked-up.png" alt="Shirt with the pipe in place" /&gt;&lt;/p&gt;

&lt;p&gt;There's a bit of housecleaning to do still but we'll look at that when we step through the code.&lt;/p&gt;

&lt;p&gt;Now the first child process does its exec and becomes &lt;code&gt;ls&lt;/code&gt;. The second process does the same and becomes &lt;code&gt;grep&lt;/code&gt;. Just to give you a visual:&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/pipes/pipeline.png" alt="The final pipeline" /&gt;&lt;/p&gt;

&lt;p&gt;That's a rough overview of how a shell pipeline works from the view of processes. Now let's dive into the implementation in &lt;code&gt;shirt&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;The Ending, Then the Beginning&lt;/h2&gt;

&lt;p&gt;I'm going to start by pasting the code &lt;code&gt;shirt&lt;/code&gt; has after implementing pipelines. Then we'll step through the changes line by line.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
    &lt;span class="n"&gt;commands&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;split_on_pipes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;placeholder_in&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vg"&gt;$stdin&lt;/span&gt;
    &lt;span class="n"&gt;placeholder_out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vg"&gt;$stdout&lt;/span&gt;
    &lt;span class="n"&gt;pipe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;

    &lt;span class="n"&gt;commands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each_with_index&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;program&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Shellwords&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shellsplit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;builtin?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;program&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;call_builtin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;program&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;commands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
          &lt;span class="n"&gt;pipe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pipe&lt;/span&gt;
          &lt;span class="n"&gt;placeholder_out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pipe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
          &lt;span class="n"&gt;placeholder_out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vg"&gt;$stdout&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;

        &lt;span class="n"&gt;spawn_program&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;program&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;placeholder_out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;placeholder_in&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;placeholder_out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;placeholder_out&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="vg"&gt;$stdout&lt;/span&gt;
        &lt;span class="n"&gt;placeholder_in&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;placeholder_in&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="vg"&gt;$stdin&lt;/span&gt;
        &lt;span class="n"&gt;placeholder_in&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pipe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;waitall&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The first notable change is this line, after we get a line of input from &lt;code&gt;$stdin&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="n"&gt;commands&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;split_on_pipes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;...and here's the implementation:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;split_on_pipes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="sr"&gt;/([^&amp;quot;&amp;#39;|]+)|[&amp;quot;&amp;#39;]([^&amp;quot;&amp;#39;]+)[&amp;quot;&amp;#39;]/&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flatten&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compact&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This method takes a line of input and splits it using pipes as a delimiter. It's a bit hard to grok but the &lt;a href="http://rick.measham.id.au/paste/explain.pl?regex=%2F%28%5B%5E%22%27%7C%5D%2B%29%7C%5B%22%27%5D%28%5B%5E%22%27%5D%2B%29%5B%22%27%5D%2F"&gt;gist of it&lt;/a&gt; is that it matches one or more characters that are not a quote or a pipe &lt;em&gt;or&lt;/em&gt; it matches a quote, followed by some non-quote characters, followed by another quote. Full credit goes to &lt;a href="http://stackoverflow.com/a/4970136/1124616"&gt;http://stackoverflow.com/a/4970136/1124616&lt;/a&gt;. It returns an array of command strings.&lt;/p&gt;

&lt;p&gt;The reason we dance around the quotes and go to that trouble is that it should be possible to include a pipe character inside a quoted string, to pass as an argument to a program. If we were just to use a naive &lt;code&gt;line.split('|')&lt;/code&gt; then we'd end up splitting on pipe characters that were passed inside quotes as program arguments.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;    &lt;span class="n"&gt;placeholder_in&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vg"&gt;$stdin&lt;/span&gt;
    &lt;span class="n"&gt;placeholder_out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vg"&gt;$stdout&lt;/span&gt;
    &lt;span class="n"&gt;pipe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This is simply some boilerplate setup. We'll talk about these variables further into the source.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;    &lt;span class="n"&gt;commands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each_with_index&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;program&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Shellwords&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shellsplit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;builtin?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;program&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;call_builtin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;program&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now that we can have multiple commands running at one time we need to process each one individually, hence the loop.&lt;/p&gt;

&lt;p&gt;There's something notable here about the handling of builtins: it hasn't changed. Even though we'll be supporting pipes in the shell the builtin commands will not be able to use pipes in the same way that subprocesses do. I hope the reason why becomes clear as we look at the next two blocks of code, but I'll be sure to remind you when the time comes.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;commands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
        &lt;span class="n"&gt;pipe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pipe&lt;/span&gt;
        &lt;span class="n"&gt;placeholder_out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pipe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="n"&gt;placeholder_out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vg"&gt;$stdout&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This is some setup before we actually spawn a new process for the current command. This particular piece of code is responsible for setting up the future &lt;code&gt;$stdout&lt;/code&gt; of the current command.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;else&lt;/code&gt; block takes care of the case where the current command is the last one in the pipeline. In that case its &lt;code&gt;$stdout&lt;/code&gt; should be set to &lt;code&gt;$stdout&lt;/code&gt; of the shell. In this way the last command will print its output back to the terminal.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;if&lt;/code&gt; block takes care of the other commands in the pipeline. It creates a new pipe and assigns the future &lt;code&gt;$stdout&lt;/code&gt; of the current command to the write-only &lt;code&gt;IO&lt;/code&gt; object that it returned.&lt;/p&gt;

&lt;p&gt;Then we pass the program, arguments, and the placeholder stdin and stdout to the &lt;code&gt;spawn_program&lt;/code&gt; method.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;        &lt;span class="n"&gt;spawn_program&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;program&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;placeholder_out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;placeholder_in&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Here's the implementation:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;spawn_program&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;program&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;placeholder_out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;placeholder_in&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;fork&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;placeholder_out&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="vg"&gt;$stdout&lt;/span&gt;
      &lt;span class="vg"&gt;$stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;placeholder_out&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;placeholder_out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;placeholder_in&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="vg"&gt;$stdin&lt;/span&gt;
      &lt;span class="vg"&gt;$stdin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;placeholder_in&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;placeholder_in&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;program&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The fork + exec parts of this code are the same before, but there's new code too. There's a block of code to reopen &lt;code&gt;$stdout&lt;/code&gt; to point to the stdout placeholder we assigned earlier, this would be a write-only end of a pipe. If there is no placeholder stdout (ie. this is the last command in a pipeline) then we don't modify &lt;code&gt;$stdout&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We use &lt;code&gt;IO#reopen&lt;/code&gt; to change &lt;code&gt;$stdout&lt;/code&gt; to point to a different &lt;code&gt;IO&lt;/code&gt; object. We could have instead passed an instance of &lt;code&gt;File&lt;/code&gt; to have &lt;code&gt;$stdout&lt;/code&gt; write to a file.&lt;/p&gt;

&lt;p&gt;We give the same treatment to &lt;code&gt;$stdin&lt;/code&gt; below that.&lt;/p&gt;

&lt;p&gt;One very important point about this code: the placeholder &lt;code&gt;IO&lt;/code&gt; objects are closed after being passed to &lt;code&gt;#reopen&lt;/code&gt;. Why? We need a quick review of what happens with &lt;code&gt;IO#reopen&lt;/code&gt;. So &lt;code&gt;$stdout.reopen(placeholder_out)&lt;/code&gt; will reassociate &lt;code&gt;$stdout&lt;/code&gt; with the file descriptor that's pointed at by &lt;code&gt;placeholder_out&lt;/code&gt;. So now there are two references to the same file descriptor. Once we do the &lt;code&gt;exec&lt;/code&gt; and &lt;code&gt;ls&lt;/code&gt; finishes writing to its &lt;code&gt;$stdout&lt;/code&gt; it will close its &lt;code&gt;$stdout&lt;/code&gt;. This signals the process listening on the read-only end of the pipe that there is no more data to be sent so it can stop listening. But, if we didn't close &lt;code&gt;placeholder_out&lt;/code&gt; then the process listening on the read-only end of the pipe could never stop listening for more data because there is still an open reference to the write-only end of the pipe that might be written to. So, &lt;em&gt;make sure to close references to &lt;code&gt;IO&lt;/code&gt; objects you're not going to use&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In the end the program gets passed to &lt;code&gt;exec&lt;/code&gt; and the modified &lt;code&gt;$stdout&lt;/code&gt; and &lt;code&gt;$stdin&lt;/code&gt; are shared with the executed program.&lt;/p&gt;

&lt;p&gt;This is a good time to bring up builtins again. The reason that builtins can't participate in pipelines in this way is because they don't have their own &lt;code&gt;$stdin&lt;/code&gt; and &lt;code&gt;$stdout&lt;/code&gt; to redirect. They share these with &lt;code&gt;shirt&lt;/code&gt; since they're called in the context of the shell itself. So we'll have to hook them up in a different way, we'll save that for a later article.&lt;/p&gt;

&lt;p&gt;Lastly:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;        &lt;span class="n"&gt;placeholder_out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;placeholder_out&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="vg"&gt;$stdout&lt;/span&gt;
        &lt;span class="n"&gt;placeholder_in&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;placeholder_in&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="vg"&gt;$stdin&lt;/span&gt;
        &lt;span class="n"&gt;placeholder_in&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pipe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;waitall&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The first two lines here are related precisely to what I explained in the last section. The parent process also holds references to the &lt;code&gt;IO&lt;/code&gt; objects from the pipes. In order for the child processes to communicate properly the parent process needs to close its references to those &lt;code&gt;IO&lt;/code&gt; objects.&lt;/p&gt;

&lt;p&gt;The next line assigns the future &lt;code&gt;$stdin&lt;/code&gt; for the next process to the read-only &lt;code&gt;IO&lt;/code&gt; object returned from the pipe generated for the current command. Putting it at the end of the loop ensures that every command in the pipeline gets its &lt;code&gt;$stdin&lt;/code&gt; reassociated, except for the first command through the loop. This makes perfect sense because the first command can't take input from a command that came before it, because there isn't one.&lt;/p&gt;

&lt;p&gt;The last line here tells the current process to wait for all child processes to exit. Since we're now spawning multiple processes at one time we have to wait for all of them to finish before we can return control to the terminal. Currently &lt;code&gt;shirt&lt;/code&gt; doesn't inspect the return value from that call to check for failures, etc. but it'll need to do that in the future.&lt;/p&gt;

&lt;h2&gt;Whew!&lt;/h2&gt;

&lt;p&gt;If you're still reading then I hope you learned a thing or two and now understand how simple shell pipelines are. The more I look at the implementation of a Unix shell the more I realize how many system primitives were originally created for the purpose of implementing a shell.&lt;/p&gt;

&lt;p&gt;Next time around we'll implement another feature that was being handled by a subshell: io redirection.&lt;/p&gt;

&lt;hr /&gt;


&lt;p&gt;If you enjoy learning about this stuff then check out &lt;a href="http://workingwithunixprocesses.com"&gt;Working With Unix Processes&lt;/a&gt; because it's all about Unix programming for the Rubyist.&lt;/p&gt;

&lt;p&gt;The source for this article is available &lt;a href="https://github.com/jstorimer/shirt/tree/fourth"&gt;on github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;sup&gt;1&lt;/sup&gt; I got this data by first installing pstree through homebrew. Then I started up a shirt instance with &lt;code&gt;./shirt&lt;/code&gt;. I used ps(1) to get the pid of the &lt;code&gt;shirt&lt;/code&gt; process. Then I fed that into pstree as &lt;code&gt;pstree &amp;lt;pid&amp;gt;&lt;/code&gt; to get the output you see.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/jLbemULkDz3Q5FLyCBnr40A-jtM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jLbemULkDz3Q5FLyCBnr40A-jtM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/jLbemULkDz3Q5FLyCBnr40A-jtM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jLbemULkDz3Q5FLyCBnr40A-jtM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/CLsEJ8N1fQg" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2012/03/18/a-unix-shell-in-ruby-pipes.html</feedburner:origLink></entry>
 
 <entry>
   <title>eBooks for Programmers Should Include a TXT</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/7RETO8OCETU/ebooks-for-programming-should-include-txt.html" />
   <updated>2012-03-13T00:00:00-04:00</updated>
   <id>http://jstorimer.com/2012/03/13/ebooks-for-programming-should-include-txt</id>
   <content type="html">&lt;p&gt;If I'm not in the terminal then I'm not doing real work.&lt;/p&gt;

&lt;p&gt;Recently I had to refer to &lt;a href="http://workingwithunixprocesses.com"&gt;my book&lt;/a&gt; while I was working on a project. I work in a full-screen terminal and don't like to leave it. The world outside my terminal is filled with distractions, bright colours, and menus. My textual environment is where my real work happens.&lt;/p&gt;

&lt;p&gt;So to consult my book I opened the PDF version and kept switching context back and forth between the PDF and the terminal. Have you tried copying and pasting code from a PDF lately? Not perfect.&lt;/p&gt;

&lt;p&gt;I had the same experience when I was reading &lt;a href="http://devblog.avdi.org/2011/11/15/early-access-beta-of-objects-on-rails-now-available-2/"&gt;Objects on Rails&lt;/a&gt;. As I was reading the text I wanted to follow along with the code examples. I was annoyed with switching back and forth between my graphical reader and my programming environment.&lt;/p&gt;

&lt;p&gt;A few days later I read &lt;a href="http://minimalinux.blogspot.com/2012/01/ebook-is-ready.html"&gt;this&lt;/a&gt;. It's a free eBook about Linux, &lt;strong&gt;available in several formats including TXT&lt;/strong&gt;. Brilliant!&lt;/p&gt;

&lt;p&gt;This made perfect sense to me. As a programmer I'm used to working in the terminal. If I'm going to be referring to a technical book while I'm working then, of course, &lt;strong&gt;I want to be able to read the book from my terminal&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Back to my original issue: I converted both my book and my copy of Objects on Rails to TXT files&lt;sup&gt;1&lt;/sup&gt; and set this up:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; &lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;wwup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;less /path/to/workingwithunixprocesses.txt&amp;#39;&lt;/span&gt;
&lt;span class="gp"&gt;$&lt;/span&gt; &lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;oor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;less different//path/to/objectsonrails.txt&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now when I'm working in a terminal I can just open a new session and type &lt;code&gt;wwup&lt;/code&gt; or &lt;code&gt;oor&lt;/code&gt; to read the books.&lt;/p&gt;

&lt;p&gt;The best part about this is that the book is now in the realm of the powerful text processing tools offered in the terminal. There's simple things like piping the book text into grep(1) to search for something, but the most useful tool is certainly less(1). Notice that I loaded the text with less(1) as part of the alias I created.&lt;/p&gt;

&lt;p&gt;less(1) is so useful for this kind of stuff. Vim users will be right at home with its commands. You can scroll the text up and down line-by-line using &lt;code&gt;j&lt;/code&gt; and &lt;code&gt;k&lt;/code&gt; respectively. Use &lt;code&gt;Ctrl-d&lt;/code&gt; and &lt;code&gt;Ctrl-u&lt;/code&gt; to scroll the text up and down page-by-page. Besides the basic movement commands the most useful feature for reading is incremental search. Press &lt;code&gt;/&lt;/code&gt; and start typing to begin a search. Any matches in the text will be highlighted, at this point you can use &lt;code&gt;n&lt;/code&gt; to see the next match and &lt;code&gt;N&lt;/code&gt; to see the previous match.&lt;/p&gt;

&lt;p&gt;It's also really easy to play with some code while keeping the text open, the exact thing I wanted to do when reading through Objects on Rails. You can shell out from less(1) by prefixing a command with a &lt;code&gt;!&lt;/code&gt;. So you can use &lt;code&gt;!irb&lt;/code&gt; to open an irb session right from less(1). Copy and paste code that you're reading right into the irb session for easy tinkering. If I'm working on something more incremental I just split my shell horizontally, reading the book on one side and coding on the other side.&lt;/p&gt;

&lt;p&gt;I think I'll definitely start doing this for programming books that I'm reading. Especially for ones that are useful to keep around as references.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://workingwithunixprocesses.com"&gt;Working With Unix Processes&lt;/a&gt; now ships with a TXT version alongside the other formats. The book will be available at 40% off until this Friday because I think this is fun and I want you to have it.&lt;/p&gt;

&lt;p&gt;Happy Spring!&lt;/p&gt;

&lt;p&gt;&lt;sup&gt;1&lt;/sup&gt; I used pdftotext(1) (part of &lt;a href="http://www.foolabs.com/xpdf/"&gt;xpdf&lt;/a&gt;) to convert PDF files to TXT files. I used &lt;a href="http://www.mbayer.de/html2text/"&gt;html2text&lt;/a&gt; to convert HTML files to TXT files.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/J0kKcoil51m6YUmSb8da7Iu6tG0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/J0kKcoil51m6YUmSb8da7Iu6tG0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/J0kKcoil51m6YUmSb8da7Iu6tG0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/J0kKcoil51m6YUmSb8da7Iu6tG0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/7RETO8OCETU" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2012/03/13/ebooks-for-programming-should-include-txt.html</feedburner:origLink></entry>
 
 <entry>
   <title>A Unix Shell in Ruby - Part 3: A Login Shell and the PATH</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/7vfUfTKtnb0/a-unix-shell-in-ruby-search-path.html" />
   <updated>2012-03-10T00:00:00-05:00</updated>
   <id>http://jstorimer.com/2012/03/10/a-unix-shell-in-ruby-search-path</id>
   <content type="html">&lt;h2&gt;First, A Word of Warning&lt;/h2&gt;

&lt;p&gt;In this article I'm going to set up &lt;code&gt;shirt&lt;/code&gt; as the default login shell for my system to show what will happen when it's treated like every other shell. &lt;strong&gt;Be wary of doing this yourself&lt;/strong&gt;. I definitely encourage you to follow along at home, but make sure you read through the article first so you know what to expect and don't end up with a broken shell :)&lt;/p&gt;

&lt;h2&gt;Changing the Login Shell&lt;/h2&gt;

&lt;p&gt;Each user can specify which shell they want to use when opening a new terminal or logging in to the sytem.&lt;/p&gt;

&lt;p&gt;Changing the login shell can be done with the chsh(1) command. On OSX it can also be changed &lt;a href="http://hints.macworld.com/article.php?story=20071025221744166"&gt;through the GUI&lt;/a&gt;. Let's change my login shell to &lt;code&gt;shirt&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;sudo chsh -s /path/to/shirt &lt;span class="sb"&gt;`&lt;/span&gt;whoami&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;If I do that and launch a new terminal it dies immediately :/ So it appears that something didn't work.&lt;/p&gt;

&lt;p&gt;With a bit of digging I found that this is due to the 'shebang' line at the &lt;a href="https://github.com/jstorimer/shirt/blob/master/shirt#L1"&gt;beginning of the program&lt;/a&gt;. It tells the system to use the version of ruby specified by env(1). The env(1) command has everything to do with environment variables. Let's talk about those.&lt;/p&gt;

&lt;h2&gt;Environment Variables&lt;/h2&gt;

&lt;p&gt;Environment variables are a process-generic method of sharing data. I say process-generic because most any programming language has a way of reading and writing environment variables. I'll be referring to the collection of current environment variables as 'the environment'.&lt;/p&gt;

&lt;p&gt;We'll talk more about the environment in a bit, what we care about right now is how come &lt;code&gt;shirt&lt;/code&gt; died when we booted it as a login shell?&lt;/p&gt;

&lt;p&gt;One of the most important environment variables is called &lt;code&gt;PATH&lt;/code&gt;. The &lt;code&gt;PATH&lt;/code&gt; is an ordered list of directories specifying where the shell and the system calls should look for programs to execute. For example, a common &lt;code&gt;PATH&lt;/code&gt; looks like this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$PATH&lt;/span&gt;
&lt;span class="go"&gt;/usr/local/bin:/usr/bin:/bin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Each directory is separated by a colon. This &lt;code&gt;PATH&lt;/code&gt; tells the system to first look for programs in &lt;code&gt;/usr/local/bin&lt;/code&gt;, then, if it finds nothing there, look in &lt;code&gt;/usr/bin&lt;/code&gt;, then &lt;code&gt;/bin&lt;/code&gt;. In this way you can have a custom install of &lt;code&gt;vim&lt;/code&gt; in &lt;code&gt;/usr/local/bin&lt;/code&gt; that would be favoured over the system default &lt;code&gt;vim&lt;/code&gt; in &lt;code&gt;/usr/bin&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;How the PATH Broke Our Login Shell&lt;/h2&gt;

&lt;p&gt;When a login shell boots it has no customization. The system default, when booting a new login shell, is to set the &lt;code&gt;PATH&lt;/code&gt; to the following:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="go"&gt;/usr/bin:/bin:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;So when &lt;code&gt;shirt&lt;/code&gt; boots in this way the shebang line looks in the environment to find &lt;code&gt;ruby&lt;/code&gt;. With this &lt;code&gt;PATH&lt;/code&gt; the only version it will find is the system default at &lt;code&gt;/usr/bin/ruby&lt;/code&gt;. Since I'm on OS X the system default is MRI 1.8.7. So &lt;code&gt;shirt&lt;/code&gt; is being booted with this ruby.&lt;/p&gt;

&lt;p&gt;In my everyday shell I have the rbenv shims at the start of my &lt;code&gt;PATH&lt;/code&gt; so that when I run the &lt;code&gt;ruby&lt;/code&gt; command it's always handled by rbenv.&lt;/p&gt;

&lt;p&gt;As a responsible Ruby developer I have my global rbenv version set to MRI 1.9.3. Let's simulate what's happening with the login shell by trying to boot &lt;code&gt;shirt&lt;/code&gt; with the system ruby:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; /usr/bin/ruby shirt
&lt;span class="go"&gt;shirt:5: syntax error, unexpected &amp;#39;=&amp;#39;, expecting &amp;#39;|&amp;#39;&lt;/span&gt;
&lt;span class="go"&gt;  &amp;#39;cd&amp;#39; =&amp;gt; lambda { |dir = ENV[&amp;quot;HOME&amp;quot;]| Dir.chdir(dir) },&lt;/span&gt;
&lt;span class="go"&gt;                         ^&lt;/span&gt;
&lt;span class="go"&gt;shirt:5: syntax error, unexpected &amp;#39;}&amp;#39;, expecting $end&lt;/span&gt;
&lt;span class="go"&gt;  &amp;#39;cd&amp;#39; =&amp;gt; lambda { |dir = ENV[&amp;quot;HOME&amp;quot;]| Dir.chdir(dir) },&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Aha. So we're using some syntax that is only supported in Ruby 1.9. I'm OK with that, but that means we'll need to have 1.9 installed as the system default in order for &lt;code&gt;shirt&lt;/code&gt; to be a login shell. Rather than actually building Ruby and replacing the version at &lt;code&gt;/usr/bin/ruby&lt;/code&gt; I'm just going to move that one out of the way for now and symlink in my rbenv ruby.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; mv /usr/bin/ruby /usr/bin/ruby.orig
&lt;span class="gp"&gt;$&lt;/span&gt; ln -s &lt;span class="sb"&gt;`&lt;/span&gt;rbenv which ruby&lt;span class="sb"&gt;`&lt;/span&gt; /usr/bin/ruby
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now if I open a new shell it works!&lt;/p&gt;

&lt;h2&gt;Back on the Path&lt;/h2&gt;

&lt;p&gt;If you actually try to use this as your login shell you'll probably be frustrated, there's many things that still aren't implemented. Let's continue working with the &lt;code&gt;PATH&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Hypothetically, the first thing I need to do in this shell session is work with &lt;code&gt;redis-cli&lt;/code&gt;. I installed redis through homebrew, so that program was installed into &lt;code&gt;/usr/local/bin&lt;/code&gt;. If I try running &lt;code&gt;redis-cli&lt;/code&gt; from inside the &lt;code&gt;shirt&lt;/code&gt; login shell I get an error saying that it couldn't be found.&lt;/p&gt;

&lt;p&gt;I can use the env(1) command to inspect the current environment variables and I see that my &lt;code&gt;PATH&lt;/code&gt;, as expected, doesn't include &lt;code&gt;/usr/local/bin&lt;/code&gt;. Hence it can't find my &lt;code&gt;redis-cli&lt;/code&gt;. So we need a way to set environment variables.&lt;/p&gt;

&lt;p&gt;Since this will need to change the state of the shell itself, we'll implement it as a builtin.&lt;/p&gt;

&lt;h2&gt;Like Bash?&lt;/h2&gt;

&lt;p&gt;How does &lt;code&gt;bash&lt;/code&gt; handle this? It uses a command called export(1). Here's how we'd add a custom value to the &lt;code&gt;PATH&lt;/code&gt; in &lt;code&gt;bash&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/bin:&lt;span class="nv"&gt;$PATH&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;export(1) is telling &lt;code&gt;bash&lt;/code&gt; to set the variable &lt;code&gt;PATH&lt;/code&gt; to the previous value of &lt;code&gt;PATH&lt;/code&gt; (specified by &lt;code&gt;$PATH&lt;/code&gt;) prepended with &lt;code&gt;/usr/local/bin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Personally, I think &lt;code&gt;export&lt;/code&gt; is a little unclear as far as names go, so we'll use &lt;code&gt;set&lt;/code&gt; to specify changes to environment variables shell-wide.&lt;/p&gt;

&lt;h2&gt;Setting Environment Variables&lt;/h2&gt;

&lt;p&gt;Here's the implementation for &lt;code&gt;shirt&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="no"&gt;BUILTINS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  &lt;span class="s1"&gt;&amp;#39;set&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;=&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Notice how we simply set a key on the &lt;code&gt;ENV&lt;/code&gt; constant? &lt;code&gt;ENV&lt;/code&gt; is the Ruby interface to environment variables for the current process.&lt;/p&gt;

&lt;p&gt;It's a pretty naive approach, but it works. When using the &lt;code&gt;set&lt;/code&gt; command it simply splits the first argument on the '=' character. The first part is assumed to be the variable name, the second part is considered to be its value.&lt;/p&gt;

&lt;p&gt;Now issue the following commands to change and inspect the &lt;code&gt;PATH&lt;/code&gt; for our shell:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="go"&gt;-&amp;gt; set PATH=/usr/local/bin:/usr/bin:/bin&lt;/span&gt;
&lt;span class="go"&gt;-&amp;gt; env&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Notice that I specified the &lt;code&gt;PATH&lt;/code&gt; in full, rather than referring to the existing value (&lt;code&gt;$PATH&lt;/code&gt;) as we did with &lt;code&gt;bash&lt;/code&gt;. &lt;code&gt;shirt&lt;/code&gt; doesn't yet have a way to substite variables (or substitute other things a la backticks) into the command string. We'll tackle that problem all at once in another article.&lt;/p&gt;

&lt;p&gt;Now when I try to run my &lt;code&gt;redis-cli&lt;/code&gt; from &lt;code&gt;/usr/local/bin&lt;/code&gt; it works just fine!&lt;/p&gt;

&lt;h2&gt;Connecting the Dots&lt;/h2&gt;

&lt;p&gt;This comes full circle when we take into account that 1) a child process inherits the environment of its parent, and 2) the environment is preserved through an exec.&lt;/p&gt;

&lt;p&gt;That's how come &lt;code&gt;shirt&lt;/code&gt; was able to work previously and find programs in &lt;code&gt;/usr/local/bin&lt;/code&gt;. I had added &lt;code&gt;/usr/local/bin&lt;/code&gt; to my &lt;code&gt;PATH&lt;/code&gt; as part of my &lt;code&gt;.bashrc&lt;/code&gt; file, so when I would &lt;code&gt;exec&lt;/code&gt; or just launch an instance of &lt;code&gt;shirt&lt;/code&gt; it would inherit that environment, along with the customized &lt;code&gt;PATH&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Similarly, when &lt;code&gt;shirt&lt;/code&gt; forks a process to exec a command, the environment (and subsequently the &lt;code&gt;PATH&lt;/code&gt;) is passed all the way down. This is how &lt;code&gt;exec&lt;/code&gt; finds which program it should become when you pass it a program that's not at an absolute path.&lt;/p&gt;

&lt;h2&gt;'Local' Environment Variables&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;set&lt;/code&gt; command we implemented can change environment variables shell-wide, but what about when you want to change an environment variable just for the invocation of one command? This is very common (as you'll see from the examples below) and we can actually do it without changing &lt;code&gt;shirt&lt;/code&gt; at all.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;# Here&amp;#39;s how bash does it&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="no"&gt;RAILS_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;staging&lt;/span&gt; &lt;span class="n"&gt;rails&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="no"&gt;VERBOSE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt;

&lt;span class="c1"&gt;# Here&amp;#39;s how shirt does it (also works in bash)&lt;/span&gt;
&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="no"&gt;RAILS_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;staging&lt;/span&gt; &lt;span class="n"&gt;rails&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;
&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="no"&gt;VERBOSE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The env(1) command is available on most systems and fits this purpose exactly. &lt;code&gt;bash&lt;/code&gt; has that nice shorthand, but I don't feel the need to add that extra parsing code right now when the env(1) command does it so nicely.&lt;/p&gt;

&lt;h2&gt;More Environment Variables&lt;/h2&gt;

&lt;p&gt;Now that we have a facility for changing environment variables we can add some more customization to our shell. The prompt, for instance.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;PROMPT&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;-&amp;gt; &amp;#39;&lt;/span&gt;

&lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="vg"&gt;$stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;PROMPT&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now the prompt can be customized simply by setting the &lt;code&gt;PROMPT&lt;/code&gt; environment variable. It's still primitive in that you can't dynamically use commands in the prompt line, but that will be added later when we have a more general way of evaluating command strings.&lt;/p&gt;

&lt;h2&gt;A Refactor&lt;/h2&gt;

&lt;p&gt;Before we end this article I want to do some refactoring: I'd like to keep everything in one file for now so the source is easy to read and easy to follow, but the problem is that we now have a bunch of boilerplate code before the actual meat of the program.&lt;/p&gt;

&lt;p&gt;We first define all of our builtins, as well as setting up a default environment variable, before we actually show the logic of the program. Let's reverse those two. Here's &lt;code&gt;shirt&lt;/code&gt; after the refactor.&lt;/p&gt;

&lt;p&gt;The notable changes are that the program logic moved to the top of the file into a method called &lt;code&gt;main&lt;/code&gt;. This method gets invoked on the last line of the file.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;#!/usr/bin/env ruby&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;shellwords&amp;#39;&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;
  &lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="vg"&gt;$stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;PROMPT&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vg"&gt;$stdin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;
    &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Shellwords&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shellsplit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;BUILTINS&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="no"&gt;BUILTINS&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fork&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;BUILTINS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s1"&gt;&amp;#39;cd&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;HOME&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]|&lt;/span&gt; &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="s1"&gt;&amp;#39;exit&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="s1"&gt;&amp;#39;exec&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|*&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="s1"&gt;&amp;#39;set&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;=&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;PROMPT&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;-&amp;gt; &amp;#39;&lt;/span&gt;

&lt;span class="n"&gt;main&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;As always, the &lt;a href="http://github.com/jstorimer/shirt/tree/third"&gt;source is on Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the next article we'll finish up with some search path stuff, then I'll show some pretty peculiar behaviour which will lead to implementing pipes in Ruby! Don't miss it!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/1POuuDYNcgxuavYosKGIpitmZe4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1POuuDYNcgxuavYosKGIpitmZe4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/1POuuDYNcgxuavYosKGIpitmZe4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1POuuDYNcgxuavYosKGIpitmZe4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/7vfUfTKtnb0" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2012/03/10/a-unix-shell-in-ruby-search-path.html</feedburner:origLink></entry>
 
 <entry>
   <title>A Unix Shell in Ruby - Part 2: Builtins</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/Lxx6z95xJtI/a-unix-shell-in-ruby-builtins.html" />
   <updated>2012-02-21T00:00:00-05:00</updated>
   <id>http://jstorimer.com/2012/02/21/a-unix-shell-in-ruby-builtins</id>
   <content type="html">&lt;p&gt;Wecome to the second article in this series. &lt;a href="/2012/02/16/a-unix-shell-in-ruby.html"&gt;Last time&lt;/a&gt; we implemented a verrrry basic shell that could just run most basic commands. This time around we're going to look at how it's broken and how we can fix it.&lt;/p&gt;

&lt;p&gt;First up, we'll need a few builtins.&lt;/p&gt;

&lt;h2&gt;A Note on Launching&lt;/h2&gt;

&lt;p&gt;Last time I explained the semantics of &lt;code&gt;exec&lt;/code&gt;: a call to &lt;code&gt;exec&lt;/code&gt; will replace the current process with another. This time, when we launch &lt;code&gt;shirt&lt;/code&gt; we're going to do so with the exec(1) utility. So we'll launch our shell like this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; &lt;span class="nb"&gt;exec&lt;/span&gt; ./shirt
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;When we do this from &lt;code&gt;bash&lt;/code&gt;, our &lt;code&gt;bash&lt;/code&gt; process &lt;em&gt;becomes&lt;/em&gt; a &lt;code&gt;shirt&lt;/code&gt; process. This way we can ensure that we're not running as a descendant of a &lt;code&gt;bash&lt;/code&gt; shell and we can minimize the dependence on &lt;code&gt;bash&lt;/code&gt; and its features.&lt;/p&gt;

&lt;p&gt;Onward.&lt;/p&gt;

&lt;h2&gt;Even cd doesn't work!&lt;/h2&gt;

&lt;p&gt;First, we'll try the cd command:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; &lt;span class="nb"&gt;exec&lt;/span&gt; ./shirt
&lt;span class="gp"&gt;$&lt;/span&gt; &lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;span class="go"&gt;/Users/jessestorimer/projects/shirt&lt;/span&gt;
&lt;span class="gp"&gt;$&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /usr/local
&lt;span class="gp"&gt;$&lt;/span&gt; &lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;span class="go"&gt;/Users/jessestorimer/projects/shirt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;:(&lt;/p&gt;

&lt;p&gt;Even though &lt;code&gt;cd&lt;/code&gt; appears to have worked it didn't actually change our current directory. If we look back at the code from last lesson it becomes obvious why this is the case.&lt;/p&gt;

&lt;h2&gt;Backstory&lt;/h2&gt;

&lt;p&gt;When we tell &lt;code&gt;shirt&lt;/code&gt; to run a command it does it in two steps: fork + exec. The call to &lt;code&gt;fork&lt;/code&gt; creates a new child process. The call to &lt;code&gt;exec&lt;/code&gt; transforms that new process into a &lt;code&gt;cd&lt;/code&gt; process.&lt;/p&gt;

&lt;p&gt;Although the child process knows the process ID of its parent, it can have no direct effect on the parents' state. So then, we shouldn't be surprised that the parent process (our &lt;code&gt;shirt&lt;/code&gt; process) is unaffected when one of its children changes directories.&lt;/p&gt;

&lt;p&gt;Just to make this crystal clear: the &lt;code&gt;cd&lt;/code&gt; is taking effect on the &lt;em&gt;child&lt;/em&gt; process, but that change is not reflected in the parent process. So once the child has finished and exited it's as though the &lt;code&gt;cd&lt;/code&gt; never happened.&lt;/p&gt;

&lt;p&gt;We'll get around this by making &lt;code&gt;cd&lt;/code&gt; a 'builtin' command.&lt;/p&gt;

&lt;h2&gt;A Note About Builtins&lt;/h2&gt;

&lt;p&gt;Every shell has some built in commands. These are commands which are inherently different from typical utilies in that they change the state of the shell and run in the shell process itself.&lt;/p&gt;

&lt;p&gt;For instance, a utility like &lt;code&gt;cat&lt;/code&gt; simply prints text to the terminal. It &lt;em&gt;does not&lt;/em&gt; change the state of the shell itself. The same goes for common commands like &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;tail&lt;/code&gt;, and &lt;code&gt;curl&lt;/code&gt;. But there are certain commands that need to change the state of the shell, and &lt;code&gt;cd&lt;/code&gt; is one of them.&lt;/p&gt;

&lt;h2&gt;Implementing cd&lt;/h2&gt;

&lt;p&gt;OK, so we can't implement &lt;code&gt;cd&lt;/code&gt; in the same way that our other commands are handled. We'll have to add a special handling to our shell for builtin commands.&lt;/p&gt;

&lt;p&gt;Before that, let's do a slight refactor of our shell from last time to have a more consistent run loop that we can build upon:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;#!/usr/bin/env ruby&lt;/span&gt;

&lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="vg"&gt;$stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;-&amp;gt; &amp;#39;&lt;/span&gt;
  &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vg"&gt;$stdin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;

  &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fork&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;In this implementation we've reduced a bit of duplication when printing the prompt. We start by entering an endless loop, printing the prompt, getting a line of input using &lt;code&gt;gets&lt;/code&gt;, removing leading and trailing whitespace with &lt;code&gt;strip&lt;/code&gt;,  and then processing that input as before.&lt;/p&gt;

&lt;p&gt;Here's our first pass at implementing &lt;code&gt;cd&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;#!/usr/bin/env ruby&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;shellwords&amp;#39;&lt;/span&gt;

&lt;span class="no"&gt;BUILTINS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cd&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;

&lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="vg"&gt;$stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;-&amp;gt; &amp;#39;&lt;/span&gt;
  &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vg"&gt;$stdin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;
  &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Shellwords&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shellsplit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;BUILTINS&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="no"&gt;BUILTINS&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fork&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Perfect, now &lt;code&gt;cd&lt;/code&gt; works as expected. Here's the explanation.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;BUILTINS&lt;/code&gt; constant stores a hash denoting the builtin commands we support. The key specifies the builtin command and the value is a lambda which encapsulates the behaviour. For &lt;code&gt;cd&lt;/code&gt; we use Ruby to change the directory &lt;em&gt;without&lt;/em&gt; first creating a child process. In this way, the current directory of the shell process itself will be changed.&lt;/p&gt;

&lt;p&gt;After getting the input we split the input line into a command and its arguments. This is done with &lt;code&gt;Shellwords&lt;/code&gt;, which is part of the Ruby standard library. Why is it used, you ask? Shellwords will split the string the same way that &lt;code&gt;bash&lt;/code&gt; does. The documentation for &lt;a href="http://www.ruby-doc.org/stdlib-1.9.3/libdoc/shellwords/rdoc/Shellwords.html#method-c-shellsplit"&gt;Shellwords.shellsplit&lt;/a&gt; has a great example of this.&lt;/p&gt;

&lt;p&gt;The last addition is a conditional. If the command is one of the builtin functions then we should use that instead of the fork+exec method.&lt;/p&gt;

&lt;h2&gt;Just Try to Leave, I Dare You!&lt;/h2&gt;

&lt;p&gt;Let's implement another builtin, &lt;code&gt;exit&lt;/code&gt;. &lt;code&gt;exit&lt;/code&gt; doesn't exist as an executable anywhere on your system, it's always implemented as a builtin. Here's the relevant code for our implementation of &lt;code&gt;exit&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="no"&gt;BUILTINS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s1"&gt;&amp;#39;cd&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="s1"&gt;&amp;#39;exit&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now we can do a session like:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; ls
&lt;span class="go"&gt;shirt&lt;/span&gt;
&lt;span class="gp"&gt;$&lt;/span&gt; &lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;span class="go"&gt;/Users/jessestorimer/projects/shirt&lt;/span&gt;
&lt;span class="gp"&gt;$&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /usr/local
&lt;span class="gp"&gt;$&lt;/span&gt; &lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;span class="go"&gt;/usr/local&lt;/span&gt;
&lt;span class="gp"&gt;$&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Most of the time you'll probably exit without passing an exit code, but &lt;a href="/2012/01/19/exit-exit-abort-raise.html"&gt;it can be useful sometimes&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Change me!&lt;/h2&gt;

&lt;p&gt;We'll implement one more builtin, &lt;code&gt;exec&lt;/code&gt;. This will behave the same way that &lt;code&gt;bash&lt;/code&gt;' &lt;code&gt;exec&lt;/code&gt; does, it will transform the shell process into another process. Useful for scripting or when you want the shell to become another program leaving no trace. Here's the implemenation:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="no"&gt;BUILTINS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s1"&gt;&amp;#39;cd&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="s1"&gt;&amp;#39;exit&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="s1"&gt;&amp;#39;exec&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|*&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;You get the idea.&lt;/p&gt;

&lt;h2&gt;Before You Go&lt;/h2&gt;

&lt;p&gt;We're implementing builtins by splitting a string and matching it to an array of predefined commands. In reality a shell like &lt;code&gt;bash&lt;/code&gt; implements a real language and would do this work with a &lt;a href="http://en.wikipedia.org/wiki/Parsing"&gt;real parser&lt;/a&gt;. We're taking shortcuts for the purposes of moving quickly and learning.&lt;/p&gt;

&lt;h2&gt;OK, now you can leave&lt;/h2&gt;

&lt;p&gt;That's it for our first look at builtins. This shell is getting more and more functional :) You can get the latest version of &lt;code&gt;shirt&lt;/code&gt; &lt;a href="http://github.com/jstorimer/shirt/tree/second"&gt;on Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to see what other builtin commands are part of a shell like &lt;code&gt;bash&lt;/code&gt; use &lt;code&gt;man builtin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next time we'll look at handling environment variables, specifically the &lt;code&gt;PATH&lt;/code&gt;. I won't be able to post again next week, but look for the next article two weeks from now.&lt;/p&gt;

&lt;hr /&gt;


&lt;p&gt;For a more thorough introduction to Unix programming basics check out &lt;a href="http://workingwithunixprocesses.com"&gt;Working With Unix Processes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/65XGwtxhtc7aXrp5WfVMBRFhUPg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/65XGwtxhtc7aXrp5WfVMBRFhUPg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/65XGwtxhtc7aXrp5WfVMBRFhUPg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/65XGwtxhtc7aXrp5WfVMBRFhUPg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/Lxx6z95xJtI" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2012/02/21/a-unix-shell-in-ruby-builtins.html</feedburner:origLink></entry>
 
 <entry>
   <title>A Unix Shell in Ruby</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/CrrB5TBrprc/a-unix-shell-in-ruby.html" />
   <updated>2012-02-16T00:00:00-05:00</updated>
   <id>http://jstorimer.com/2012/02/16/a-unix-shell-in-ruby</id>
   <content type="html">&lt;p&gt;This is the first article in a series where I'll implement a Unix shell in pure Ruby code.&lt;/p&gt;

&lt;h2&gt;Why a shell?&lt;/h2&gt;

&lt;p&gt;A shell is the quintessential example of a Unix program. It hits all of the interesting points that a Unix system is capable of.&lt;/p&gt;

&lt;p&gt;It has to read input from STDIN, spawn processes requested from users, send signals to processes based on input, connect processes together with pipes, and provide a scripting environment for programmers to get work done.&lt;/p&gt;

&lt;h2&gt;What's a shell?&lt;/h2&gt;

&lt;p&gt;It's possible that you're using a shell all the time without knowing where the shell begins and where it ends. Or the fact that there are many different shells available to you. The default shell on most Unix systems is called &lt;code&gt;bash&lt;/code&gt;. &lt;code&gt;bash&lt;/code&gt; was written in the eighties as a replacement for its predecessor: the Bourne shell. Hence, &lt;code&gt;bash&lt;/code&gt; stands for 'Bourne Again SHell'.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;bash&lt;/code&gt; is a program like any other. It gets treated the same way as would &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;cat&lt;/code&gt;, or &lt;code&gt;tail&lt;/code&gt;. So what makes a shell different? When you launch a shell it enters an endless loop of reading input and processing it. It reads the commands you type and launches programs based on that.&lt;/p&gt;

&lt;p&gt;You can see this firsthand if you open a command line and try typing &lt;code&gt;bash&lt;/code&gt;. Chances are you are already in an instance of a &lt;code&gt;bash&lt;/code&gt; shell, but since it's a program like any other you can launch it again. Now you're in a shell in a shell. Inception!? Go ahead and exit the 'subshell' to get back to your original &lt;code&gt;bash&lt;/code&gt; session.&lt;/p&gt;

&lt;h2&gt;Prior Art&lt;/h2&gt;

&lt;p&gt;There are many shells available for Unix systems. Besides &lt;code&gt;bash&lt;/code&gt;, the most popular alternative is &lt;code&gt;zsh&lt;/code&gt;. There are lots of good reasons to give &lt;code&gt;zsh&lt;/code&gt; a try, enumerated &lt;a href="https://gist.github.com/1507733"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;The Plan&lt;/h2&gt;

&lt;p&gt;We'll start out building a shell that resembles &lt;code&gt;bash&lt;/code&gt; for familiarity. Along the way we might choose to make design decisions that deviate from what &lt;code&gt;bash&lt;/code&gt; does, but that's the fun of writing your own! You can do it your way.&lt;/p&gt;

&lt;h2&gt;shirt&lt;/h2&gt;

&lt;p&gt;Our shell will be called &lt;code&gt;shirt&lt;/code&gt;. This stands for 'SHell in Ruby? Totally!'. Here's our first implementation:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;#!/usr/bin/env ruby&lt;/span&gt;

&lt;span class="vg"&gt;$stdin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each_line&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fork&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Stick that in a file, make it executable with &lt;code&gt;chmod +x shirt&lt;/code&gt; and then run it using &lt;code&gt;./shirt&lt;/code&gt;. You'll be presented with a blank line, but try typing in a shell command like &lt;code&gt;ls&lt;/code&gt; or &lt;code&gt;ruby -v&lt;/code&gt;. This shell is still missing key features but the absolute basics are working.&lt;/p&gt;

&lt;p&gt;So what's going on here?&lt;/p&gt;

&lt;h2&gt;Taking the Hard Way&lt;/h2&gt;

&lt;p&gt;The truth is that we could have implemented this in a much simpler way. We could replace the whole &lt;code&gt;fork&lt;/code&gt;, &lt;code&gt;exec&lt;/code&gt;, and &lt;code&gt;wait&lt;/code&gt; bit with one call to &lt;a href="https://github.com/rubinius/rubinius/blob/master/kernel/common/process.rb#L710-731"&gt;&lt;code&gt;system()&lt;/code&gt;&lt;/a&gt;. We're goint to avoid this method for two reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;We're here to learn&lt;/strong&gt;, so we're going to use the lowest level building blocks available to us to get an idea of what's really possible here. This implementation is closer to &lt;code&gt;bash&lt;/code&gt; or other system shells.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;This is more flexible&lt;/strong&gt;. We won't get to it much in this article but doing it this way will actually provide us with more flexibility later when we want to implement things like pipes.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;I'll explain things one piece at a time.&lt;/p&gt;

&lt;h2&gt;Getting Input&lt;/h2&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="vg"&gt;$stdin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each_line&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This line will put the program in an endless loop. It will read from standard input until it gets a newline and then pass that line of text into the block.&lt;/p&gt;

&lt;p&gt;If this is your first introduction to &lt;code&gt;$stdin&lt;/code&gt; it's fairly simple. Every process has a &lt;code&gt;$stdin&lt;/code&gt; file hooked up by default. This is where processes look to read input. This input might be coming from a keyboard or from a pipe, either can be read just the same.  In this case it causes the program to block until it gets an entire line of input from the user.&lt;/p&gt;

&lt;h2&gt;Executing a Command&lt;/h2&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;  &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fork&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;There are two important concepts here: &lt;code&gt;fork&lt;/code&gt; and &lt;code&gt;exec&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Calling &lt;code&gt;fork&lt;/code&gt; creates an new process that's an exact copy of the current process. It gets a copy of everything in memory and all open file descriptors. Certain housekeeping data is copied over like process group id, session group id, etc., and the new process gets its own process id, but for all intents and purposes it's an &lt;em&gt;exact copy&lt;/em&gt;.
 So &lt;code&gt;fork&lt;/code&gt; gets us a new process where we will execute the command that came in from &lt;code&gt;$stdin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Notice that we pass a block to &lt;code&gt;fork&lt;/code&gt; and store its return value. The block is passed to the newly created process. It runs that block and then exits. In the parent process the process id (pid) of the newly created process is returned from &lt;code&gt;fork&lt;/code&gt;. More on that pid in the next section.&lt;/p&gt;

&lt;p&gt;Calling &lt;code&gt;exec&lt;/code&gt; transforms the current process into another one specified by the file passed as input. An example should clear this up, calling &lt;code&gt;exec('ls')&lt;/code&gt; will transform the current Ruby process into an &lt;code&gt;ls&lt;/code&gt; process. The transformation happens immediately so any code that you have after the &lt;code&gt;exec&lt;/code&gt; will never be reached. &lt;code&gt;exec&lt;/code&gt; is a no-looking-back kind of thing.&lt;/p&gt;

&lt;p&gt;Try out &lt;code&gt;exec('ls')&lt;/code&gt; in &lt;code&gt;irb&lt;/code&gt; if you never have before. Notice that you get the output of &lt;code&gt;ls&lt;/code&gt; and then you're back to the terminal. The &lt;code&gt;irb&lt;/code&gt; process is gone, replaced entirely by &lt;code&gt;ls&lt;/code&gt;. So when &lt;code&gt;ls&lt;/code&gt; exited you're back to the shell.&lt;/p&gt;

&lt;p&gt;The pattern we're using here, &lt;code&gt;fork&lt;/code&gt; and &lt;code&gt;exec&lt;/code&gt; is a common way to spawn commands. It's the method used by Ruby constructs like &lt;code&gt;Kernel#system&lt;/code&gt; and &lt;code&gt;Kernel#`&lt;/code&gt;. If we were to skip the &lt;code&gt;fork&lt;/code&gt; and just call &lt;code&gt;exec&lt;/code&gt; then the &lt;code&gt;shirt&lt;/code&gt; process itself would be transformed and it would no longer be able to respond to input. Calling &lt;code&gt;fork&lt;/code&gt; creates a new child process to be transformed into the necessary command.&lt;/p&gt;

&lt;h2&gt;Waiting Patiently&lt;/h2&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;  &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The last piece of the puzzle is &lt;code&gt;Process.wait&lt;/code&gt;. Calling &lt;code&gt;fork&lt;/code&gt; will return immediately. It creates a child process then returns context to the parent process. If we didn't wait for the child process to finish its work then we'd end up spawning multiple processes in parallel. In that case their input and output would be interleaved all over each other and it would be unclear which output is coming from which command. This keeps things usable and gives us a synchronous shell.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Process.wait&lt;/code&gt; is a blocking call that won't return until the process represented by the passed-in pid has exited. Using this ensures that our shell will only run one command at a time.&lt;/p&gt;

&lt;h2&gt;Some Chrome&lt;/h2&gt;

&lt;p&gt;Before we end this first article let's give our shell a bit of chrome so we can recognize the prompt.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;#!/usr/bin/env ruby&lt;/span&gt;

&lt;span class="vg"&gt;$stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;-&amp;gt; &amp;#39;&lt;/span&gt;

&lt;span class="vg"&gt;$stdin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each_line&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fork&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;
  &lt;span class="vg"&gt;$stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;-&amp;gt; &amp;#39;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now when you run the shell you get a simple prompt before each command so you can tell which lines are output and which lines are input.&lt;/p&gt;

&lt;h2&gt;Just the Start&lt;/h2&gt;

&lt;p&gt;There's still lots of ways to break the shell. Did you try using &lt;code&gt;cd&lt;/code&gt;? How about going back in history?&lt;/p&gt;

&lt;p&gt;There's still lots of missing features, and since the shell is actually running inside another instance of a shell it's getting some features for free.&lt;/p&gt;

&lt;p&gt;Next time I'll look at launching &lt;code&gt;shirt&lt;/code&gt; outside the context of another shell and implemeting some built-in commands.&lt;/p&gt;

&lt;hr /&gt;


&lt;p&gt;&lt;a href="http://github.com/jstorimer/shirt/tree/first"&gt;Grab the source&lt;/a&gt; on Github.&lt;/p&gt;

&lt;p&gt;For a more thorough, Ruby-centric introduction to Unix programming basics check out &lt;a href="http://workingwithunixprocesses.com/?shirt"&gt;Working With Unix Processes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/iPXJw6NWYUxoJpGwBixMbVR5vwA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/iPXJw6NWYUxoJpGwBixMbVR5vwA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/iPXJw6NWYUxoJpGwBixMbVR5vwA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/iPXJw6NWYUxoJpGwBixMbVR5vwA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/CrrB5TBrprc" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2012/02/16/a-unix-shell-in-ruby.html</feedburner:origLink></entry>
 
 <entry>
   <title>11 Resources for Learning Unix Programming</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/8H-oq6jvyMM/learning-unix-programming.html" />
   <updated>2012-02-10T00:00:00-05:00</updated>
   <id>http://jstorimer.com/2012/02/10/learning-unix-programming</id>
   <content type="html">&lt;p&gt;Recently I got an email from a reader of &lt;a href="http://workingwithunixprocesses.com"&gt;WWUP&lt;/a&gt; asking how I learned about all this stuff. Here's what I told him.&lt;/p&gt;

&lt;hr /&gt;


&lt;p&gt;I personally get a lot from reading source code and from piecing together different resources. I have very little experience with C programming, and learned everything I know about Unix programming w/o having to write C code. Besides the resources below I learn a lot from experimenting with little bits of code and writing my own software.&lt;/p&gt;

&lt;p&gt;Here's a brain dump of some stuff that helped me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://unicorn.bogomips.org/"&gt;http://unicorn.bogomips.org/&lt;/a&gt;. Lots of good info in the included files like DESIGN, PHILOSOPHY, etc.&lt;/li&gt;
&lt;li&gt;Any other piece of software by Eric Wong (author of Unicorn) &lt;a href="http://rubygems.org/profiles/normalperson"&gt;http://rubygems.org/profiles/normalperson&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.destroyallsoftware.com/"&gt;https://www.destroyallsoftware.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://tomayko.com/writings/unicorn-is-unix"&gt;http://tomayko.com/writings/unicorn-is-unix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/TwP/servolux"&gt;https://github.com/TwP/servolux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;I'm also a frequent reader of manpages&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/defunkt/resque"&gt;https://github.com/defunkt/resque&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pic.plover.com/UnixReader/"&gt;http://pic.plover.com/UnixReader/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Anything by Russ Cox (&lt;a href="http://swtch.com/~rsc/"&gt;http://swtch.com/~rsc/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://cat-v.org/"&gt;http://cat-v.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The Linux Programming Interface &lt;a href="http://nostarch.com/tlpi"&gt;http://nostarch.com/tlpi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The Art of Unix Programming &lt;a href="http://www.faqs.org/docs/artu/"&gt;http://www.faqs.org/docs/artu/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;USP Ruby mailing list &lt;a href="http://bogomips.org/usp.ruby/README"&gt;http://bogomips.org/usp.ruby/README&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The truth is that there are a lot of really great free resources out there, but they're not cohesive and most are written for C programmers.&lt;/p&gt;

&lt;p&gt;I tend to steer clear of the thick reference books and go instead for books that give me a look into how smart people think about programming. There's lots of good thought in the history of Unix and its programmers.&lt;/p&gt;

&lt;hr /&gt;


&lt;p&gt;Want a cohesive guide to Unix programming written specifically for non-C programmers? Have a look at &lt;a href="http://workingwithunixprocesses.com"&gt;Working With Unix Processes&lt;/a&gt;, a brief book for precisely that.&lt;/p&gt;

&lt;p&gt;I'm sure there are other resources available for learning this stuff. What am I missing?&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/rFpKnt1MngGxakIg-KsoFcxf6WY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rFpKnt1MngGxakIg-KsoFcxf6WY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/rFpKnt1MngGxakIg-KsoFcxf6WY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rFpKnt1MngGxakIg-KsoFcxf6WY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/8H-oq6jvyMM" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2012/02/10/learning-unix-programming.html</feedburner:origLink></entry>
 
 <entry>
   <title>Pairing Is Not Codereview</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/hbyyvD3vaWw/pairing-is-not-codereview.html" />
   <updated>2012-01-30T00:00:00-05:00</updated>
   <id>http://jstorimer.com/2012/01/30/pairing-is-not-codereview</id>
   <content type="html">&lt;p&gt;&lt;img src="/images/substitute.png" alt="Is it a substitute?" /&gt;&lt;/p&gt;

&lt;p&gt;I &lt;a href="http://jstorimer.com/ruby/2010/09/30/you-should-be-doing-formal-code-review.html"&gt;previously posted&lt;/a&gt; about the importance of formal code review and its benefits. Though I shared why the code review process is important I didn't make it clear how that fits into a software development process alongside TDD, pairing, etc.&lt;/p&gt;

&lt;p&gt;I replied thusly to @brynary's tweet:&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/breakdown.png" alt="My breakdown" /&gt;&lt;/p&gt;

&lt;p&gt;I want to expand on that.&lt;/p&gt;

&lt;h2&gt;Pairing&lt;/h2&gt;

&lt;p&gt;Others have &lt;a href="http://blog.jayfields.com/2008/02/pair-programming-all-time.html"&gt;written&lt;/a&gt; &lt;a href="http://blog.obiefernandez.com/content/2008/08/the-hashrocket-way-pair-programming.html"&gt;about&lt;/a&gt; &lt;a href="http://www.markhneedham.com/blog/2009/06/08/pair-programming-so-you-dont-want-to-do-it/"&gt;pair programming&lt;/a&gt; and I don't really have anything to add. I think pairing is a fine practice &lt;em&gt;in certain situations&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In my experience it is most useful at the beginning of the software development process. When you're looking to the horizon for a solution, unsure of which direction to take. Once a course has been chosen then a single developer can push the code in that direction.&lt;/p&gt;

&lt;h2&gt;Code Review&lt;/h2&gt;

&lt;p&gt;Code review doesn't even relate orthogonally to pairing. Code review is the last step in the software development process.&lt;/p&gt;

&lt;p&gt;Code review is one developer saying to another:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;"Hey, I've found a problem, wrote some tests, implemented a solution, tested the solution locally and in the staging environment and now I think it's ready to go. Do you see any reason why it shouldn't be deployed?"&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;If there is anything that indicates the change shouldn't go online then this is the time to bring it up. This is not the time for sweeping design changes.&lt;/p&gt;

&lt;h2&gt;What Code Review is For&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The biggest benefit of code review is fresh eyes&lt;/strong&gt; on the code. Ideally, eyes that weren't involved in the design and implementation of the code. Fresh eyes are the best bet to find edge cases that the original author may have missed.&lt;/p&gt;

&lt;p&gt;You should have at least one reviewer on each review who is familiar with the (official or unofficial) style guide of the project. This is the stage where your style guide is enforced. Did the author forget to use an idiom common to the project? Was some code re-implemented that could have been included from a module elsewhere?&lt;/p&gt;

&lt;h2&gt;Making Suggestions&lt;/h2&gt;

&lt;p&gt;When reviewing code it can be tempting to point out all the ways that the author is 'wrong'. In other words, all the things that you would have done differently. Remove ego from the equation as much as possible, your way isn't necessarily 'right'. After that &lt;strong&gt;err on the side of being verbose, keeping in mind that not every comment needs to be addressed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not all code review comments need to be answered with modifications to the code. Not every suggestion needs to be implemented. Anything that prevents the code from working as advertised needs to be addressed. Everything else is at the discretion of the author.&lt;/p&gt;

&lt;p&gt;The point of this kind of comment is basically to say 'gotcha!'. If the author decided to do a database query from a view helper then you should remind them that we put database queries in the controller and reserve the view helpers for extracted view logic. This doesn't mean that the entire changeset should be delayed to ensure that this convention be followed. &lt;strong&gt;The most important thing is that code gets shipped&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The author can always follow up later to fix the regression. The subtle point of this kind of comment is to make the author think twice the next time they break convention. It's to remind them that they have to be accountable to their peers. Their peers are watching, and caring!&lt;/p&gt;

&lt;h2&gt;Waiting On Others&lt;/h2&gt;

&lt;p&gt;It seems at first glance like code review will slow down a development cycle. We have one developer responsible for implementing a feature from start to finish. Before deploying the code he hands off responsibility to a reviewer to '+1' the whole thing. What if the reviewer is busy, takes days to respond? Talk about buzzkill.&lt;/p&gt;

&lt;p&gt;If code review is going to be part of your development process then developers need to understand its gravity. Developers should be aware that when a code review is assigned to them &lt;strong&gt;they are the last thing holding up a changeset from being deployed&lt;/strong&gt;. There's no excuse for letting this go on longer than it has to.&lt;/p&gt;

&lt;p&gt;Unless something prevents it: &lt;strong&gt;code reviews should be performed the same day they're received&lt;/strong&gt;. If you can't do it then forward it on to someone else. The point isn't to enforce rigid structure into your process where none is needed. The point is to &lt;strong&gt;respect your co-workers&lt;/strong&gt;. The way to do that is to help them get their stuff deployed without delay.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;As &lt;a href="http://jstorimer.com/ruby/2010/09/30/you-should-be-doing-formal-code-review.html"&gt;I mentioned&lt;/a&gt;, code review has had a huge impact on my development as a programmer. Having my code critiqued by other developers always sheds new light and I've learned a ton from the suggestions of others.&lt;/p&gt;

&lt;p&gt;My biggest takeaway from code review was a different perspective on code. Code review helped me understand that I'm not just implementing features for end users, I'm implementing APIs for my peers. They may very well be the ones who have to understand and maintain my code in the future.&lt;/p&gt;

&lt;p&gt;No matter how important it seems to ship something quick to make an end user happy the guy performing maintenance must be considered. Code review ensures that that guy gets a voice before your code ever sees the light of day.&lt;/p&gt;

&lt;hr /&gt;


&lt;p&gt;I'm &lt;a href="http://jstorimer.com"&gt;Jesse Storimer&lt;/a&gt;. &lt;a href="http://twitter.com/jstorimer"&gt;Follow me&lt;/a&gt; on Twitter.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/rNICVXGIDE-AMxPpQyTmJrTRLRE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rNICVXGIDE-AMxPpQyTmJrTRLRE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/rNICVXGIDE-AMxPpQyTmJrTRLRE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rNICVXGIDE-AMxPpQyTmJrTRLRE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/hbyyvD3vaWw" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2012/01/30/pairing-is-not-codereview.html</feedburner:origLink></entry>
 
 <entry>
   <title>The Better To RTFM</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/kL7Nn491xUo/to-better-rtfm.html" />
   <updated>2012-01-26T00:00:00-05:00</updated>
   <id>http://jstorimer.com/2012/01/26/to-better-rtfm</id>
   <content type="html">&lt;p&gt;Unix manpages are great if you already know what you're looking for. But what if you don't?&lt;/p&gt;

&lt;p&gt;If you've read &lt;a href="http://ozmm.org/posts/man_what.html"&gt;prior art on manpages&lt;/a&gt; then you know that the manpages are separated into sections: section 1 is for general commands, section 2 is for system calls, etc. If you know exactly what command or system call you're looking for then it's easy to look it up: &lt;code&gt;man grep&lt;/code&gt; finds the grep documentation. Here's some tips to dig a little deeper.&lt;/p&gt;

&lt;h2&gt;1. Each manpage section has its own intro page.&lt;/h2&gt;

&lt;p&gt;The intro pages provide an overview about each section. Try &lt;code&gt;man intro&lt;/code&gt; for an example. For something of more interest try &lt;code&gt;man 2 intro&lt;/code&gt;. Believe it or not that's probably one of the most concise and to the point introductions to systems programming that I've seen. Unless you knew you were looking for that it's kind of hard to find.&lt;/p&gt;

&lt;p&gt;Contrary to &lt;code&gt;man man&lt;/code&gt;, which provides information about how to use the &lt;code&gt;man&lt;/code&gt; command, intro pages provide general info about the documentation itself. Very useful.&lt;/p&gt;

&lt;h2&gt;2. You can search the manpages.&lt;/h2&gt;

&lt;p&gt;There are two commands for this purpose: whatis(1) and apropos(1). The &lt;code&gt;whatis&lt;/code&gt; command searches for exact matches in the manpage database. The &lt;code&gt;apropos&lt;/code&gt; command searches for partial matches. Want to know which variants of &lt;code&gt;grep&lt;/code&gt; you have documentation for?&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; whatis grep
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This will return a few manpages with the whole word 'grep' in the name.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; apropos grep
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This will return more manpages than before, this time including some that have grep as a substring. This includes stuff like zgrep(1), pgrep(1), etc.&lt;/p&gt;

&lt;p&gt;The good news is that &lt;strong&gt;you don't need to remember any extra commands to search the manpages: just use &lt;code&gt;man -k search-string&lt;/code&gt;&lt;/strong&gt;. &lt;code&gt;man -k&lt;/code&gt; is equivalent to apropos(1).&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; man -k grep
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;3. Some interesting manpages you probably didn't know about.&lt;/h2&gt;

&lt;p&gt;intro(2). signal(7). environ(7). style(9).&lt;/p&gt;

&lt;p&gt;Go forth and RTFM.&lt;/p&gt;

&lt;hr /&gt;


&lt;p&gt;I'm &lt;a href="http://jstorimer.com"&gt;Jesse Storimer&lt;/a&gt;. &lt;a href="http://twitter.com/jstorimer"&gt;Follow me&lt;/a&gt; on Twitter.&lt;/p&gt;

&lt;p&gt;For a more comprehensive introduction to systems programming try my book: &lt;a href="http://workingwithunixprocesses.com/?rtfm"&gt;Working With Unix Processes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/aH5Fw98SpViI6tanS2_p0wbkl70/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aH5Fw98SpViI6tanS2_p0wbkl70/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/aH5Fw98SpViI6tanS2_p0wbkl70/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aH5Fw98SpViI6tanS2_p0wbkl70/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/kL7Nn491xUo" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2012/01/26/to-better-rtfm.html</feedburner:origLink></entry>
 
 <entry>
   <title>Exit, Exit! Abort, Raise…Get Me Outta Here!</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/pzyYmCJ8BqQ/exit-exit-abort-raise.html" />
   <updated>2012-01-19T00:00:00-05:00</updated>
   <id>http://jstorimer.com/2012/01/19/exit-exit-abort-raise</id>
   <content type="html">&lt;p&gt;I &lt;a href="http://rubysource.com/exit-exit-abort-raise-get-me-outta-here/"&gt;guest-posted over on rubysource.com&lt;/a&gt; about exit codes, why they're important, and how to use them from your Ruby programs. It's worth a read.&lt;/p&gt;

&lt;hr /&gt;


&lt;p&gt;I'm &lt;a href="http://jstorimer.com"&gt;Jesse Storimer&lt;/a&gt;. &lt;a href="http://twitter.com/jstorimer"&gt;Follow me&lt;/a&gt; on Twitter.&lt;/p&gt;

&lt;p&gt;Get my eBook, &lt;a href="http://workingwithunixprocesses.com?ex"&gt;Working With Unix Processes&lt;/a&gt;, and learn even more about Unix programming, all from the comfort of Ruby.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/qqIi2rbNqbVr5Qi1Ujq41nGVOxs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qqIi2rbNqbVr5Qi1Ujq41nGVOxs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/qqIi2rbNqbVr5Qi1Ujq41nGVOxs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qqIi2rbNqbVr5Qi1Ujq41nGVOxs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/pzyYmCJ8BqQ" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2012/01/19/exit-exit-abort-raise.html</feedburner:origLink></entry>
 
 <entry>
   <title>The Hungry Programmer</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/wL_0Q20q7w8/the-hungry-programmer.html" />
   <updated>2012-01-09T00:00:00-05:00</updated>
   <id>http://jstorimer.com/2012/01/09/the-hungry-programmer</id>
   <content type="html">&lt;p&gt;Programming is a lot like eating.&lt;/p&gt;

&lt;p&gt;Tonight I was hungry. I wasn't at home. I couldn't go to the kitchen for a snack. I looked around and saw only McDonald's across the street.&lt;/p&gt;

&lt;p&gt;Then I was struck with the same dilemma that I face whenever I leave the comfort of my own home for any decent spread of time: Do I eat crappy food now and satisfy that hunger? Or do I stay hungry for a little longer and eat a healthy meal back at home?&lt;/p&gt;

&lt;p&gt;As I pondered this dilemma I couldn't help but notice how much it relates to code quality. But more about food first.&lt;/p&gt;

&lt;p&gt;I can only speak for myself, but I do not consider a McDonald's restaurant capable of providing me with a healthy meal. As an aspiring raw fooder, or even as a person who cares what I eat, McDonald's food is far from what I would consider a healthy meal. But, like a lot of you I'm sure, I grew up eating McDonald's without questioning its health benefits. I was hungry and McDonald's was food.&lt;/p&gt;

&lt;p&gt;Now that I understand the short and long-term effects of McDonald's on my body I avoid it all costs. The same goes for pre-processed foods in general. This has been a journey for me. Deciding to change your eating habits is more than a one-day process and &lt;strong&gt;healthy eating is a continuum&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This'll all relate to programming very soon :)&lt;/p&gt;

&lt;h2&gt;Healthy Eating is a Continuum?&lt;/h2&gt;

&lt;p&gt;Eating at McDonald's is not a healthy meal. However eating a Big Mac with a side salad is marginally healthier than eating a Big Mac with fries. Eating a tuna wrap from Starbucks is marginally healthier than any meal containing a Big Mac. Eating a bowl of soup from your local boutique coffee shop is marginally healthier than a tuna wrap from Starbucks. Eating a homemade meal with fresh ingredients is healthier than any of these meals.&lt;/p&gt;

&lt;p&gt;There are two takeaways from our look at food:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Everything is relative&lt;/strong&gt;. You can almost always do better and almost always do worse. Eating a Big Mac does not equal death, but refraining from food for an entire day in anticipation of a homemade meal is obviously not healthy either.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Every meal is anew&lt;/strong&gt;. It's very easy to get into traps like "Well, I had a Big Mac yesterday so I might as well have another one today". That kind of thinking is not logical or helpful. Every decision to eat is a new decision. Even if you had a Big Mac for breakfast today, having a home-made meal for lunch is a step up on that continuum.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;Code as Food&lt;/h2&gt;

&lt;p&gt;Much like food, code quality is a continuum.&lt;/p&gt;

&lt;p&gt;At a very basic level we can say that a library that ships with no tests and no documentation is of lower quality than the same library with tests and documentation.&lt;/p&gt;

&lt;p&gt;But between the obvious is a lot of murky water. Everyone has their own ideas about what is 'healthy' code. Some people are very aware of their programming habits and work on improving them. Some people are doing the same crap they've been doing for years without a thought to whether or not it's 'healthy'.&lt;/p&gt;

&lt;h2&gt;Making Healthy Choices&lt;/h2&gt;

&lt;p&gt;Treat code like food.&lt;/p&gt;

&lt;p&gt;Just like you have to eat, you have to ship code. But how you do that has both short- and long-term effects.&lt;/p&gt;

&lt;p&gt;If you take the McDonald's approach and ship shit then you satisfy that need in the short-term. But you'll feel the effects in the long-term. Your code will be harder to maintain and need more attention later. It won't have a long and healthy life.&lt;/p&gt;

&lt;p&gt;If you take the home-made meal approach then you leave that need unsatisfied for a little while. The short-term effect is that you stay hungry, but it's for a good reason: the long-term effects will be positive. Your code will be easier to maintain, bugs will be easier to fix, and it will be easier to introduce change. Your code will have a long and healthy life.&lt;/p&gt;

&lt;h2&gt;Decisions&lt;/h2&gt;

&lt;p&gt;Writing healthy code requires the same thing that healthy eating does: recognition and commitment. To go from eating poorly to eating well requires a recognition that there's something that needs improvement. To act on that recognition requires commitment to your decision.&lt;/p&gt;

&lt;p&gt;To improve your programming habits requires the same: recognition that something needs to be improved and the commitment to do so.&lt;/p&gt;

&lt;p&gt;As always, your choices must be pragmatic. You have to eat something, and your code has to ship sometime. In lieu of finding a healthy meal McDonald's will have to do. I don't know the constraints of your software project, and sometimes you'll have to ship shit. Just remember that &lt;strong&gt;healthy programming is a continuum&lt;/strong&gt;. Get a side salad with that Big Mac instead of fries.&lt;/p&gt;

&lt;p&gt;There is no 'healthiest' meal. You can spend all day preparing the healthiest meal you can imagine but it does no good unless it's in your stomach. &lt;strong&gt;Code quality is important, but it's nothing unless you ship it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The surest path to healthier code is incremental improvements. Program a little bit healthier every day rather than discarding the old habits in one go and expecting them to be replaced by new, healthy ones.&lt;/p&gt;

&lt;hr /&gt;


&lt;p&gt;I'm &lt;a href="http://jstorimer.com"&gt;Jesse Storimer&lt;/a&gt;. &lt;a href="http://twitter.com/jstorimer"&gt;Follow me&lt;/a&gt; on Twitter.&lt;/p&gt;

&lt;p&gt;Get my eBook, &lt;a href="http://workingwithunixprocesses.com?hp"&gt;Working With Unix Processes&lt;/a&gt;, and become a Unix guru without any C programming.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Cd1ADE4pz_cJMaNnV1Ef0iTE2fs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Cd1ADE4pz_cJMaNnV1Ef0iTE2fs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Cd1ADE4pz_cJMaNnV1Ef0iTE2fs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Cd1ADE4pz_cJMaNnV1Ef0iTE2fs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/wL_0Q20q7w8" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2012/01/09/the-hungry-programmer.html</feedburner:origLink></entry>
 
 <entry>
   <title>When to use STDERR instead of STDOUT</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/5fwc2aT2Xjo/the-difference-between-stdout-and-stderr.html" />
   <updated>2011-12-29T00:00:00-05:00</updated>
   <id>http://jstorimer.com/2011/12/29/the-difference-between-stdout-and-stderr</id>
   <content type="html">&lt;p&gt;&lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stderr&lt;/code&gt; both quack the same, but are used for very different purposes.&lt;/p&gt;

&lt;p&gt;Every process is initialized with three open file descriptors, &lt;code&gt;stdin&lt;/code&gt;, &lt;code&gt;stdout&lt;/code&gt;, and &lt;code&gt;stderr&lt;/code&gt;. &lt;code&gt;stdin&lt;/code&gt; is an abstraction for accepting input (from the keyboard or from pipes) and &lt;code&gt;stdout&lt;/code&gt; is an abstraction for giving output (to a file, to a pipe, to a console).&lt;/p&gt;

&lt;p&gt;That's a very simplified explanation but true nonetheless. Those three file descriptors are collectively called 'The Standard Streams'.&lt;/p&gt;

&lt;h2&gt;Where does &lt;code&gt;stderr&lt;/code&gt; come from?&lt;/h2&gt;

&lt;p&gt;It's fairly straightforward to understand why &lt;code&gt;stdin&lt;/code&gt; and &lt;code&gt;stdout&lt;/code&gt; exist, however &lt;code&gt;stderr&lt;/code&gt; seems like the odd one out. Why do we need another stream for errors?&lt;/p&gt;

&lt;p&gt;This is a quote from Doug McIllroy, inventor of Unix pipes, explaining how &lt;code&gt;stderr&lt;/code&gt; came to be. 'v6' is referring to a version of specific version of the original Unix operating system that was released in 1975.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;All programs placed diagnostics on the standard output. This had always caused trouble when the
output was redirected into a ﬁle, but became intolerable when the output was sent to an unsuspecting process. Nevertheless, unwilling to violate the simplicity of the standard-input-standard-output model, people
tolerated this state of affairs through v6. Shortly thereafter Dennis Ritchie cut the Gordian knot by introducing the standard error ﬁle. That was not quite enough. With pipelines diagnostics could come from any
of several programs running simultaneously. Diagnostics needed to identify themselves.&lt;small&gt;Doug McIllroy, &lt;a href='http://pic.plover.com/UnixReader/'&gt;"A Research UNIX Reader: Annotated Excerpts from the Programmer’s Manual, 1971-1986"&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;&lt;/blockquote&gt;

&lt;h2&gt;Why do we need &lt;code&gt;stderr&lt;/code&gt;?&lt;/h2&gt;

&lt;p&gt;So there was a time when &lt;code&gt;stderr&lt;/code&gt; didn't exist. As McIllroy mentions, in that time people were unwilling to violate the simplicity of the standard-input-standard-output model to add something like &lt;code&gt;stderr&lt;/code&gt;. Let's have a look at the &lt;code&gt;grep&lt;/code&gt; command to see a real example of why &lt;code&gt;stderr&lt;/code&gt; is needed.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; grep hosts /private/etc/*
&lt;span class="go"&gt;grep: /private/etc/AFP.conf: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/aliases.db: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;/private/etc/amavisd.conf:# from internal hosts to a dedicated TCP port (such as 10026) for filtering&lt;/span&gt;
&lt;span class="go"&gt;/private/etc/auto_master:/net          -hosts      -nobrowse,hidefromfinder,nosuid&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/kcpassword: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/krb5.keytab: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/master.passwd: Permission denied&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;From this command I've got some diagnostic messages (permission errors) mixed with real matched output. &lt;strong&gt;When writing to a console both &lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stderr&lt;/code&gt; will be printed&lt;/strong&gt;, this is useful so that I can see the errors as they happen. But what if I was redirecting the output to a file to send to somebody else, or save for later?&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; grep hosts /private/etc/* &amp;gt; results.txt
&lt;span class="go"&gt;grep: /private/etc/AFP.conf: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/aliases.db: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/kcpassword: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/krb5.keytab: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/master.passwd: Permission denied&lt;/span&gt;

&lt;span class="gp"&gt;$&lt;/span&gt; cat results.txt
&lt;span class="go"&gt;/private/etc/amavisd.conf:# from internal hosts to a dedicated TCP port (such as 10026) for filtering&lt;/span&gt;
&lt;span class="go"&gt;/private/etc/auto_master:/net          -hosts      -nobrowse,hidefromfinder,nosuid&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;That's actually just what I wanted: I saw the errors printed to the console but all of the matched output was sent to the file. In the time of Unix v6 both the errors AND the output would have been sent to the file, which I would have needed to clean up manually. Woohoo for &lt;code&gt;stderr&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Redirecting &lt;code&gt;stderr&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;You can also achieve the opposite, send &lt;code&gt;stderr&lt;/code&gt; to a file and print &lt;code&gt;stdout&lt;/code&gt; on the console by redirecting a specific file descriptor number. For &lt;code&gt;stderr&lt;/code&gt; that's 2.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; grep hosts /private/etc/* 2&amp;gt; error.log
&lt;span class="go"&gt;/private/etc/amavisd.conf:# from internal hosts to a dedicated TCP port (such as 10026) for filtering&lt;/span&gt;
&lt;span class="go"&gt;/private/etc/auto_master:/net          -hosts      -nobrowse,hidefromfinder,nosuid&lt;/span&gt;

&lt;span class="gp"&gt;$&lt;/span&gt; cat error.log
&lt;span class="go"&gt;grep: /private/etc/AFP.conf: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/aliases.db: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/kcpassword: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/krb5.keytab: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/master.passwd: Permission denied&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;And one more example, redirecting both &lt;code&gt;stderr&lt;/code&gt; and &lt;code&gt;stdout&lt;/code&gt; to a file, to preserve exactly what you'd see on the console.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; grep hosts /private/etc/* &amp;amp;&amp;gt; results.txt
&lt;span class="gp"&gt;$&lt;/span&gt; cat results.txt
&lt;span class="go"&gt;grep: /private/etc/AFP.conf: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/aliases.db: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;/private/etc/amavisd.conf:# from internal hosts to a dedicated TCP port (such as 10026) for filtering&lt;/span&gt;
&lt;span class="go"&gt;/private/etc/auto_master:/net          -hosts      -nobrowse,hidefromfinder,nosuid&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/kcpassword: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/krb5.keytab: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/master.passwd: Permission denied&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Identify Yourself!&lt;/h2&gt;

&lt;p&gt;Notice how the error messages from grep are prepended with 'grep:'?&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="go"&gt;grep: /private/etc/master.passwd: Permission denied&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This is what McIllroy was talking about when he said "With pipelines diagnostics could come from any of several programs running simultaneously. Diagnostics needed to identify themselves." Consider a pipeline like this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="go"&gt;grep hosts /private/etc/* | awk &amp;#39;{print($1)}&amp;#39; | xargs cat&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/AFP.conf: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/aliases.db: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/kcpassword: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/krb5.keytab: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/master.passwd: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;cat: /private/etc/amavisd.conf:#: No such file or directory&lt;/span&gt;
&lt;span class="go"&gt;cat: /private/etc/auto_master:/net: No such file or directory&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Were it not for the prefixed command name in front of the error we'd have no idea which command was printing the error. For all we know every error could have been coming from &lt;code&gt;awk&lt;/code&gt;. Thankfully most commands support this convention today so we can figure out where we're going wrong.&lt;/p&gt;

&lt;h2&gt;&lt;code&gt;stderr&lt;/code&gt; and Pipes&lt;/h2&gt;

&lt;p&gt;When you pipe the output of one command to another command only the &lt;code&gt;stdout&lt;/code&gt; is passed over the pipe. Again, this is just what we want, but was not the case back in the Unix v6 days. Have a look at this grep example:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; grep hosts /private/etc/* | grep &lt;span class="s1"&gt;&amp;#39;Permission denied&amp;#39;&lt;/span&gt; &amp;gt; results.txt
&lt;span class="go"&gt;grep: /private/etc/AFP.conf: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/aliases.db: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/kcpassword: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/krb5.keytab: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/master.passwd: Permission denied&lt;/span&gt;

&lt;span class="gp"&gt;$&lt;/span&gt; cat results.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;So the errors were printed to the console but they're not present in the output. Highlighted in this case by the fact that we searched for them with the second &lt;code&gt;grep&lt;/code&gt; command but they don't exist in the results file.&lt;/p&gt;

&lt;p&gt;If you need to pass &lt;code&gt;stderr&lt;/code&gt; over a pipe along with &lt;code&gt;stdout&lt;/code&gt; you can do that by redirecting the &lt;code&gt;stderr&lt;/code&gt; stream (file descriptor #2) to &lt;code&gt;stdout&lt;/code&gt; (file descriptor #1), like so:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; grep hosts /private/etc/* 2&amp;gt;&amp;amp;1 | grep &lt;span class="s1"&gt;&amp;#39;Permission denied&amp;#39;&lt;/span&gt; &amp;gt; results.txt

&lt;span class="gp"&gt;$&lt;/span&gt; cat results.txt 
&lt;span class="go"&gt;grep: /private/etc/AFP.conf: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/aliases.db: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/kcpassword: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/krb5.keytab: Permission denied&lt;/span&gt;
&lt;span class="go"&gt;grep: /private/etc/master.passwd: Permission denied&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;In this case there was nothing printed to the console, but the errors were matched and sent to the results file.&lt;/p&gt;

&lt;h2&gt;I probably don't want your help docs&lt;/h2&gt;

&lt;p&gt;It's pretty obvious that any error messages should be printed to &lt;code&gt;stderr&lt;/code&gt; because I probably don't want them as input to other programs, and if I really do then I can use redirection to get it. But McIllroy specifically says that &lt;code&gt;stderr&lt;/code&gt; is for diagnostic messages, why didn't he just say errors?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;stderr&lt;/code&gt; is also the place where you print stuff like help docs when an invalid argument is passed to a command&lt;/strong&gt;. In this case its help docs should be printed, but not be passed on to the next program.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; cat Gemfile | grep -k gem | awk &lt;span class="s1"&gt;&amp;#39;{print($2)}&amp;#39;&lt;/span&gt; | xargs gem install
&lt;span class="go"&gt;grep: invalid option -- k&lt;/span&gt;
&lt;span class="go"&gt;Usage: grep [OPTION]... PATTERN [FILE]...&lt;/span&gt;
&lt;span class="go"&gt;Try `grep --help&amp;#39; for more information.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Thankfully the help docs for &lt;code&gt;grep&lt;/code&gt; are printed to &lt;code&gt;stderr&lt;/code&gt; so I don't try to install them as gems in this case.&lt;/p&gt;

&lt;p&gt;But if I'm invoking a command specifically to read its help docs, then it should be printed to &lt;code&gt;stdout&lt;/code&gt;. Take the following example:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="console"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; git --help | grep pull
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;In this case I certainly want the help docs; I asked for them explicitly with the &lt;code&gt;--help&lt;/code&gt; option so I could grep for the specific option I was looking for. &lt;strong&gt;When asking explicitly for help docs they should be printed to &lt;code&gt;stdout&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;Unix Reader&lt;/h2&gt;

&lt;p&gt;The Unix Reader is a fascinating read from someone who was there and contributing in the early days of Unix. &lt;a href="http://pic.plover.com/UnixReader/reader.pdf"&gt;This document&lt;/a&gt; is a good place to start if you enjoy reading about Unix history and origins, or just like to hear some hacker stories.&lt;/p&gt;

&lt;p&gt;Leave a comment if you know of other stuff that's printed to &lt;code&gt;stderr&lt;/code&gt; besides errors and usage documentation.&lt;/p&gt;

&lt;hr /&gt;


&lt;p&gt;Like what you just read? Check out my eBook: &lt;a href="http://workingwithunixprocesses.com?std"&gt;Working With Unix Processes&lt;/a&gt;. The first crash course in Unix programming just for Rubyists.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/OhVWUjkj_sUISTB9fOpInyKkytQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/OhVWUjkj_sUISTB9fOpInyKkytQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/OhVWUjkj_sUISTB9fOpInyKkytQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/OhVWUjkj_sUISTB9fOpInyKkytQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/5fwc2aT2Xjo" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2011/12/29/the-difference-between-stdout-and-stderr.html</feedburner:origLink></entry>
 
 <entry>
   <title>The rails command and exec(2)</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/0SKhvPq1Xpc/rails-and-exec.html" />
   <updated>2011-12-20T00:00:00-05:00</updated>
   <id>http://jstorimer.com/2011/12/20/rails-and-exec</id>
   <content type="html">&lt;p&gt;TL;DR: The sole job of the &lt;code&gt;rails&lt;/code&gt; command that ships with the rails gem is to &lt;code&gt;exec ./script/rails&lt;/code&gt; in your Rails project. Combine that with &lt;a href="http://tenderlovemaking.com/2011/11/30/psa-the-number-of-gems-installed-on-your-system-can-impact-rails-boot-time/"&gt;Aaron's PSA&lt;/a&gt; and that can be considerable overhead. &lt;strong&gt;You should use &lt;code&gt;./script/rails&lt;/code&gt; instead of &lt;code&gt;rails&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;hr /&gt;


&lt;p&gt;Ah, the &lt;code&gt;rails&lt;/code&gt; command. Chances are that if you're writing Ruby code: you're using the &lt;code&gt;rails&lt;/code&gt; command all the time.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;rails&lt;/code&gt; command is just a thin wrapper around exec(2). If you don't know what exec(2) is or why the &lt;code&gt;rails&lt;/code&gt; command uses it then keep reading.&lt;/p&gt;

&lt;h2&gt;From the top&lt;/h2&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;## File: rails/bin/rails&lt;/span&gt;
&lt;span class="c1"&gt;#!/usr/bin/env ruby&lt;/span&gt;

&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rails/cli&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt;
  &lt;span class="n"&gt;railties_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expand_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;../../railties/lib&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="vg"&gt;$:&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unshift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;railties_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rails/cli&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This is the contents of &lt;code&gt;bin/rails&lt;/code&gt; from the rails gem. This is the code that gets invoked when you use the &lt;code&gt;rails&lt;/code&gt; binary.&lt;/p&gt;

&lt;p&gt;You can see that all it really does is require &lt;code&gt;rails/cli&lt;/code&gt; from railties. Let's look there next.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;## File: railties/lib/rails/cli.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rbconfig&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rails/script_rails_loader&amp;#39;&lt;/span&gt;

&lt;span class="c1"&gt;# If we are inside a Rails application this method performs an exec and thus&lt;/span&gt;
&lt;span class="c1"&gt;# the rest of this script is not run.&lt;/span&gt;
&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ScriptRailsLoader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exec_script_rails!&lt;/span&gt;

&lt;span class="n"&gt;railties_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expand_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;../../lib&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="vg"&gt;$:&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unshift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;railties_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;directory?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;railties_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="vg"&gt;$:&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;railties_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rails/ruby_version_check&amp;#39;&lt;/span&gt;
&lt;span class="no"&gt;Signal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;INT&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rails/commands/application&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The first line of interest is the one after the requires. The comment mentions that this method may or may not call exec. If it does then the rest of the script won't run.&lt;/p&gt;

&lt;p&gt;It's time to step back and look at what exec(2) does. First, exec(2) is a system call: a direct request to the kernel asking for some function that only the kernel can do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;exec(2) transforms the current process into another process&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Hi from Ruby&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ls&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Bye from Ruby&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;If you execute that block of code you'll notice that the last line after the &lt;code&gt;exec&lt;/code&gt; is never reached. The call to &lt;code&gt;exec&lt;/code&gt; actually transformed the Ruby process into an &lt;code&gt;ls&lt;/code&gt; process. You'll see the output from &lt;code&gt;ls&lt;/code&gt; right after the output from the first line.&lt;/p&gt;

&lt;p&gt;In this way exec(2) is a bit like jumping out of a plane. Your process fully commits to becoming another process and there's no way to go back and resume execution. The &lt;code&gt;ls&lt;/code&gt; process has no idea that it used to be a Ruby process, and is not programmed to transform itself to another process.&lt;/p&gt;

&lt;p&gt;This looks a bit like &lt;code&gt;Kernel#system&lt;/code&gt; but works differently. If you shell out using something like &lt;code&gt;system&lt;/code&gt; your Ruby process will resume execution after the shell command is finished.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Hi from Ruby&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ls&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Bye from Ruby&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;In this example the last line will be executed.&lt;/p&gt;

&lt;p&gt;This is because &lt;code&gt;Kernel#system&lt;/code&gt; uses a combination of fork(2) (create a new process) and exec(2) (transform that process) rather than transforming the current process.&lt;/p&gt;

&lt;p&gt;The example above was a bit contrived. Keep reading to see how the &lt;code&gt;rails&lt;/code&gt; command uses it.&lt;/p&gt;

&lt;p&gt;Down another level.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;## File: railties/lib/rails/script_rails_loader.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;pathname&amp;#39;&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Rails&lt;/span&gt;
  &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;ScriptRailsLoader&lt;/span&gt;
    &lt;span class="no"&gt;RUBY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="no"&gt;RbConfig&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;CONFIG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;values_at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;bindir&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;ruby_install_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="no"&gt;RbConfig&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;CONFIG&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;EXEEXT&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="no"&gt;SCRIPT_RAILS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;script&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec_script_rails!&lt;/span&gt;
      &lt;span class="n"&gt;cwd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pwd&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;in_rails_application?&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;in_rails_application_subdirectory?&lt;/span&gt;
      &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="no"&gt;RUBY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;SCRIPT_RAILS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="no"&gt;ARGV&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;in_rails_application?&lt;/span&gt;
      &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;..&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="c1"&gt;# Recurse in a chdir block: if the search fails we want to be sure&lt;/span&gt;
        &lt;span class="c1"&gt;# the application is generated in the original working directory.&lt;/span&gt;
        &lt;span class="n"&gt;exec_script_rails!&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;cwd&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pwd&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt; 
    &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;SystemCallError&lt;/span&gt;
      &lt;span class="c1"&gt;# could not chdir, no problem just return&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt; 

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;in_rails_application?&lt;/span&gt;
      &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;SCRIPT_RAILS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt; 

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;in_rails_application_subdirectory?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Pathname&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pwd&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;SCRIPT_RAILS&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;root?&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;in_rails_application_subdirectory?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;   
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This class is a bit noisy. We'll take it one line at a time.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="no"&gt;RUBY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="no"&gt;RbConfig&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;CONFIG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;values_at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;bindir&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;ruby_install_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="no"&gt;RbConfig&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;CONFIG&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;EXEEXT&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="no"&gt;SCRIPT_RAILS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;script&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The class sets up some constants for itself. The first is notable as it gets the full path to the Ruby executable for this system. By running it through &lt;code&gt;File.join&lt;/code&gt; and adding the extension suffix it is compatible with both Unix and Windows filesystems.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec_script_rails!&lt;/span&gt;
  &lt;span class="n"&gt;cwd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pwd&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;in_rails_application?&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;in_rails_application_subdirectory?&lt;/span&gt;
  &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="no"&gt;RUBY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;SCRIPT_RAILS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="no"&gt;ARGV&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;in_rails_application?&lt;/span&gt;
  &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;..&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# Recurse in a chdir block: if the search fails we want to be sure&lt;/span&gt;
    &lt;span class="c1"&gt;# the application is generated in the original working directory.&lt;/span&gt;
    &lt;span class="n"&gt;exec_script_rails!&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;cwd&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pwd&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;   
&lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;SystemCallError&lt;/span&gt;
  &lt;span class="c1"&gt;# could not chdir, no problem just returnend&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
  
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;in_rails_application?&lt;/span&gt;
  &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;SCRIPT_RAILS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt; 

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;in_rails_application_subdirectory?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Pathname&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pwd&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;SCRIPT_RAILS&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;root?&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;in_rails_application_subdirectory?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The main method here is &lt;code&gt;exec_script_rails!&lt;/code&gt;. Notice that it returns unless already in a Rails app directory or subdirectory. In that case &lt;code&gt;exec&lt;/code&gt; won't be called and the command will take a different path.&lt;/p&gt;

&lt;p&gt;The methods &lt;code&gt;in_rails_application_subdirectory?&lt;/code&gt; and &lt;code&gt;in_rails_application?&lt;/code&gt; recursively search the filesystem looking for &lt;code&gt;script/rails&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Assuming that we're somewhere in a Rails app directory the following block of code is executed.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;  &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="no"&gt;RUBY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;SCRIPT_RAILS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="no"&gt;ARGV&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;in_rails_application?&lt;/span&gt;
  &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;..&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# Recurse in a chdir block: if the search fails we want to be sure&lt;/span&gt;
    &lt;span class="c1"&gt;# the application is generated in the original working directory.&lt;/span&gt;
    &lt;span class="n"&gt;exec_script_rails!&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;cwd&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pwd&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;SystemCallError&lt;/span&gt;
  &lt;span class="c1"&gt;# could not chdir, no problem just return&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;When already in the root of a Rails app then the &lt;code&gt;exec&lt;/code&gt; is done immediately, passing any of the arguments that were passed in on the command line. Remember from our talk about &lt;code&gt;exec&lt;/code&gt; that if this happens then none of the rest of the code afterwards will be executed.&lt;/p&gt;

&lt;p&gt;The other code path covers the case where the &lt;code&gt;rails&lt;/code&gt; command is being used from a Rails app subdirectory. It continues to &lt;code&gt;Dir.chdir&lt;/code&gt; to the parent directory until it gets to the root of the Rails app, at which point it does the same call to &lt;code&gt;exec&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The comment about chdir refers to the fact that even though the pwd is being changed with &lt;code&gt;Dir.chdir&lt;/code&gt; it will be reset to the original working directory when the block returns.&lt;/p&gt;

&lt;h2&gt;So...&lt;/h2&gt;

&lt;p&gt;So, besides being used à la &lt;code&gt;rails new&lt;/code&gt; to bootstrap a new app, the whole point of the &lt;code&gt;rails&lt;/code&gt; command is just to find &lt;code&gt;./script/rails&lt;/code&gt; and 'become' it. You can do the job of the &lt;code&gt;rails&lt;/code&gt; command yourself by just using &lt;code&gt;./script/rails&lt;/code&gt; directly.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;rails console
&lt;span class="c"&gt;# same as&lt;/span&gt;
./script/rails console
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Using &lt;code&gt;./script/rails&lt;/code&gt; directly avoids only a little bit of code, but it may provide more of a boost than you think given &lt;a href="http://tenderlovemaking.com/2011/11/30/psa-the-number-of-gems-installed-on-your-system-can-impact-rails-boot-time/"&gt;Aaron Patterson's recent PSA regarding rubygems&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When you use the &lt;code&gt;rails&lt;/code&gt; command you pay the penalty of loading every gemspec on your system. Even worse is using &lt;code&gt;bundle exec rails&lt;/code&gt;. Since both &lt;code&gt;bundle&lt;/code&gt; and &lt;code&gt;rails&lt;/code&gt; are rubygems binstubs you pay that penalty twice!&lt;/p&gt;

&lt;p&gt;By using &lt;code&gt;./script/rails&lt;/code&gt; you can avoid paying that penalty and execute just a little bit less code from Rails startup. And, as we all know: The best code is no code at all.&lt;/p&gt;

&lt;p&gt;Understanding how your tools work is critical to improving your workflow, as well as properly debugging your production apps, find out what you need to know about Unix programming in &lt;a href="http://workingwithunixprocesses.com"&gt;Working With Unix Processes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/EMzTTdBmDp9E6ZOE-IzDi4iEf6Y/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/EMzTTdBmDp9E6ZOE-IzDi4iEf6Y/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/EMzTTdBmDp9E6ZOE-IzDi4iEf6Y/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/EMzTTdBmDp9E6ZOE-IzDi4iEf6Y/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/0SKhvPq1Xpc" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2011/12/20/rails-and-exec.html</feedburner:origLink></entry>
 
 <entry>
   <title>On Colorized Output</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/PkdKtqvIGN4/on-colorized-output.html" />
   <updated>2011-12-16T00:00:00-05:00</updated>
   <id>http://jstorimer.com/2011/12/16/on-colorized-output</id>
   <content type="html">&lt;p&gt;Colorized output should be configurable.&lt;/p&gt;

&lt;p&gt;This is a followup to my &lt;a href="http://jstorimer.com/2011/12/12/writing-ruby-scripts-that-respect-pipelines.html"&gt;last post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In that post I said:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;When you are piping output to another program you should always send plain, unformatted text. Unix utilities expect to deal with plain text.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt; A redditor &lt;a href="http://www.reddit.com/r/programming/comments/ncm7k/writing_ruby_scripts_that_play_nice_with_the_unix/c382zi7"&gt;commented on that post&lt;/a&gt; to this effect: (paraphrasing is mine)&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Modern pagers and other programs can handle colorized output just fine, so colorized output from your scripts should be configurable.&lt;/p&gt;

&lt;p&gt;If you're redirecting to a file, or some other program that doesn't understand escaped color sequences, then colorized output can be turned off, otherwise it'll probably work just fine.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Good advice, and he's absolutely right.&lt;/p&gt;

&lt;p&gt;I started from the same &lt;a href="https://gist.github.com/1465437/97442b46bed8fbb4b6ac441c739430b80997fb13"&gt;script used in the last post&lt;/a&gt; and removed the check for &lt;code&gt;$stdout.tty?&lt;/code&gt; so that colorized output is always on. Now to experiment.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;hilong Gemfile | less
&lt;span class="nv"&gt;$ &lt;/span&gt;hilong Gemfile | grep gem
&lt;span class="nv"&gt;$ &lt;/span&gt;hilong Gemfile | more
&lt;span class="nv"&gt;$ &lt;/span&gt;hilong Gemfile &amp;gt; out.put
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Your results may vary depending on your system and your configuration, but for me the first two experiments worked just fine and the second two didn't.&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;grep&lt;/code&gt; and &lt;code&gt;less&lt;/code&gt; handled the color codes fine, but &lt;code&gt;more&lt;/code&gt; didn't. Redirecting to a file obviously just preserved the raw text, which won't be interpreted by text editors and the like when it's opened later.&lt;/p&gt;

&lt;p&gt;So there needs to be some way to turn colorized output on...or off...&lt;/p&gt;

&lt;h2&gt;Sensible Default?&lt;/h2&gt;

&lt;p&gt;When in doubt, follow suit. Tools like &lt;code&gt;grep&lt;/code&gt; and &lt;code&gt;less&lt;/code&gt; don't colorize output by default. But &lt;code&gt;ack&lt;/code&gt;, for instance, does colorize by default. So what should &lt;code&gt;hilong&lt;/code&gt; do?&lt;/p&gt;

&lt;p&gt;Given that the 'highlighting' is basically the point of this tool I think that colorized output should be enabled by default. For most modern tools colorized output will not cause a problem, disabling colorized output will be a special case.&lt;/p&gt;

&lt;p&gt;But there needs to be an option for that.&lt;/p&gt;

&lt;h2&gt;Parsing command-line options&lt;/h2&gt;

&lt;p&gt;Ruby's standard library has a class just for parsing command-line options. It's called &lt;code&gt;optparse&lt;/code&gt;. Using the script from the last blog post, here's how to use &lt;code&gt;optparse&lt;/code&gt; to accept a &lt;code&gt;--no-color&lt;/code&gt; option.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="n"&gt;maximum_line_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
&lt;span class="n"&gt;colorized_output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;optparse&amp;#39;&lt;/span&gt;
&lt;span class="no"&gt;OptionParser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;--no-color&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Disable colorized output&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;colorized_output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt; 
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse!&lt;/span&gt;

&lt;span class="c1"&gt;# Keep reading lines of input as long as they&amp;#39;re coming.&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ARGF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gets&lt;/span&gt;
  &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each_line&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="c1"&gt;# Construct a string that begins with the length of this line&lt;/span&gt;
    &lt;span class="c1"&gt;# and ends with the content. The trailing newline is #chop&amp;#39;ped &lt;/span&gt;
    &lt;span class="c1"&gt;# off of the content so we can control where the newline occurs.&lt;/span&gt;
    &lt;span class="c1"&gt;# The string are joined with a tab character so that indentation&lt;/span&gt;
    &lt;span class="c1"&gt;# is preserved.&lt;/span&gt;
    &lt;span class="n"&gt;output_line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chop&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# If the line is long and our $stdout is not being piped then we&amp;#39;ll&lt;/span&gt;
    &lt;span class="c1"&gt;# colorize this line.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;colorized_output&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;maximum_line_length&lt;/span&gt;
      &lt;span class="c1"&gt;# Turn the output to red starting at the first character.&lt;/span&gt;
      &lt;span class="n"&gt;output_line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;red&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Something of interest is that &lt;code&gt;colorized_output&lt;/code&gt; is assigned to &lt;code&gt;true&lt;/code&gt; at the beginning, and then is assigned the value of the parsed option if that was passed in. Nowhere is it specified that &lt;code&gt;--no-color&lt;/code&gt; should set &lt;code&gt;colorized_output&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;, it's simply assigned the value passed by &lt;code&gt;optparse&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;optparse&lt;/code&gt; encourages best practices by recognizing certain conventions. eg. &lt;code&gt;--[no-]thing&lt;/code&gt; for boolean options, &lt;code&gt;--arg value&lt;/code&gt; for required options.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;optparse&lt;/code&gt; was able to figure that &lt;code&gt;--no-color&lt;/code&gt; is a boolean and that it should be negative (false) considering it's prefixed with a &lt;code&gt;--no&lt;/code&gt;. Rad.&lt;/p&gt;

&lt;p&gt;Notice that the check for &lt;code&gt;$stdout.tty?&lt;/code&gt; has been removed. It no longer matters. Output is colorized unless disabled with the command-line option.&lt;/p&gt;

&lt;p&gt;Now &lt;code&gt;hilong&lt;/code&gt; can be used with that option to disable colorized output.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;hilong --no-color Gemfile
&lt;span class="nv"&gt;$ &lt;/span&gt;cat Gemfile Gemfile.lock | hilong --no-color | more
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Perfect. And thanks to &lt;code&gt;optparse&lt;/code&gt; there's also some nice documentation showing which options are supported.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;hilong -h
Usage: hilong &lt;span class="o"&gt;[&lt;/span&gt;options&lt;span class="o"&gt;]&lt;/span&gt;
        --no-color                   Disable colorized output
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Not bad, but it's easy to make that look better.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;optparse&amp;#39;&lt;/span&gt;
&lt;span class="no"&gt;OptionParser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="c1"&gt;# This banner is the first line of the help documentation.&lt;/span&gt;
  &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;banner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Usage: hilong [options] [files]&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;\&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;Show character count for each line of input and highlight long lines.&amp;quot;&lt;/span&gt;

  &lt;span class="c1"&gt;# Separator just adds a new line with the specified text.&lt;/span&gt;
  &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;separator&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;
  &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;separator&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Specific options:&amp;quot;&lt;/span&gt;

  &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;--no-color&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Disable colorized output&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;colorized_output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# on_tail says that this option should appear at the bottom of&lt;/span&gt;
  &lt;span class="c1"&gt;# the options list.&lt;/span&gt;
  &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;on_tail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-h&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;--help&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;You&amp;#39;re looking at it!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="vg"&gt;$stderr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;
    &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now the help docs look like this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;hilong -h
Usage: hilong &lt;span class="o"&gt;[&lt;/span&gt;options&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;files&lt;span class="o"&gt;]&lt;/span&gt;
Show character count &lt;span class="k"&gt;for &lt;/span&gt;each line of input and highlight long lines.

Specific options:
        --no-color                   Disable colorized output
    -h, --help                       You&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;re looking at it!
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Much better.&lt;/p&gt;

&lt;h2&gt;Moar options&lt;/h2&gt;

&lt;p&gt;I want to show one more case with &lt;code&gt;optparse&lt;/code&gt;. Currently the script assumes that long lines are 80 chars or more. It's &lt;a href="http://richarddingwall.name/2008/05/31/is-the-80-character-line-limit-still-relevant/"&gt;generally&lt;/a&gt; &lt;a href="http://www.vogella.de/blog/2011/09/06/eclipse-default-line-length-of-80-chars-outdate/"&gt;accepted&lt;/a&gt; that 80 chars is a long line but some some devs push that number to 120, or something else entirely. The maximum line length should be configurable.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-m&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;--max NUM&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Maximum line length&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;maximum_line_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Again &lt;code&gt;optparse&lt;/code&gt; is making a few assumptions about the options, but it does a pretty good job of it. It's set to accept an &lt;code&gt;Integer&lt;/code&gt; along with the &lt;code&gt;-m&lt;/code&gt; or &lt;code&gt;--max&lt;/code&gt; option. The result is assigned to the previously existing local variable and is handled by the rest of the script.&lt;/p&gt;

&lt;p&gt;Now it can be used like so:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cat Gemfile* | hilong --max 20
&lt;span class="nv"&gt;$ &lt;/span&gt;hilong --m 140 Gemfile
&lt;span class="nv"&gt;$ &lt;/span&gt;hilong --max&lt;span class="o"&gt;=&lt;/span&gt;180 Gemfile
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Try to pass something besides an Integer with the &lt;code&gt;max&lt;/code&gt; option and &lt;code&gt;optparse&lt;/code&gt; rightfully complains.&lt;/p&gt;

&lt;p&gt;Full source of the hilong script is at &lt;a href="https://gist.github.com/1465437"&gt;https://gist.github.com/1465437&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://www.ruby-doc.org/stdlib-1.9.2/libdoc/optparse/rdoc/OptionParser.html"&gt;ruby-core documentation for OptionParser&lt;/a&gt; contains a useful example if you want to know more.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/cAcXprAt7Dxoepaad30vvyPLRxA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/cAcXprAt7Dxoepaad30vvyPLRxA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/cAcXprAt7Dxoepaad30vvyPLRxA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/cAcXprAt7Dxoepaad30vvyPLRxA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/PkdKtqvIGN4" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2011/12/16/on-colorized-output.html</feedburner:origLink></entry>
 
 <entry>
   <title>Writing Ruby Scripts That Respect Pipelines</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/isXmW0hdrk4/writing-ruby-scripts-that-respect-pipelines.html" />
   <updated>2011-12-12T00:00:00-05:00</updated>
   <id>http://jstorimer.com/2011/12/12/writing-ruby-scripts-that-respect-pipelines</id>
   <content type="html">&lt;p&gt;Pipes are the most powerful concept on the command line.&lt;/p&gt;

&lt;p&gt;With pipes you can string together small, simple commands into bigger, more useful pipelines. This is the secret sauce that goes along with the Unix philosophy of "Do one thing, and do it well". Take this as an example:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="c"&gt;# Look for any lines mentioning &amp;#39;user&amp;#39; in the current git diff&lt;/span&gt;
&lt;span class="c"&gt;# and display them one page at a time using less(1).&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git diff | grep user | less
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;A simple utility&lt;/h2&gt;

&lt;p&gt;Here's a Ruby script I'm calling &lt;code&gt;hilong&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It's a small, simple utility that takes a file as an argument and prints each line prepended with its length. Lines longer than the maximum length (80 chars by default) are highlighted in red. Here's the simplest version of our script:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;#!/usr/bin/env ruby&lt;/span&gt;

&lt;span class="c1"&gt;# A file is passed in as an argument&lt;/span&gt;
&lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ARGV&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# escaped bash color codes&lt;/span&gt;
&lt;span class="n"&gt;red&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[31m&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;reset_color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[0m&amp;quot;&lt;/span&gt;

&lt;span class="n"&gt;maximum_line_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;

&lt;span class="c1"&gt;# For each line of the input...&lt;/span&gt;
&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each_line&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="c1"&gt;# Construct a string that begins with the length of this line&lt;/span&gt;
  &lt;span class="c1"&gt;# and ends with the content. The trailing newline is #chop&amp;#39;ped &lt;/span&gt;
  &lt;span class="c1"&gt;# off of the content so we can control where the newline occurs.&lt;/span&gt;
  &lt;span class="c1"&gt;# The strings are joined with a tab character so that indentation&lt;/span&gt;
  &lt;span class="c1"&gt;# is preserved.&lt;/span&gt;
  &lt;span class="n"&gt;output_line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chop&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;maximum_line_length&lt;/span&gt;
    &lt;span class="c1"&gt;# Turn the output to red starting at the first character.&lt;/span&gt;
    &lt;span class="n"&gt;output_line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;red&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Reset the text color back to what it was at the end of the&lt;/span&gt;
    &lt;span class="c1"&gt;# line.&lt;/span&gt;
    &lt;span class="n"&gt;output_line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reset_color&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="vg"&gt;$stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;output_line&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;And here's how it works:&lt;/p&gt;

&lt;div class="highlight"&gt;
  &lt;pre&gt;&lt;code class="bash"&gt; &lt;span class="nv"&gt;$ &lt;/span&gt;hilong Gemfile
17    &lt;span class="nb"&gt;source&lt;/span&gt; :rubygems
1
13    gem &lt;span class="s1"&gt;'jekyll'&lt;/span&gt;
&lt;span style="color: #A00"&gt;82    gem &lt;span class=""&gt;'liquid'&lt;/span&gt;, &lt;span class=""&gt;'2.2.2'&lt;/span&gt;         &lt;span class=""&gt;# The comment on this line is long-winded, not sure why... &lt;/span&gt;&lt;/span&gt;
16    gem &lt;span class="s1"&gt;'RedCloth'&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This works pretty well. It takes a file as input and puts the modified version onto its &lt;code&gt;$stdout&lt;/code&gt;. Let's see how it fares when we combine it with other utilities.&lt;/p&gt;

&lt;h2&gt;Introducing Pipes&lt;/h2&gt;

&lt;p&gt;Let's start by trying to pipe the output of this utility to another utility:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="c"&gt;# Only show &amp;#39;gem&amp;#39; lines.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;hilong Gemfile | grep gem
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This works nicely. Since we put our output on &lt;code&gt;$stdout&lt;/code&gt; grep(1) can read it and do the proper filtering. It even preserves our color codes!&lt;/p&gt;

&lt;p&gt;Let's try another one:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="c"&gt;# View the output one page at a time.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;hilong Gemfile | more
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Eeee. Now we get some ugly escape codes in our output. It seems that more(1) doesn't know what to do with the bash escaped colors that we included so it just includes it as part of the output. The same things happens if you redirect the output to a file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When you are piping output to another program you should always send plain, unformatted text. Unix utilities expect to deal with plain text.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;Is a tty?&lt;/h2&gt;

&lt;p&gt;So we can't include our color codes if our output is being piped to another program, but we want to include the color codes if our output is being displayed in a terminal. How do we tell?&lt;/p&gt;

&lt;p&gt;Ruby's &lt;code&gt;IO#isatty&lt;/code&gt; method (aliased as &lt;code&gt;IO#tty?&lt;/code&gt;) will tell you whether or not the &lt;code&gt;IO&lt;/code&gt; in question is attached to a terminal. Calling it on &lt;code&gt;$stdout&lt;/code&gt;, for instance, when it's being piped will return false.&lt;/p&gt;

&lt;p&gt;We'll rewrite our script to make use of this, I've highlighted the relevant part below:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;  &lt;span class="c1"&gt;# If the line is long and our $stdout is not being piped then we&amp;#39;ll&lt;/span&gt;
  &lt;span class="c1"&gt;# colorize this line.&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vg"&gt;$stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tty?&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;maximum_line_length&lt;/span&gt;
    &lt;span class="c1"&gt;# Turn the output to red starting at the first character.&lt;/span&gt;
    &lt;span class="n"&gt;output_line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;red&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Reset the text color back to what it was at the end of the&lt;/span&gt;
    &lt;span class="c1"&gt;# line.&lt;/span&gt;
    &lt;span class="n"&gt;output_line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reset_color&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt; 

  &lt;span class="vg"&gt;$stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;output_line&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now if we try piping our output to more(1) again, or to a file, we get nice plain text.&lt;/p&gt;

&lt;h2&gt;Incoming!&lt;/h2&gt;

&lt;p&gt;Most Unix utilties also respond to pipes coming from the other direction, as input. Let's see how our utility responds when we pipe in some input:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cat Gemfile Gemfile.lock | hilong 
/Users/jessestorimer/projects/hilong/hilong:4:in &lt;span class="sb"&gt;`&lt;/span&gt;initialize&lt;span class="s1"&gt;&amp;#39;: can&amp;#39;&lt;/span&gt;t convert nil into String &lt;span class="o"&gt;(&lt;/span&gt;TypeError&lt;span class="o"&gt;)&lt;/span&gt;
from /Users/jessestorimer/projects/hilong/hilong:4:in &lt;span class="sb"&gt;`&lt;/span&gt;open&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;span class="s1"&gt;    from /Users/jessestorimer/projects/hilong/hilong:4:in `&amp;lt;main&amp;gt;&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;:/&lt;/p&gt;

&lt;p&gt;Right now our utility is only written to handle input given as a filename passed in via &lt;code&gt;ARGV&lt;/code&gt;. How can we make it accept raw data from a pipe?&lt;/p&gt;

&lt;p&gt;Ruby has a wonderful facility for this called &lt;code&gt;ARGF&lt;/code&gt;. &lt;code&gt;ARGF&lt;/code&gt; provides a consistent interface for raw data coming in via a pipe, and filenames passed via &lt;code&gt;ARGV&lt;/code&gt;. Let's rewrite our script to take advantage of it:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="diff"&gt;# Read input from files or pipes.
&lt;span class="gd"&gt;-input = File.open(ARGV[0])&lt;/span&gt;
&lt;span class="gi"&gt;+input = ARGF.read&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Wonderful! If something is passed in on &lt;code&gt;ARGV&lt;/code&gt; then &lt;code&gt;ARGF&lt;/code&gt; will assume that it's filenames and call &lt;code&gt;IO#read&lt;/code&gt; on them sequentially. If &lt;code&gt;ARGV&lt;/code&gt; is empty then it reads from &lt;code&gt;$stdin&lt;/code&gt; to get data passed in via pipe.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unix utilities will ignore standard input if filenames are given&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now let's look at all the ways we can use our new utility.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;hilong Gemfile
&lt;span class="nv"&gt;$ &lt;/span&gt;hilong Gemfile | more
&lt;span class="nv"&gt;$ &lt;/span&gt;hilong Gemfile &amp;gt; output.txt
&lt;span class="nv"&gt;$ &lt;/span&gt;hilong Gemfile Gemfile.lock
&lt;span class="nv"&gt;$ &lt;/span&gt;cat Gemfile* | hilong
&lt;span class="nv"&gt;$ &lt;/span&gt;cat Gemfile | hilong - Gemfile.lock
&lt;span class="nv"&gt;$ &lt;/span&gt;hilong &amp;lt; Gemfile
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;One more case...&lt;/h2&gt;

&lt;p&gt;With only a few small changes we were able to get our utility to respect pipelines like any other Unix utility would. But there's one more case I want to demonstrate. What if we're getting input from a pipe coming from a command such as &lt;code&gt;tail -f&lt;/code&gt; where the input never stops coming?&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;tail -f log/test.log | hilong
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;If you give this a try and append to the log file you'll notice that our utility seems to be supressing the output. We're not seeing anything being printed.&lt;/p&gt;

&lt;p&gt;This is due to the fact that we're using &lt;code&gt;ARGF#read&lt;/code&gt;. &lt;code&gt;#read&lt;/code&gt; will block until it receives EOF, but the tail utility will never send EOF because it always has more data. So the first time our utility is invoked with some data it simply blocks and never returns. So we need to change the way we're reading from &lt;code&gt;ARGF&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We'll read from &lt;code&gt;ARGF&lt;/code&gt; one line at a time using &lt;code&gt;#each_line&lt;/code&gt;. &lt;code&gt;#each_line&lt;/code&gt; will, duh, read each line in succession. So anytime a newline is encountered the String is passed into the block.&lt;/p&gt;

&lt;p&gt;Here are the required changes:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;# Keep reading lines of input as long as they&amp;#39;re coming.&lt;/span&gt;
&lt;span class="no"&gt;ARGF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each_line&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="c1"&gt;# Construct a string that begins with the length of this line&lt;/span&gt;
  &lt;span class="c1"&gt;# and ends with the content. The trailing newline is #chop&amp;#39;ped &lt;/span&gt;
  &lt;span class="c1"&gt;# off of the content so we can control where the newline occurs.&lt;/span&gt;
  &lt;span class="c1"&gt;# The string are joined with a tab character so that indentation&lt;/span&gt;
  &lt;span class="c1"&gt;# is preserved.&lt;/span&gt;
  &lt;span class="n"&gt;output_line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chop&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;And that'll do it! Now our utility can handle the slew of input methods I showed above, plus handle continuous data from a pipe.&lt;/p&gt;

&lt;p&gt;The full, finished source for the hilong utility is at &lt;a href="https://gist.github.com/1465437/c75c872957329fd4034bedaf11c4de70635992e4"&gt;https://gist.github.com/1465437/c75c872957329fd4034bedaf11c4de70635992e4&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you can think of a better way to accomplish any of this or there's another use case that I missed let me know in the comments.&lt;/p&gt;

&lt;hr /&gt;


&lt;p&gt;Read the followup post: &lt;a href="http://jstorimer.com/2011/12/16/on-colorized-output.html"&gt;On Colorized Output&lt;/a&gt; where the colorized output becomes configurable.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/j57LJgW4OUt2VCGLeVvVMBbcf4c/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/j57LJgW4OUt2VCGLeVvVMBbcf4c/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/j57LJgW4OUt2VCGLeVvVMBbcf4c/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/j57LJgW4OUt2VCGLeVvVMBbcf4c/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/isXmW0hdrk4" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2011/12/12/writing-ruby-scripts-that-respect-pipelines.html</feedburner:origLink></entry>
 
 <entry>
   <title>You Should be Doing Formal Code Review</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/QGcWpF6n138/you-should-be-doing-formal-code-review.html" />
   <updated>2010-09-30T00:00:00-04:00</updated>
   <id>http://jstorimer.com/ruby/2010/09/30/you-should-be-doing-formal-code-review</id>
   <content type="html">&lt;p&gt;The two practices that have contributed most greatly to my development as a programmer are &lt;span class="caps"&gt;TDD&lt;/span&gt; and formal code review.&lt;/p&gt;
&lt;p&gt;Much like &lt;span class="caps"&gt;TDD&lt;/span&gt;, you should be doing formal code review. This isn&amp;#8217;t for QA purposes, or because developers are untrustworthy in general. Much like &lt;span class="caps"&gt;TDD&lt;/span&gt;, the benefits aren&amp;#8217;t just the outputs of the behaviour, the real benefit is that formal code review changes the way that you think about code.&lt;/p&gt;
&lt;p&gt;From a managerial standpoint the most obvious benefit is that two heads are better than one. Much like pair programming, it&amp;#8217;s best to have more than one developer look at every line of code that makes it into your product.&lt;/p&gt;
&lt;p&gt;From a developer&amp;#8217;s standpoint formal code review often looks like a nuisance. If your current workflow is to write tests, write code, and then ship it, formal code review introduces a brand new blocker into that simple chain of events. Now you need to wait for other developers to comment on your code, you need to resolve any comments they make, and make sure that everyone else is as happy with your code as you are.&lt;/p&gt;
&lt;p&gt;Let me tell you, it&amp;#8217;s well worth it.&lt;/p&gt;
&lt;p&gt;Here are some reasons why:&lt;/p&gt;
&lt;h2&gt;It helps you disidentify with your code.&lt;/h2&gt;
&lt;p&gt;By disidentify I mean that it helps you think of your code as outside yourself. This may seem obvious but I know a lot of programmers who don&amp;#8217;t make the distinction between code and self. The real point of this is that in order to produce the best code possible you need to be able to admit to yourself that what you already have may not be perfect.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s face it, developers are often overly confident in their work, and telling them that something is done wrong can be taken as a personal attack. If you get used to letting other people look at, and critque, your code then disidentification becomes a necessity. This also goes vice versa, you need to be able to talk about the code of your peers without worrying about them taking your critiques as a personal attack. The goal here is to ensure that the best code possible makes it into your final release.&lt;/p&gt;
&lt;h2&gt;It makes you avoid shortcuts.&lt;/h2&gt;
&lt;p&gt;This one may not be true for everyone, but it&amp;#8217;s true for me. Before ever doing formal code review I would often choose suboptimal solutions in order to get changes online fast and get on to the next thing. There was a good chance that other developers wouldn&amp;#8217;t read my code, and of course the end users of the software wouldn&amp;#8217;t know the difference.&lt;/p&gt;
&lt;p&gt;But when you know, for a fact, that your peers will be reviewing every line of code that you write you will ensure your code is as good as it can be. It&amp;#8217;s pretty motivating to think that your peers will be looking at, and commenting on, all of the little shortcuts that you took in your latest patch.&lt;/p&gt;
&lt;p&gt;Really, it&amp;#8217;s about being accountable to your fellow developers. Like I said, when you&amp;#8217;re writing code for your end users they won&amp;#8217;t know how pretty it is, how fast it could be, etc. But when you think of your end users as your fellow developers, motivation increases to ensure that code is readable, extensible, and optimized.&lt;/p&gt;
&lt;h2&gt;It encourages you to review your own code.&lt;/h2&gt;
&lt;p&gt;When making changes and pushing them directly to a production branch, there&amp;#8217;s often little motivation to review your own code once you get all the tests passing. &amp;#8220;That seems a good enough indicator that things are working, on to the next thing!&amp;#8221;&lt;/p&gt;
&lt;p&gt;Again, when you know, for a fact, that your peers are going to review this patch, you&amp;#8217;ll be motivated to give it a thorough review yourself before anyone else does. I&amp;#8217;ve found that this step is crucial in the development process, much like the refactoring step of &lt;span class="caps"&gt;TDD&lt;/span&gt;, during this step you will always find ways to improve on what you&amp;#8217;ve already got.&lt;/p&gt;
&lt;h2&gt;Reading other people&amp;#8217;s code helps you to improve, and helps you improve others.&lt;/h2&gt;
&lt;p&gt;This tip is often given by elite programmers: Read more code. Formal code review facilitates that. It&amp;#8217;s not a matter of some programmers being better than others so that the n00bs can learn from the hax0rz, it&amp;#8217;s the point that different developers work on different things and solve problems in different ways.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve found that programmers can learn most when they are exposed to the programming styles of other programmers. This also helps to create a funnel effect in terms of your Coding style. Any organization will have an explicit (or implicit) set of Coding style guidelines. Formal code review will ensure that any code that is not in accordance with style guidelines gets noticed. Similarly, any code that introduces new, better, styles will also get noticed!&lt;/p&gt;
&lt;h2&gt;It makes for better code.&lt;/h2&gt;
&lt;p&gt;This is a no brainer. Formal code review is kind of like delayed pair programming. I don&amp;#8217;t need to reiterate the benefits of pair programming here, see &lt;a href="http://blog.obiefernandez.com/content/2009/09/10-reasons-pair-programming-is-not-for-the-masses.html"&gt;posts&lt;/a&gt; &lt;a href="http://blog.obiefernandez.com/content/2008/08/the-hashrocket-way-pair-programming.html"&gt;by&lt;/a&gt; Obie Fernandez.&lt;/p&gt;
&lt;h2&gt;Formal Code Review Tools&lt;/h2&gt;
&lt;p&gt;OK, so now that you&amp;#8217;re convinced you need to be doing formal code review, you need tools to support this. If your team is small enough you might think that simply emailing around review requests with Github links would be good enough, but I assure that there is a better way, especially if you have a team size &amp;gt; 2.&lt;/p&gt;
&lt;h3&gt;Rietveld&lt;/h3&gt;
&lt;p&gt;The tool that I am most familiar with is called Rietveld. The &lt;span class="caps"&gt;CLI&lt;/span&gt; and UI are less than perfect, but the overall workflow is great. You can see an &lt;a href="http://codereview.appspot.com/"&gt;example&lt;/a&gt; project running on App Engine.&lt;/p&gt;
&lt;p&gt;My only complaint about Rivetld is that it was built for &lt;span class="caps"&gt;SVN&lt;/span&gt; and has poor integration with Git. See Gerrit.&lt;/p&gt;
&lt;h3&gt;Gerrit&lt;/h3&gt;
&lt;p&gt;Gerrit I am less familiar, I&amp;#8217;ve only tried the &lt;a href="http://android.git.kernel.org/?p=tools/gerrit.git;a=summary"&gt;demo&lt;/a&gt;. From what I can tell the UI is even more complicated, but the software itself seems cleverer and knows more about Git. I can&amp;#8217;t speak to the workflow.&lt;/p&gt;
&lt;h3&gt;Github&lt;/h3&gt;
&lt;p&gt;With &lt;a href="http://github.com/blog/712-pull-requests-2-0"&gt;Pull Requests 2.0&lt;/a&gt; Github is becoming a viable platform for formal code reviews. My opinion is that their tools aren&amp;#8217;t quite ready yet but they may be in the future. Missing features: inline commenting on diffs, ability to shorten the list of reviewers (you don&amp;#8217;t always want everyone on the project reviewing changes), ability for individual reviewers to mark changesets as resolved, and a Merge! buton. With a few more features, Github really could be the best of the bunch.&lt;/p&gt;
&lt;h2&gt;Ending&lt;/h2&gt;
&lt;p&gt;There is often talk in the Ruby community of deploying code dozens of times per day, supporting Agile development or Extreme programming, realeasing early and often, etc. You hear less talk about code quality and maintainability, which are the two main benefits of formal code review.&lt;/p&gt;
&lt;p&gt;For the reasons mentioned above, code making it into your project will be of higher quality and higher maintainability. The second point, maintainability, is especially important as the size of your development team grows. When the size of a development team gets above 3, and especially as it enters the double digits, code begins to move very fast. A lot of code will be committed to the project on any given day. Development at that pace is hard to track, and quality/maintainability is left up to the programmer writing the code.&lt;/p&gt;
&lt;p&gt;By implementing formal code review you can spread some of that workload. Make sure that a new feature going into your project gets a thorough review by more than just the programmer who wrote it. Like me, you&amp;#8217;ll come to enjoy reading and reviewing code almost as much as you enjoy writing it.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/3Ya6d0bYm0gYgLBr2jAfQbPZVYs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3Ya6d0bYm0gYgLBr2jAfQbPZVYs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/3Ya6d0bYm0gYgLBr2jAfQbPZVYs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3Ya6d0bYm0gYgLBr2jAfQbPZVYs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/QGcWpF6n138" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/ruby/2010/09/30/you-should-be-doing-formal-code-review.html</feedburner:origLink></entry>
 
 <entry>
   <title>Why the Shopify Platform is a Big Deal for Developers</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/nFiEpy5aBXc/why-the-shopify-platform-is-a-big-deal-for-developers.html" />
   <updated>2010-02-09T00:00:00-05:00</updated>
   <id>http://jstorimer.com/shopify/2010/02/09/why-the-shopify-platform-is-a-big-deal-for-developers</id>
   <content type="html">&lt;p&gt;Where I give three reasons why the Shopify platform is a big deal for developers and two reasons why it hasn&amp;#8217;t caught on (yet). In doing so I will compare the Shopify platform to other, somewhat similar, platforms, namely the Facebook developers program and the Apple App Store.&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/partners.png" class="left-img" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;If you are not familiar with the Shopify Platform, here is a good introduction from &lt;a href="http://twitter.com/tobi"&gt;@tobi&lt;/a&gt;: &lt;a href="http://blog.leetsoft.com/2009/6/2/so-about-this-shopify-platform"&gt;The Shopify platform&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; I work at Shopify.&lt;/p&gt;
&lt;h2&gt;Unique market&lt;/h2&gt;
&lt;p&gt;The Shopify platform provides a unique market that hasn&amp;#8217;t ever been more easily exposed. Let me explain with some examples.&lt;/p&gt;
&lt;p&gt;&lt;span class='strong'&gt;Facebook&lt;/span&gt;: The Facebook developers program gives an application developer access to a massive market. I forget the current numbers but Facebook has something like 300 million users, each one a potential user of your application. However, Facebook is a &lt;span class='strong'&gt;free service&lt;/span&gt;. It provides a lot of value at no charge. The challenge for a Facebook application is trying to convince its users that it is providing a service valuable enough to warrant payment, even if that compensation is not very high, it can be subsisted with the sheer volume of users for your application.&lt;/p&gt;
&lt;p&gt;&lt;span class='strong'&gt;Apple&lt;/span&gt;: Apple&amp;#8217;s App Store provides access to a large market of paying customers. iPhone users are paying customers (albeit of some terrible service provider) and had to pay for the iPhone, and there are a lot of iPhone users, again I don&amp;#8217;t have numbers, but those things are everywhere. Apple &lt;a href="http://www.apple.com/pr/library/2009/09/28appstore.html"&gt;has proved&lt;/a&gt; that people are willing to pay for iPhone applications. However, and I&amp;#8217;ll bet this is true if you ask any iPhone user, most App Store purchases are made on a whim. An application provides a &lt;span class='strong'&gt;novel concept&lt;/span&gt; and warrants a one-time $1 purchase. However if that application instead required recurring billing, I have a feeling that most purchases wouldn&amp;#8217;t last past the first month.&lt;/p&gt;
&lt;p&gt;&lt;span class='strong'&gt;Shopify&lt;/span&gt;: The Shopify platform, at first glance, offers a less lucrative market. There are orders of magnitude fewer potential users. Shopify currently boasts approximately 5,000 active sellers, this is your potential user base. However, unlike Facebook, every Shopify user is a paying customer and most are paying significant monthly fees. And unlike iPhone users, Shopify users are typically using this service to power their business and personal income. Shopify has gone to the trouble of filtering out users who are willing to pay for online services, and they are offering developers, through the Shopify platform, the chance to sell their online service to these users.&lt;/p&gt;
&lt;p&gt;Unlike the App Store, Shopify users are unlikely to purchase a novel application on a whim. Rather, they will be willing to pay good money for an application that will &lt;span class='strong'&gt;drive their business&lt;/span&gt;. If you come up with an application that lets them process their orders faster, thereby providing better customer service, or increase sales then it seems likely that users will be willing to pay, and continue to pay every month, for a service providing that.&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/platform.jpeg" class="right-img" alt="" /&gt;&lt;/p&gt;
&lt;h2&gt;Simplicity of getting started&lt;/h2&gt;
&lt;p&gt;It&amp;#8217;s very simple to get started with the Shopify platform. Especially if you are a Ruby on Rails developer. There is a &lt;a href="http://github.com/Shopify/shopify_app"&gt;Rails plugin&lt;/a&gt; that you can install that gets you up and running very fast. The plugin handles the Shopify platform &lt;a href="http://api.shopify.com/authentication.html"&gt;authentication scheme&lt;/a&gt; for you, it also provides a simple ActiveResource &lt;span class="caps"&gt;API&lt;/span&gt; to access Shopify stores.&lt;/p&gt;
&lt;p&gt;I don&amp;#8217;t want to show any code examples because the power of the &lt;span class="caps"&gt;API&lt;/span&gt; is that its implemented as with a &lt;span class="caps"&gt;REST&lt;/span&gt; interface as &lt;span class="caps"&gt;XML&lt;/span&gt; over &lt;span class="caps"&gt;HTTP&lt;/span&gt;, so can be accessed from any programming language: Ruby, Python, &lt;span class="caps"&gt;PHP&lt;/span&gt;, Objective-C, etc. You can check out the &lt;a href="http://api.shopify.com"&gt;&lt;span class="caps"&gt;API&lt;/span&gt; docs&lt;/a&gt; to see some sample &lt;span class="caps"&gt;HTTP&lt;/span&gt; requests/responses and there is also a &lt;a href="http://jmacaulay.net/blogs/main/1130012-got-8-minutes-put-a-shopify-app-online"&gt;screencast&lt;/a&gt; showing how to get up and running with a Rails app.&lt;/p&gt;
&lt;p&gt;A real strength of the &lt;span class="caps"&gt;API&lt;/span&gt; is the simple, yet flexible, &lt;a href="http://api.shopify.com/billing.html"&gt;Billing system&lt;/a&gt;. The Apple App Store has very simple pricing, you fill in a form that lists your price, they go to the trouble of collecting the money, storing/charging the credit cards, and so on, then you get 70% of that. The Shopify Billing &lt;span class="caps"&gt;API&lt;/span&gt; is similar, except you create the charges for your application programatically, in your code, rather than in a form field.&lt;/p&gt;
&lt;p&gt;This opens up whole new billing avenues for your application. Rather than charging every customer the same amount when they install the app, you have a lot of choices. Want to provide a beta period? Trial accounts? Charges based on the number of products that a merchant has? Based on how much the merchant is paying Shopify? Multiple subscription plans? This is all possible, and even simple, with the Shopify Billing &lt;span class="caps"&gt;API&lt;/span&gt;. Just like Apple, Shopify handles the storage of credit cards, collection of money, and you get 80% of your charges. The Shopify Billing &lt;span class="caps"&gt;API&lt;/span&gt; even provides a little more sugar than that, things such as &lt;a href="http://api.shopify.com/billing.html"&gt;upgrading/downgrading&lt;/a&gt; subscription plans is built into the &lt;span class="caps"&gt;API&lt;/span&gt; and the logic for pro-rating plan changes is handled by Shopify!&lt;/p&gt;
&lt;h2&gt;Ease of marketing&lt;/h2&gt;
&lt;p&gt;I won&amp;#8217;t spend too much time talking about this point. Shopify provides the same kind of marketing as Facebook and Apple. Your application will be listed for free in the &lt;a href="http://api.shopify.com/billing.html"&gt;Shopify App Store&lt;/a&gt;, which is integrated into the admin area of every Shopify customer. Your application may also be featured in the App Store, on the Shopify blog, etc. The Shopify App Store has support for reviews and categories to make your apps easier to find.&lt;/p&gt;
&lt;h2&gt;Problems&lt;/h2&gt;
&lt;p&gt;So why hasn&amp;#8217;t the Shopify App Store taken off yet? Why isn&amp;#8217;t everyone jumping on that wagon?&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/bread.jpg" class="right-img" alt="" /&gt;&lt;/p&gt;
&lt;h2&gt;Problem: Shopify Developers aren&amp;#8217;t Shopify Users&lt;/h2&gt;
&lt;p&gt;This is a problem that Facebook and Apple don&amp;#8217;t have. Undoubtedly, Every Facebook developer is a Facebook user, they know how the software works and they know how people are using it. The same is true of the iPhone, anyone developing apps for the iPhone is an iPhone user. They have one of these devices and they know the ins and outs of the device, the expected behaviour of the interface, how much apps typically cost, and so on.&lt;/p&gt;
&lt;p&gt;Conversely, very few software developers also happen to be Shopify merchants. Sure, there must be some crossover, but most software developers won&amp;#8217;t know what it&amp;#8217;s like to run an online store. This is a stumbling block for developers to get started with the Shopify platform. For example, an iPhone user, in the process of using their iPhone, may find a problem that an app could solve, so they can go and write this app, put it on the App Store, and make a buck. However, since most developers aren&amp;#8217;t also going to be users of Shopify, this process isn&amp;#8217;t really possible.&lt;/p&gt;
&lt;p&gt;I was lucky enough to attend &lt;a href="http://futureruby.com/"&gt;FutureRuby&lt;/a&gt; this past July and had several conversations with developers about this very topic. They had heard of the Shopify platform and could see the benefits, however they didn&amp;#8217;t know what kinds of apps Shopify users were looking for. These developers weren&amp;#8217;t e-commerce merchants themselves, so they didn&amp;#8217;t know where to begin when thinking about contributing to the Shopify platform.&lt;/p&gt;
&lt;p&gt;A possible solution to this problem might be having Shopify app developers work closely with specific merchants to build an app that that a particular merchant might find useful and, most likely, other merchants would find useful. Any developers interested in this approach should probably start by looking around the &lt;a href="http://forums.shopify.com"&gt;Shopify forums&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Problem: Lack of a Killer App to Lead the Way&lt;/h2&gt;
&lt;p&gt;The Apple App Store has done a great job in this area. Stories &lt;a href="http://www.pcworld.com/article/185276/tapulous_we_make_1_million_a_month_from_app_store.html"&gt;abound&lt;/a&gt; of small developer shops, usually a team of 2-3, pulling in a hundred thousand, or even a million, dollars per month from their iPhone apps. Then there is the &lt;a href="http://www.mobileorchard.com/podcast-interview-with-hampton-catlin/"&gt;story of iWik&lt;/a&gt;, the wikipedia browser, selling 50,000 copies in its first week after just a few days of development.&lt;/p&gt;
&lt;p&gt;The Shopify App Store isn&amp;#8217;t without its success stories however. &lt;a href="http://fetchapp.com"&gt;Fetch&lt;/a&gt;, an application helping you sell digital goods, has been going strong for 3 years now with many &lt;a href="http://apps.shopify.com/shopify_applications/f7f77e1ad1ee85d899b9e0ee0dd0d846"&gt;happy customers&lt;/a&gt;. There is also the &lt;a href="http://www.shopify.com/press/shopify-acquires-mndcreative/"&gt;story of MNDCreative&lt;/a&gt; releasing an iPhone app that integrates with Shopify. That company was acquired by Shopify and is now leading mobile development there.&lt;/p&gt;
&lt;p&gt;So the Shopify platform already has several success stories. None of them are yet big enough to really inspire others to jump on the bandwagon, but I think it&amp;#8217;s just a matter of time.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/slP1SOpIaSzToalC68GPtMtEO5A/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/slP1SOpIaSzToalC68GPtMtEO5A/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/slP1SOpIaSzToalC68GPtMtEO5A/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/slP1SOpIaSzToalC68GPtMtEO5A/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/nFiEpy5aBXc" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/shopify/2010/02/09/why-the-shopify-platform-is-a-big-deal-for-developers.html</feedburner:origLink></entry>
 
 <entry>
   <title>delayed_paperclip</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/G-0-E4S_MM0/delayed-paperclip.html" />
   <updated>2010-01-30T00:00:00-05:00</updated>
   <id>http://jstorimer.com/ruby/2010/01/30/delayed-paperclip</id>
   <content type="html">&lt;p&gt;Delayed_paperclip is a &lt;a href="http://gemcutter.org/gems/delayed_paperclip"&gt;rubygem&lt;/a&gt; that works with &lt;a href="http://github.com/thoughtbot/paperclip"&gt;Paperclip&lt;/a&gt; and &lt;a href="http://github.com/tobi/delayed_job"&gt;delayed_job&lt;/a&gt;. It allows you to easily process Paperclip attachments (such as resizing images) in the background with delayed_job.&lt;/p&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;Install the gem:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;sudo gem install delayed_paperclip
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Add it to your environment.rb:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;delayed_paperclip&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Or, even better, to your Gemfile:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;http://gemcutter.org&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;delayed_paperclip&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Dependencies: Paperclip &amp;amp;&amp;amp; delayed_job&lt;/p&gt;
&lt;h2&gt;Source&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://github.com/jstorimer/delayed_paperclip"&gt;http://github.com/jstorimer/delayed_paperclip&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Usage&lt;/h2&gt;
&lt;p&gt;Make sure that you have DJ up and running.&lt;/p&gt;
&lt;p&gt;In your model:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
    &lt;span class="n"&gt;has_attached_file&lt;/span&gt; &lt;span class="ss"&gt;:avatar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:styles&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:medium&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;300x300&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:thumb&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;100x100&amp;gt;&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    
    &lt;span class="n"&gt;process_in_background&lt;/span&gt; &lt;span class="ss"&gt;:avatar&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Use your Paperclip attachment just like always in controllers and views.&lt;/p&gt;
&lt;h2&gt;Motivation&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://therailsway.com/2009/7/22/do-it-later-with-delayed-job"&gt;Every&lt;/a&gt; &lt;a href="http://github.com/tobi/delayed_job"&gt;resource&lt;/a&gt; that talks about background processing seems to mention typical tasks that should be handled in the background. Image resizing is always one of these tasks.&lt;/p&gt;
&lt;p&gt;It makes perfect sense because you want the user experience to be fast, they shouldn&amp;#8217;t be waiting while you resize images and upload them to s3. DJ should pick up and process the job almost immediately anyway, so its win-win.&lt;/p&gt;
&lt;p&gt;I have used Paperclip on a number of projects now and have never processed my images in the background (I&amp;#8217;m sure I&amp;#8217;m not the only one). There were a few guides out there with instructions on how to add the right callbacks and methods to your model to resize your images in the background, but I wanted something simpler, so I wrote this gem.&lt;/p&gt;
&lt;h2&gt;In the Wild&lt;/h2&gt;
&lt;p&gt;The project that I wrote this gem has a form that allows users to upload screenshots and dynamically add more screenshot upload fields. I did some benchmarks with this form with and without using this gem.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Specs&lt;/strong&gt;: The project is running on Heroku and using s3 for file storage. I tested the gem by uploading 6 screenshots, each has 3 different styles.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Without&lt;/em&gt; using this gem, it took the server 8.5 seconds to process the form and images. Let&amp;#8217;s think about the operations for a second here. There were 6 screenshots, each of those had to be resized to three different sizes. Then each of those image styles, plus the original, were uploaded to s3, that makes for 6 &amp;#215; 4 = 24 s3 uploads, all while the user is waiting for the form to submit.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;With&lt;/em&gt; this gem the server tool only 1.2 seconds to process the form and images. Let&amp;#8217;s look at the operations again. There were again 6 screenshots, this time there was no resizing going on. Then each of the original images was uploaded to s3, so a total of 6 uploads to s3. Meanwhile we can present the next page to the user 7 seconds faster, in this case, 1/8 of the time.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/UyfY5AFbDQz4MzRbfvI-gLU_dbE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UyfY5AFbDQz4MzRbfvI-gLU_dbE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/UyfY5AFbDQz4MzRbfvI-gLU_dbE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UyfY5AFbDQz4MzRbfvI-gLU_dbE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/G-0-E4S_MM0" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/ruby/2010/01/30/delayed-paperclip.html</feedburner:origLink></entry>
 
 <entry>
   <title>Using Mutt with Gmail on OSX</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/02pBZ80pbgY/using-mutt-with-gmail-on-osx.html" />
   <updated>2010-01-19T00:00:00-05:00</updated>
   <id>http://jstorimer.com/shells/2010/01/19/using-mutt-with-gmail-on-osx</id>
   <content type="html">&lt;h2&gt;What?&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Mutt&lt;/code&gt; is a command-line email client whose motto is &amp;#8220;All mail clients suck. This one just sucks less&amp;#8221;. Basically it brings GMail to your Terminal. You can find more information on their &lt;a href="http://www.mutt.org/"&gt;site&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Why?&lt;/h2&gt;
&lt;p&gt;1. Lately I&amp;#8217;ve had a bit of an obsession with command line tools. So the fact that &lt;code&gt;mutt&lt;/code&gt; gives me command line access to my mail piqued my interest immediately :)&lt;/p&gt;
&lt;p&gt;2. I&amp;#8217;ve always wanted tab-completion while writing emails, they are a repetitive medium. But GMail never offered that. With &lt;code&gt;mutt&lt;/code&gt; I set TextMate to be my editor so I now write email messages in TextMate, which does have tab(escape) completion.&lt;/p&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;Install &lt;code&gt;mutt&lt;/code&gt; from your favourite package management system.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="c"&gt;# Homebrew&lt;/span&gt;
brew install mutt

&lt;span class="c"&gt;# MacPorts&lt;/span&gt;
sudo port install mutt
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2&gt;Customization&lt;/h2&gt;
&lt;p&gt;You will need to create a &lt;code&gt;~/.muttrc&lt;/code&gt; with your specific &lt;code&gt;mutt&lt;/code&gt; configuration. This is the minimum required to get &lt;code&gt;mutt&lt;/code&gt; working.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="c"&gt;# ~/.muttrc&lt;/span&gt;
&lt;span class="nb"&gt;set &lt;/span&gt;&lt;span class="nv"&gt;imap_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;user@gmail.com&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;set &lt;/span&gt;&lt;span class="nv"&gt;imap_pass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;password&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;set &lt;/span&gt;&lt;span class="nv"&gt;spoolfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; imaps://imap.gmail.com:993/INBOX
&lt;span class="nb"&gt;set &lt;/span&gt;&lt;span class="nv"&gt;folder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; imaps://imap.gmail.com:993
&lt;span class="nb"&gt;set &lt;/span&gt;&lt;span class="nv"&gt;postponed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;”imaps://imap.gmail.com/&lt;span class="o"&gt;[&lt;/span&gt;Gmail&lt;span class="o"&gt;]&lt;/span&gt;/Drafts”
&lt;span class="nb"&gt;set &lt;/span&gt;&lt;span class="nv"&gt;message_cachedir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;”~/.mutt/cache/bodies”
&lt;span class="nb"&gt;set &lt;/span&gt;&lt;span class="nv"&gt;certificate_file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/.mutt/certificates
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You need to make sure that the &lt;code&gt;~/.mutt&lt;/code&gt; directories actually exist in order to mitigate funny certificate errors. If you want to know what other options are available you can check out &lt;a href="http://gist.github.com/281158"&gt;my .muttrc&lt;/a&gt; or the &lt;a href="http://wiki.mutt.org/index.cgi?ConfigList"&gt;mutt docs&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Opening URLs&lt;/h2&gt;
&lt;p&gt;Since &lt;code&gt;mutt&lt;/code&gt; is a command line tool, you can&amp;#8217;t click links in your emails. You will need &lt;a href="http://linuxcommand.org/man_pages/urlview1.html"&gt;urlview&lt;/a&gt; in order to open URLs in emails. You will need to install &lt;code&gt;urlview&lt;/code&gt; from source and apply a patch for Snow Leopard.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;wget ftp://ftp.guug.de/pub/mutt/contrib/urlview-0.9.tar.gz
tar xvzf urlview-0.9.tar.gz
&lt;span class="nb"&gt;cd &lt;/span&gt;urlview-0.9
./configure
&lt;span class="c"&gt;# apply the patch found here http://blog.joelesler.net/2009/12/getting-urlview-to-work-on-snow-leopard.html&lt;/span&gt;
make
make install
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;To open URLs in your default browser you need to create a &lt;code&gt;~/.urlview&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="c"&gt;# ~/.urlview&lt;/span&gt;
COMMAND open %s
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This tells &lt;code&gt;mutt&lt;/code&gt; to use the &lt;code&gt;open&lt;/code&gt; command on URLs, %s is a placeholder for the &lt;span class="caps"&gt;URL&lt;/span&gt;. Now, when reading an email in &lt;code&gt;mutt&lt;/code&gt;, press &lt;code&gt;&amp;lt;Ctrl&amp;gt;-b&lt;/code&gt; to see a list of links in the message and use your arrow keys and enter to select one.&lt;/p&gt;
&lt;h2&gt;&lt;span class="caps"&gt;HTML&lt;/span&gt; emails&lt;/h2&gt;
&lt;p&gt;You may quickly notice that by default &lt;code&gt;mutt&lt;/code&gt; prints out the source of &lt;span class="caps"&gt;HTML&lt;/span&gt; emails, not very useful. It is true that everyone should be providing plain text email for command line lovers like us, but alas, some people are ignorant of this fact. In order to view &lt;span class="caps"&gt;HTML&lt;/span&gt; emails with &lt;code&gt;mutt&lt;/code&gt; just add this line to your &lt;code&gt;~/.muttrc&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="c"&gt;# ~/.muttrc&lt;/span&gt;
auto_view text/html
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2&gt;Cheating&lt;/h2&gt;
&lt;p&gt;I created a cheat sheet that has some common commands that you might use with &lt;code&gt;mutt&lt;/code&gt; to manage your GMail. You can see the sheet online or access from the command line with &lt;a href="http://cheat.errtheblog.com"&gt;cheat&lt;/a&gt;: &lt;code&gt;cheat mutt_gmail&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m still a beginning &lt;code&gt;mutt&lt;/code&gt; user (about 1 week), so I haven&amp;#8217;t yet explored all the nuances of the software. Particularly excited about looking into keyboard macros.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/LlUPk0PDIcIt3U5qfb_9iOkNeh0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LlUPk0PDIcIt3U5qfb_9iOkNeh0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/LlUPk0PDIcIt3U5qfb_9iOkNeh0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LlUPk0PDIcIt3U5qfb_9iOkNeh0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/02pBZ80pbgY" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/shells/2010/01/19/using-mutt-with-gmail-on-osx.html</feedburner:origLink></entry>
 
 <entry>
   <title>Speed Up Your Paperclip Tests</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/Vm3IfyD0n8I/speep-up-your-paperclip-tests.html" />
   <updated>2010-01-05T00:00:00-05:00</updated>
   <id>http://jstorimer.com/ruby/2010/01/05/speep-up-your-paperclip-tests</id>
   <content type="html">&lt;p&gt;We all love &lt;a href="http://github.com/thoughtbot/paperclip"&gt;Paperclip&lt;/a&gt;. One of the reasons why is that it makes it painless to resize images. Which is great when you are working in development or on production, but image resizing can really slow down your automated tests.&lt;/p&gt;
&lt;p&gt;For example, I was working on a project that used &lt;a href="http://github.com/nakajima/fixjour"&gt;factories&lt;/a&gt; instead of fixtures. Every time a factory object was created, which happened multiple times in most tests, Paperclip had to resize its images.&lt;/p&gt;
&lt;p&gt;I added this little snippet to my test_helper.rb and saw my total testing time go from 100 seconds to 30 seconds. Meaning that 2/3 of the time spent running tests was actually spent resizing images!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;# test/test_helper.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TestCase&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# replace the class name with one appropriate for your app&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Screenshot&lt;/span&gt;
  &lt;span class="n"&gt;before_post_process&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="kp"&gt;false&lt;/span&gt; &lt;span class="c1"&gt;# halts processing&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I&amp;#8217;m sure that there are some automated testing purists out there who will cry that this method no longer tests the entire stack. It&amp;#8217;s possible to not have ImageMagick installed on your system and still have passing tests. My answer to that is that any good testing strategy will involve an &lt;a href="http://blog.hamptoncatlin.com/2008/hampton-hates-automated-testing"&gt;element of human testing&lt;/a&gt; which should catch this kind of problem.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/UBRzxJ8y8wsrMCEtDUn3GaBmUhY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UBRzxJ8y8wsrMCEtDUn3GaBmUhY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/UBRzxJ8y8wsrMCEtDUn3GaBmUhY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UBRzxJ8y8wsrMCEtDUn3GaBmUhY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/Vm3IfyD0n8I" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/ruby/2010/01/05/speep-up-your-paperclip-tests.html</feedburner:origLink></entry>
 
 <entry>
   <title>Explanations</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/YEagoJIjzjw/explanations.html" />
   <updated>2009-12-30T00:00:00-05:00</updated>
   <id>http://jstorimer.com/quotes/2009/12/30/explanations</id>
   <content type="html">&lt;blockquote class="right-float"&gt;
&lt;p class="right-float"&gt;&amp;#8220;We teachers &amp;#8211; perhaps all human beings &amp;#8211; are in the grip of an astonishing delusion. We think that we can take a picture, a structure, a working model of something, constructed in our minds out of long experience and familiarity, and by turning that model into a string of words, transplant it whole into the mind of someone else. &lt;br /&gt;
&lt;br /&gt;Perhaps once in a thousand times, when the explanation is extraordinary good, and the listener extraordinary experienced and skillful at turning word strings into non-verbal reality, and when the explainer and listener share in common many of the experiences being talked about, the process may work, and some real meaning may be communicated. Most of the time, explaining does not increase understanding, and may even lessen it.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;mdash; &lt;a href="http://en.wikipedia.org/wiki/John_Holt_%28educator%29"&gt;John Holt&lt;/a&gt;, (1923-1985) American Educator, &lt;a href="http://www.amazon.com/exec/obidos/ASIN/0201484048/downandoutint-20"&gt;How Children Learn&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/fpAwWFQt2pPa4g3YxE0_ydXRvfE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fpAwWFQt2pPa4g3YxE0_ydXRvfE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/fpAwWFQt2pPa4g3YxE0_ydXRvfE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fpAwWFQt2pPa4g3YxE0_ydXRvfE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/YEagoJIjzjw" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/quotes/2009/12/30/explanations.html</feedburner:origLink></entry>
 
 <entry>
   <title>Jekyll on Heroku</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/z4PfvUjE-2Y/jekyll-on-heroku.html" />
   <updated>2009-12-29T00:00:00-05:00</updated>
   <id>http://jstorimer.com/2009/12/29/jekyll-on-heroku</id>
   <content type="html">&lt;p&gt;This blog is published using &lt;a href="http://github.com/mojombo/jekyll"&gt;Jekyll&lt;/a&gt;. Jekyll is a static site generator, so you write your posts and pages on your local machine, generate your static &lt;span class="caps"&gt;HTML&lt;/span&gt; site and then publish it using a service that serves static files. Like &lt;a href="http://github.com/blog/272-github-pages"&gt;GitHub Pages&lt;/a&gt; or Slicehost.&lt;/p&gt;
&lt;p&gt;But neither of those services are free, and my blog has nowhere near enough traffic that it should cost me money, so I wanted to use the free &lt;a href="http://heroku.com/"&gt;Heroku&lt;/a&gt; plan. This is the method I have been using to publish my blog for the past month.&lt;/p&gt;
&lt;script src="http://gist.github.com/265267.js"&gt;&lt;/script&gt;&lt;p&gt;Basically Heroku treats my blog like its a Sinatra app. When you hit the root of the application it serves the index.html from the _site/ folder, and then the links from that page take the user where they want to go.&lt;/p&gt;
&lt;h2&gt;Simplicity&lt;/h2&gt;
&lt;p&gt;I recently noticed that there is a project called &lt;a href="http://github.com/bry4n/rack-jekyll"&gt;rack-jekyll&lt;/a&gt; that is supposed to make it easy to publish your Jekyll site with Rack. I tried out this project and it failed miserably when trying to display my blog.&lt;/p&gt;
&lt;p&gt;The method here is much simpler. The nice thing about the fact that this is a Sinatra app is that you have some built in niceties. Want custom 404 pages? Sinatra &lt;a href="http://www.sinatrarb.com/api/classes/Sinatra/Helpers.html#M000013"&gt;has that&lt;/a&gt;. Need to demonstrate some dynamically generated code? Just set up another route and go right ahead.&lt;/p&gt;
&lt;h2&gt;Local Development&lt;/h2&gt;
&lt;p&gt;Use the &lt;code&gt;jekyll --auto --server&lt;/code&gt; command to develop locally.&lt;/p&gt;
&lt;h2&gt;Deploying&lt;/h2&gt;
&lt;p&gt;To deploy your jekyll site to Heroku:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Make sure that your _site/ folder is not in the .gitignore file.&lt;/li&gt;
	&lt;li&gt;Add the two files from the gist above.&lt;/li&gt;
	&lt;li&gt;Commit changes.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;heroku create&lt;/code&gt; (first time around)&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;git push heroku master&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/xY-gXz3T8eRM5HJtBC8AwOX9xGo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xY-gXz3T8eRM5HJtBC8AwOX9xGo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/xY-gXz3T8eRM5HJtBC8AwOX9xGo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xY-gXz3T8eRM5HJtBC8AwOX9xGo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/z4PfvUjE-2Y" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2009/12/29/jekyll-on-heroku.html</feedburner:origLink></entry>
 
 <entry>
   <title>Notes on git pushing</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/tjFYQ4Ko3hU/notes-on-git-pushing.html" />
   <updated>2009-12-27T00:00:00-05:00</updated>
   <id>http://jstorimer.com/git/2009/12/27/notes-on-git-pushing</id>
   <content type="html">&lt;h2&gt;Pushing all local branches&lt;/h2&gt;
&lt;p&gt;Executing&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;git push
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;will update all local branches that are tracking remote branches. For example, if you have set up your local &lt;code&gt;master&lt;/code&gt; branch to track the remote &lt;code&gt;origin master&lt;/code&gt; branch, then executing &lt;code&gt;git push&lt;/code&gt; will update that branch. More on tracking remote branches &lt;a href="http://www.gitready.com/beginner/2009/03/09/remote-tracking-branches.html"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Pushing the current local branch&lt;/h2&gt;
&lt;p&gt;Say you are working in your local master branch and want to push your changes, but don&amp;#8217;t want to update all branches. You can run the &lt;code&gt;git push&lt;/code&gt; command, passing in the remote and the name of the branch you want to update:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;git push origin master
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img src="http://farm4.static.flickr.com/3451/3233621766_e4f6db7a22.jpg" alt="" /&gt;&lt;/p&gt;
&lt;h2&gt;Pushing to a named remote branch&lt;/h2&gt;
&lt;p&gt;So, what if have changes in your &lt;code&gt;master&lt;/code&gt; branch that you want to push to the remote &lt;code&gt;experimental&lt;/code&gt; branch? You could checkout your &lt;code&gt;experimental&lt;/code&gt; branch, cherry pick the changes and then use the method above to push those changes, but that&amp;#8217;s no fun.&lt;/p&gt;
&lt;p&gt;You can actually specify that you want to push your changes to some branch with a different name than the one you are working on with something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;git push &amp;lt;remote&amp;gt; &amp;lt;from&amp;gt;:&amp;lt;to&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In our example we would fill in the blanks like so:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;git push origin master:experimental
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This tells git to push the changes from your local &lt;code&gt;master&lt;/code&gt; branch to the remote &lt;code&gt;experimental&lt;/code&gt; branch. And we didn&amp;#8217;t even need to write /refs/heads anywhere ;)&lt;/p&gt;
&lt;h2&gt;Deleting remote branches&lt;/h2&gt;
&lt;p&gt;I discovered a while ago the way to delete remote branches. For example, if we wanted to delete our remote experimental branch we would issue this command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;git push origin :experimental
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;At first I was thinking &amp;#8216;Wow! That looks really dumb and makes no sense.&amp;#8217; But, if you look at the above section it makes perfect sense. Think of it this way:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;git push origin &amp;lt;nothing&amp;gt;:experimental
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It&amp;#8217;s as if we are pushing nothing into the &lt;code&gt;experimental&lt;/code&gt; branch. The same way we pushed the &lt;code&gt;master&lt;/code&gt; branch into the &lt;code&gt;experimental&lt;/code&gt; branch above.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://farm1.static.flickr.com/10/11250506_58dee63095.jpg" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/cZraxBMep_dqdeekroBF5A8Fq4w/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/cZraxBMep_dqdeekroBF5A8Fq4w/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/cZraxBMep_dqdeekroBF5A8Fq4w/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/cZraxBMep_dqdeekroBF5A8Fq4w/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/tjFYQ4Ko3hU" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/git/2009/12/27/notes-on-git-pushing.html</feedburner:origLink></entry>
 
 <entry>
   <title>Essential Rails Plugins for your Inner DBA</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/vl7X3eu1js0/essential-rails-plugins-for-your-inner-dba.html" />
   <updated>2009-12-13T00:00:00-05:00</updated>
   <id>http://jstorimer.com/ruby/2009/12/13/essential-rails-plugins-for-your-inner-dba</id>
   <content type="html">&lt;p&gt;&lt;img src="http://rlv.zcache.com/mommys_little_database_administrator_tshirt-p235769961119195408qm73_400.jpg" class="left-img" alt="" /&gt;&lt;/p&gt;
&lt;p class='intro drop'&gt;&lt;strong&gt;I&lt;/strong&gt; like to think that I&amp;#8217;m not bad at writing &lt;span class="caps"&gt;SQL&lt;/span&gt;. When it comes to writing complex queries, joinging tables, grouping columns, sorting, I&amp;#8217;m quite comfortable.&lt;/p&gt;
&lt;p&gt;However I never seem to give any thought to the possible size of the tables I am working with. Are there hundreds of records? Hundreds of thousands? Millions? This is usually not an issue for local development, however once your app is out in the wild, this is a big issue.&lt;/p&gt;
&lt;p&gt;Recently, I have been using two awesome Rails plugins to &lt;em&gt;remind&lt;/em&gt; me to not forget these things.&lt;/p&gt;
&lt;h2&gt;Query Reviewer&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://github.com/dsboulder/query_reviewer"&gt;http://github.com/dsboulder/query_reviewer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This plugin is great. Basically it adds a js widget to all your pages that runs the &lt;span class="caps"&gt;EXPLAIN&lt;/span&gt; command on each of your queries and lets you know if any warnings were generated.&lt;/p&gt;
&lt;p&gt;Just install the plugin and it will be working by default in your development environment. For each problem query, the Query reviewer widget will tell you what the problem is, ie. &amp;#8216;No index was used. Performed full table scan&amp;#8217;, &amp;#8216;A temporary table had to be used&amp;#8217;, etc.&lt;/p&gt;
&lt;p&gt;Here is an example where you need to fix something, adding an index in this case.&lt;br /&gt;
&lt;img src="http://img.skitch.com/20091213-e6ay7ba84r9pgbrehinaensn1g.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s where you hope to get to:&lt;br /&gt;
&lt;img src="http://img.skitch.com/20091213-cn46ex86es8j63qcyquapnask9.png" alt="" /&gt;&lt;/p&gt;
&lt;h2&gt;Bullet&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://github.com/flyerhzm/bullet"&gt;http://github.com/flyerhzm/bullet&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This library detects N+1 queries and unused eager loading. Again, something that you probably wouldn&amp;#8217;t notice in a development environment but can become very important in a production environment.&lt;/p&gt;
&lt;p&gt;For me this is even more important because I am beginning to understand &lt;span class="caps"&gt;SQL&lt;/span&gt; indexes and where they should be used, but eager loading still escapes me at most junctions.&lt;/p&gt;
&lt;p&gt;For Bullet, you need to add some config code to your development environment. By default it logs problems to the Rails log, as well as giving you a js alert. You can even get this thing working with Growl, if you&amp;#8217;re into that kind of thing.&lt;/p&gt;
&lt;p&gt;Here is an example of its output, its pretty smart with its suggestions:&lt;br /&gt;
&lt;img src="http://img.skitch.com/20091213-ruaqh5nb8e6mgq9b34386qdybu.png" alt="" /&gt;&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;These plugins are a great way to catch database optimizations that you might have missed. However, these &lt;em&gt;suggestions&lt;/em&gt; should be taken with a grain of salt. Much like code metrics, they can only go so far. You know your app better than these tools and in some cases it may be the right decision to ignore them.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/teCX9tojkFHRjRUggO-fSxyNlBA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/teCX9tojkFHRjRUggO-fSxyNlBA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/teCX9tojkFHRjRUggO-fSxyNlBA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/teCX9tojkFHRjRUggO-fSxyNlBA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/vl7X3eu1js0" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/ruby/2009/12/13/essential-rails-plugins-for-your-inner-dba.html</feedburner:origLink></entry>
 
 <entry>
   <title>Installing rb-gsl on Snow Leopard</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/FmpxIExL6hM/installing-rb-gsl-on-snow-leopard.html" />
   <updated>2009-10-18T00:00:00-04:00</updated>
   <id>http://jstorimer.com/ruby/2009/10/18/installing-rb-gsl-on-snow-leopard</id>
   <content type="html">&lt;p&gt;I wanted to try experimenting with &lt;span class="caps"&gt;SVD&lt;/span&gt; recommenders in Ruby (via this fantastic blog post &lt;a href="http://www.igvita.com/2007/01/15/svd-recommendation-system-in-ruby/"&gt;http://www.igvita.com/2007/01/15/svd-recommendation-system-in-ruby/&lt;/a&gt;) and was having a hell of a time trying to install Ruby&amp;#8217;s linalg. When I saw that there was also an example using rb-gsl, I was thrilled because rb-gsl is available from MacPorts. No problem, right? Wrong!&lt;/p&gt;
&lt;p&gt;Currently if you try to install rb-gsl form MacPorts (on Snow Leopard) you will get a build error. If you download the latest release of rb-gsl (1.10.3 at the time of this writing) you will get the same build error. It appears to have some code that doesn&amp;#8217;t work on Snow Leopard. Here is how I got it installed.&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;If you haven&amp;#8217;t already, install MacPorts for Snow Leopard (&lt;a href="http://forums.macrumors.com/showthread.php?t=720035"&gt;http://forums.macrumors.com/showthread.php?t=720035&lt;/a&gt;)&lt;/li&gt;
	&lt;li&gt;Install the &lt;span class="caps"&gt;GSL&lt;/span&gt; library&lt;br /&gt;
&lt;code&gt;$ sudo port install gsl plotutils&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;Because of the incompatibility of the current rb-gsl and Snow Leopard, you will have to install from the latest svn checkout.&lt;br /&gt;
&lt;code&gt;$ svn checkout svn://rubyforge.org/var/svn/rb-gsl&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;$ cd rb-gsl/trunk/rb-gsl&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;$ sudo ruby setup.rb config --prefix=/usr/local&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;Then we need to edit two lines in the generated ext/Makefile&lt;/li&gt;
	&lt;li&gt;Open up the file for editing and change these two lines to look like this:&lt;br /&gt;
&lt;code&gt;DLDFLAGS = -L.&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;LDSHARED = $(CC) -pipe -bundle -undefined dynamic_lookup&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;Then continue with the build and you should be on your way&lt;br /&gt;
&lt;code&gt;$ sudo ruby setup.rb setup&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;$ sudo ruby setup.rb install&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
&lt;p&gt;If you are installing this lib to test out the example from &lt;a href="http://www.igvita.com/2007/01/15/svd-recommendation-system-in-ruby/"&gt;above&lt;/a&gt; then you may want to check out &lt;a href="http://www.igvita.com/2007/01/15/svd-recommendation-system-in-ruby/comment-page-2/#comment-220841"&gt;my comment&lt;/a&gt; on that article.&lt;/p&gt;
&lt;p&gt;Sources:&lt;br /&gt;
&lt;a href="http://rubyforge.org/forum/forum.php?thread_id=19389&amp;amp;forum_id=1225"&gt;http://rubyforge.org/forum/forum.php?thread_id=19389&amp;amp;forum_id=1225&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://rubyforge.org/forum/forum.php?thread_id=45613&amp;amp;forum_id=1225"&gt;http://rubyforge.org/forum/forum.php?thread_id=45613&amp;amp;forum_id=1225&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Ru0M0Lwcg-W8gaCCfPZUgxH-fE0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Ru0M0Lwcg-W8gaCCfPZUgxH-fE0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Ru0M0Lwcg-W8gaCCfPZUgxH-fE0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Ru0M0Lwcg-W8gaCCfPZUgxH-fE0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/FmpxIExL6hM" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/ruby/2009/10/18/installing-rb-gsl-on-snow-leopard.html</feedburner:origLink></entry>
 
 <entry>
   <title>Sinatra and Shopify: A Classy shopifyapp</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/f6u6DYWnuE8/sinatra-and-shopify-a-classy-shopify_app.html" />
   <updated>2009-06-20T00:00:00-04:00</updated>
   <id>http://jstorimer.com/shopify/2009/06/20/sinatra-and-shopify-a-classy-shopify_app</id>
   <content type="html">&lt;p&gt;This week I wrote up a basic sinatra app that allows you to work with the &lt;a href="http://shopify.com/developers"&gt;Shopify &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt;. It&amp;#8217;s basically just a port of the &lt;a href="http://github.com/Shopify/shopify_app"&gt;shopify_app&lt;/a&gt; rails plugin to sinatra.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://apps.shopify.com"&gt;&lt;img src="http://blog.leetsoft.com/assets/2009/6/2/THUMB-dimitri3.jpg.jpeg" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Why?&lt;/h2&gt;
&lt;p&gt;I have been &lt;a href="http://www.jstorimer.com/blogs/my-blog/1133402-shopify-api-extensions"&gt;having fun working on Shopify apps&lt;/a&gt; lately, but I needed a simpler way than always generating a new rails app, new controllers, etc., for every little idea.&lt;/p&gt;
&lt;p&gt;Rails is great, but most of the &lt;a href="http://apps.shopify.com"&gt;Shopify apps&lt;/a&gt; that I have come up with are one page apps, maybe two or three pages. The point is, I don&amp;#8217;t need a controller for that, I don&amp;#8217;t need the 63 files or however many the rails generator generates for me.&lt;/p&gt;
&lt;p&gt;Sinatra is most awesome when you are working on a small app with just a few routes. You can clone this app and use it as a starting point for a shopify_app. All of the authentication logic/routes are in the lib folder, so they don&amp;#8217;t pollute the code of your app.&lt;/p&gt;
&lt;p&gt;So in app.rb, you just have to worry about the functionality of your app.&lt;/p&gt;
&lt;h2&gt;Usage&lt;/h2&gt;
&lt;p&gt;The fastest way to get this thing running:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;git clone git://github.com/jstorimer/sinatra-shopify&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;cd sinatra-shopify&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;heroku create&lt;/code&gt; (make sure that you remember the name of your app as you will need that later)&lt;/li&gt;
	&lt;li&gt;visit the &lt;a href="http://app.shopify.com/services/partners"&gt;Shopify Partners area&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Sign up for an account if you don&amp;#8217;t already have one&lt;/li&gt;
	&lt;li&gt;Log in to your Shopify partners account&lt;/li&gt;
	&lt;li&gt;Create a new application.&lt;/li&gt;
	&lt;li&gt;Make sure that the Callback &lt;span class="caps"&gt;URL&lt;/span&gt; is set to http://&lt;em&gt;yourapp&lt;/em&gt;.heroku.com/login/finalize&lt;/li&gt;
	&lt;li&gt;In the lib/sinatra/shopify.yml file replace API_KEY and &lt;span class="caps"&gt;SECRET&lt;/span&gt; with the Api Key and Secret that you just got from the Shopify Partners area&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;git push heroku master&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;heroku open&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The current implementation for authentication is to add the &lt;code&gt;authorize!&lt;/code&gt; method at the top of any routes that you want to be authenticated, like so:&lt;/p&gt;
&lt;script src='http://pastie.org/518558.js'&gt;&lt;/script&gt;&lt;p&gt;
&lt;h2&gt;Gimme the code!&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://github.com/jstorimer/sinatra-shopify"&gt;http://github.com/jstorimer/sinatra-shopify&lt;/a&gt;&lt;/p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;h2&gt;Disclaimer&lt;/h2&gt;
&lt;p&gt;I am by no means a sinatra expert, this is really my first experience with sinatra. So if you see anything that could be done better, &lt;a href="http://github.com/jstorimer/sinatra-shopify"&gt;the source&lt;/a&gt; is on Github, fork away.&lt;/p&gt;
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/XW3hYBZlMpB6f-rG8UIf8XRESzw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/XW3hYBZlMpB6f-rG8UIf8XRESzw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/XW3hYBZlMpB6f-rG8UIf8XRESzw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/XW3hYBZlMpB6f-rG8UIf8XRESzw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/f6u6DYWnuE8" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/shopify/2009/06/20/sinatra-and-shopify-a-classy-shopify_app.html</feedburner:origLink></entry>
 
 <entry>
   <title>Shopify API Extensions</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/bS02sfk2F_s/shopify-api-extensions.html" />
   <updated>2009-06-15T00:00:00-04:00</updated>
   <id>http://jstorimer.com/shopify/2009/06/15/shopify-api-extensions</id>
   <content type="html">&lt;p&gt;Excited by the release of the &lt;a href="http://blog.shopify.com/2009/6/2/shopify-app-store-and-api-officially-launched"&gt;Shopify&lt;/a&gt; &lt;a href="http://blog.leetsoft.com/2009/6/2/so-about-this-shopify-platform"&gt;platform&lt;/a&gt;, I have been playing a lot with the Shopify &lt;span class="caps"&gt;API&lt;/span&gt; and building some apps for the new &lt;a href="http://apps.shopify.com/"&gt;App Store&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Shopify &lt;span class="caps"&gt;API&lt;/span&gt; is super easy to work with, thanks to the fact that it provides an ActiveResource interface, and of course I write all of my apps in Ruby. In the course of playing with the &lt;span class="caps"&gt;API&lt;/span&gt;, I have needed some specific helpers not provided by the Shopify &lt;span class="caps"&gt;API&lt;/span&gt;, more specifically, things that ActiveResource doesn&amp;#8217;t do well. So I added a few helpers to the Shopify &lt;span class="caps"&gt;API&lt;/span&gt; that others might find useful.&lt;/p&gt;
&lt;h2&gt;Base class&lt;/h2&gt;
&lt;p&gt;The &lt;a href="http://github.com/Shopify/shopify_app/tree/master"&gt;official shopify_app plugin&lt;/a&gt; uses ActiveResource::Base when setting the site, username, password, etc. This can potentially cause problems if you are working with multiple ActiveResource API&amp;#8217;s in your application. I have added a ShopifyAPI::Base class so that there is never any spillover of username&amp;#8217;s and password&amp;#8217;s between different ActiveResource API&amp;#8217;s.&lt;/p&gt;
&lt;h2&gt;Batched find&lt;/h2&gt;
&lt;p&gt;Can be used like:&lt;br /&gt;
&lt;script src='http://pastie.org/512754.js'&gt;&lt;/script&gt;&lt;/p&gt;
&lt;p&gt;This is especially useful if you need to do something to all products, or all orders, or whatever, in a background task. There is no easy way to ask for all of a particular object using ActiveResource, so this method just asks for a batch at a time, and lets you work with each batch until there is no more.&lt;/p&gt;
&lt;p&gt;By default, it uses a batch size of 100, but you can override that by passing in a limit param, like so:&lt;br /&gt;
&lt;script src='http://pastie.org/512758.js'&gt;&lt;/script&gt;&lt;/p&gt;
&lt;p&gt;This will work in the same but will fetch things in smaller batches instead of 100 at a time.&lt;/p&gt;
&lt;h2&gt;Count&lt;/h2&gt;
&lt;p&gt;ActiveResource does not provide a nice way to ask for a count of objects, nor does the Shopify &lt;span class="caps"&gt;API&lt;/span&gt;. Now you can do something like:&lt;br /&gt;
&lt;script src='http://pastie.org/512761.js'&gt;&lt;/script&gt;&lt;br /&gt;
to get a count of all the orders for a particular shop. Once again this is actually finding all orders in batches and just recording the total number of orders returned.&lt;/p&gt;
&lt;h2&gt;Word of warning&lt;/h2&gt;
&lt;p&gt;Both of these methods involve fetching all of a particular type of object through the Shopify &lt;span class="caps"&gt;API&lt;/span&gt;. Since some shops may have hundreds or thousands of orders, products, etc. it is not wise to do this in a user-facing screen. These things should be reserved for background processes only.&lt;/p&gt;
&lt;p&gt;Check out &lt;a href="http://github.com/jstorimer/shopify_app/tree/master"&gt;my fork of the shopify_app plugin&lt;/a&gt; on github to get these goodies.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/7sDB67qC8yWOWuIibXxx_zlKzQY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7sDB67qC8yWOWuIibXxx_zlKzQY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/7sDB67qC8yWOWuIibXxx_zlKzQY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7sDB67qC8yWOWuIibXxx_zlKzQY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/bS02sfk2F_s" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/shopify/2009/06/15/shopify-api-extensions.html</feedburner:origLink></entry>
 
 <entry>
   <title>Readability</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/YP5O7u1aZC4/readability.html" />
   <updated>2009-06-10T00:00:00-04:00</updated>
   <id>http://jstorimer.com/personal/2009/06/10/readability</id>
   <content type="html">&lt;p&gt;I decided to update my blog&amp;#8217;s template after using &lt;a href="http://lab.arc90.com/experiments/readability/"&gt;Readability&lt;/a&gt; for a few days. I liked the setup that Readability provided so much that when coming to my blog, I noticed that it was very hard to read. The font was small and grey and on a white background, which I thought was OK.&lt;/p&gt;
&lt;p&gt;Through using Readability I have discovered that it&amp;#8217;s easier (for me at least) to read things when the background is off-white, this kind of manilla color is best for my eyes.&lt;/p&gt;
&lt;div class="thumbnail"&gt;&lt;a href="http://skitch.com/importer/buiyf/readability-an-arc90-lab-experiment"&gt;&lt;img src="http://img.skitch.com/20090610-td85g986p7su6p17ubkq3a22p9.preview.jpg" alt="Readability - An Arc90 Lab Experiment" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;So you should check out &lt;a href="http://lab.arc90.com/experiments/readability/"&gt;Readability&lt;/a&gt;, it&amp;#8217;s an awesome way to read websites, especially useful for those sites that insist on using 9-point grey font that&amp;#8217;s impossible to read :P&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m currently using the &lt;strong&gt;Novel&lt;/strong&gt; style with &lt;strong&gt;medium&lt;/strong&gt; font and a &lt;strong&gt;wide&lt;/strong&gt; margin.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;d love to hear what settings work best for any of you out there.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/CxPllgfu7CHUZuUqhAcx6Uy76Fw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CxPllgfu7CHUZuUqhAcx6Uy76Fw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/CxPllgfu7CHUZuUqhAcx6Uy76Fw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CxPllgfu7CHUZuUqhAcx6Uy76Fw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/YP5O7u1aZC4" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/personal/2009/06/10/readability.html</feedburner:origLink></entry>
 
 <entry>
   <title>Transformers and Git</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/1AF0ZVgduls/transformers-and-git.html" />
   <updated>2009-05-30T00:00:00-04:00</updated>
   <id>http://jstorimer.com/git/2009/05/30/transformers-and-git</id>
   <content type="html">&lt;p&gt;Today, I was watching some of the Special Features from the live-action Transformers movie, very interesting stuff.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.theage.com.au/ffximage/2007/06/27/lge_Trans_070627040418616_wideweb__300x300.jpg" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;I noticed that whenever they would show clips from the movie there would be some text at the bottom of the screen, always a timestamp followed by a string of text.&lt;/p&gt;
&lt;p&gt;Here is one such message: &amp;#8220;additional paint and suppression sweetening&amp;#8230;&amp;#8221;&lt;/p&gt;
&lt;p&gt;Looks like a &lt;a href="http://en.wikipedia.org/wiki/Revision_control"&gt;version control system&lt;/a&gt; to me, and looks like those animators have the same problem as I do, trying to come up with good commit messages.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/LvHtkxNPm--Fds-NUA0BT57eBIU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LvHtkxNPm--Fds-NUA0BT57eBIU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/LvHtkxNPm--Fds-NUA0BT57eBIU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LvHtkxNPm--Fds-NUA0BT57eBIU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/1AF0ZVgduls" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/git/2009/05/30/transformers-and-git.html</feedburner:origLink></entry>
 
 <entry>
   <title>UML vs. Rails Simplicity</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/MeJ37izGhkg/uml-vs-rails-simplicity.html" />
   <updated>2009-03-24T00:00:00-04:00</updated>
   <id>http://jstorimer.com/ruby/2009/03/24/uml-vs-rails-simplicity</id>
   <content type="html">&lt;p&gt;Yesterday I was working through a conceptually difficult relationship between my Rails models. After sitting at the keyboard and pulling my hair for a few minutes I went to the whiteboard where I could lay things out and get a better overview of the situation.&lt;/p&gt;
&lt;p&gt;Having taken a course on Software Engineering at University, my first instinct was to use &lt;span class="caps"&gt;UML&lt;/span&gt; and pictures to represent the situation I wanted and transcribe it to code later. But since I&amp;#39;m using Rails it was actually easier to just write the code. I just wrote something like this:&lt;/p&gt;
&lt;script src="http://gist.github.com/84174.js"&gt;&lt;/script&gt;&lt;p&gt;instead of &lt;br /&gt;
&lt;img src="http://www.ukoln.ac.uk/qa-focus/documents/case-studies/case-study-03/qa-uml" width='500px' /&gt;&lt;br /&gt;
&lt;span class="caps"&gt;YIKES&lt;/span&gt;!&lt;/p&gt;
&lt;p&gt;It&amp;#39;s funny that &lt;span class="caps"&gt;UML&lt;/span&gt; exists as a pseudo-language on top of other programming languages, so that people, technical and non-technical, can talk about these things and you can have a shorthand for defining relations between models etc. without having to actually write code.&lt;/p&gt;
&lt;p&gt;I love how Rails circumvented a lot of that by just making the framework so simple. The way I talk about Rails (and Ruby) code at a high level is the same way that I actually implement it in code.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://blog.patientslikeme.com/wp-content/uploads/2009/01/crossing-chasm.jpg" /&gt;&lt;/p&gt;
&lt;p class="details"&gt;  &lt;span style="font-size: 10px;"&gt;  &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;   from &lt;a href="http://jstorimer.posterous.com/uml-vs-rails-simplicity"&gt;Jesse&amp;#8217;s posterous&lt;/a&gt;  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/IQieU0MNX-bo3wanBo2Ad2OJfwE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/IQieU0MNX-bo3wanBo2Ad2OJfwE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/IQieU0MNX-bo3wanBo2Ad2OJfwE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/IQieU0MNX-bo3wanBo2Ad2OJfwE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/MeJ37izGhkg" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/ruby/2009/03/24/uml-vs-rails-simplicity.html</feedburner:origLink></entry>
 
 <entry>
   <title>Ruby on a Plane</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/X2iKUHbM-co/ruby-on-a-plane.html" />
   <updated>2009-03-12T00:00:00-04:00</updated>
   <id>http://jstorimer.com/ruby/2009/03/12/ruby-on-a-plane</id>
   <content type="html">&lt;p&gt;&lt;img src='http://static2.shopify.com/s/files/1/0024/7532/files/ruby_on_a_plane.jpg?1235620061' alt='' /&gt;&lt;/p&gt;
&lt;p&gt;Lately it has seemed that every time I turn around, I hear about another great Ruby project that was started on the plane to .&lt;/p&gt;
&lt;p&gt;I have been keeping a list of the ones I have come across so far, either in conversation, blog posts or podcast. If you know of more, please leave them in the comments.&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://gilesbowkett.blogspot.com/2008/09/towelie-keeps-your-code-dry.html"&gt;Towelie&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://liquidmarkup.org/"&gt;Liquid&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://rubini.us/"&gt;Rubinius&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://jimneath.org/2008/04/17/paperclip-attaching-files-in-rails/"&gt;Paperclip&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://techno-weenie.net/2009/1/18/is-my-show-on-yet"&gt;isLostOnYet&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://giantrobots.thoughtbot.com/2009/2/11/yiloveit"&gt;yiloveit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I realize that great projects also happen off of planes, but I can&amp;#8217;t ignore how often I have seen this lately :[]&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/xhP79NDIUpMhhc_qu9nHIKVCIoo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xhP79NDIUpMhhc_qu9nHIKVCIoo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/xhP79NDIUpMhhc_qu9nHIKVCIoo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xhP79NDIUpMhhc_qu9nHIKVCIoo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/X2iKUHbM-co" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/ruby/2009/03/12/ruby-on-a-plane.html</feedburner:origLink></entry>
 
 <entry>
   <title>Skating to Work</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/EsC3vTnfwZ0/skating-to-work.html" />
   <updated>2009-01-25T00:00:00-05:00</updated>
   <id>http://jstorimer.com/2009/01/25/skating-to-work</id>
   <content type="html">&lt;p&gt;Ahh Canada. Where else could someone skate to work?&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.bellcold.com/SweetShots/Skating%20on%20the%20Rideau%20Canal.JPG" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;I consider myself lucky, not only do I live in Ottawa, home of the &lt;a href="http://www.canadascapital.gc.ca/bins/ncc_web_content_page.asp?cid=16297-16299-10080&amp;amp;lang=1"&gt;worlds largest skating rink&lt;/a&gt;, but I also live near the middle of the Rideau Canal and &lt;a href="http://www.shopify.com/about"&gt;work near one end of the Rideau Canal&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the mornings and evenings I tie up my skates and go for a 15 min. skate on the Canal. It&amp;#8217;s a great way to start and end the day.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ottawainfocenter.com/rideau_canal_skating.jpg" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;And then there are &amp;#8216;those&amp;#8217; days. &amp;uarr;&lt;/p&gt;
&lt;p&gt;Skating on the Canal is a great way to get some exercise and see some of the downtown from a different angle. If you happen to be in Ottawa in the winter, it&amp;#8217;s definitely checking out.&lt;/p&gt;
&lt;p&gt;Sometimes in the morning there is no one else out there but me, and it&amp;#8217;s so freeing to be skating out there in downtown Ottawa with no people around and no cars around, it&amp;#8217;s awesome.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/szqfn6S65uphYU6uj7-zW3eJ2U8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/szqfn6S65uphYU6uj7-zW3eJ2U8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/szqfn6S65uphYU6uj7-zW3eJ2U8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/szqfn6S65uphYU6uj7-zW3eJ2U8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/EsC3vTnfwZ0" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2009/01/25/skating-to-work.html</feedburner:origLink></entry>
 
 <entry>
   <title>Rework Your Git History</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/OQT7blx5POA/rework-your-git-history.html" />
   <updated>2009-01-16T00:00:00-05:00</updated>
   <id>http://jstorimer.com/git/2009/01/16/rework-your-git-history</id>
   <content type="html">&lt;p&gt;Git is an awesome tool. Recently I have been discovering more and more cool things I can do with git. Here is one such thing.&lt;/p&gt;
&lt;p&gt;I was recently working in a development branch and had made more commits than were necessary. I had been committing every time I got a small piece of new functionality to work and I had about 12 commits that should have been only 3 commits. Enter &lt;code&gt;git rebase --interactive&lt;/code&gt;:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;
git rebase -i &lt;commit&gt;&lt;br /&gt;
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;This is awesome. It gives you an interactive way to reorganize your commit history since the one specified in &amp;lt;commit&amp;gt;.  It opens up your &lt;code&gt;$EDITOR&lt;/code&gt; with the list of commits, something like this:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;
pick c9205f4 Ok, so spawn doesn&amp;#8217;t work exactly right yet.&lt;br /&gt;
pick c770395 Added Errno::&lt;span class="caps"&gt;ENOTDIR&lt;/span&gt; to the list of errors when rmdiring&lt;br /&gt;
pick 49221b6 There&amp;#8217;s no reason to load anything but test for the database.yml&lt;br /&gt;
pick bc1af0c Removed rake/gempackagetask and the rubyforge rake task&lt;br /&gt;
pick 8a43c13 Added requirement for thoughtbot-shoulda &amp;gt;=2.0.0 in test_helper&lt;br /&gt;
pick 06f9b99 #47: Multipage PDFs fixed by Pete Deffendol&lt;br /&gt;
pick 279b757 Updated the rake task to take &lt;span class="caps"&gt;STI&lt;/span&gt; into consideration.&lt;br /&gt;
 &lt;br /&gt;
# Rebase 701abb0..279b757 onto 701abb0&lt;br /&gt;
#&lt;br /&gt;
# Commands:&lt;br /&gt;
#  pick = use commit&lt;br /&gt;
#  edit = use commit, but stop for amending&lt;br /&gt;
#  squash = use commit, but meld into previous commit&lt;br /&gt;
#&lt;br /&gt;
# If you remove a line here &lt;span class="caps"&gt;THAT&lt;/span&gt; &lt;span class="caps"&gt;COMMIT&lt;/span&gt; &lt;span class="caps"&gt;WILL&lt;/span&gt; BE &lt;span class="caps"&gt;LOST&lt;/span&gt;.&lt;br /&gt;
# However, if you remove everything, the rebase will be aborted.&lt;br /&gt;
#&lt;br /&gt;
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;You can rewrite &lt;code&gt;pick&lt;/code&gt; to change the behaviour.&lt;/p&gt;
&lt;p&gt;If you want to combine a commit with the one above, just change it from &lt;code&gt;pick&lt;/code&gt; to &lt;code&gt;squash&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you want to leave a commit as it is, just leave it at &lt;code&gt;pick&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you want to change a commit, change it to &lt;code&gt;edit&lt;/code&gt;. &lt;code&gt;Edit&lt;/code&gt; is awesome, you can change which files are included in the commit and even update old commit messages.&lt;/p&gt;
&lt;p&gt;You can even change the order of commits by just rearranging the lines in the file. But be careful, if you delete a line, then that commit will be deleted.&lt;/p&gt;
&lt;p&gt;When you exit the text editor, it will start rebasing your commits. If there is a merge conflict, or when a commit has been marked as edit, then the rebase stops. You make your changes and amend your commit with &lt;code&gt;git commit --amend&lt;/code&gt;. Then just &lt;code&gt;git rebase --continue&lt;/code&gt; to continue on with the rebase!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/8Si_1fSTAmYVA2qxEMEFIW6roBY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/8Si_1fSTAmYVA2qxEMEFIW6roBY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/8Si_1fSTAmYVA2qxEMEFIW6roBY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/8Si_1fSTAmYVA2qxEMEFIW6roBY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/OQT7blx5POA" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/git/2009/01/16/rework-your-git-history.html</feedburner:origLink></entry>
 
 <entry>
   <title>What the heck is JSONP?</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/KVoJIqw1oX4/what-the-heck-is-jsonp.html" />
   <updated>2009-01-12T00:00:00-05:00</updated>
   <id>http://jstorimer.com/js/2009/01/12/what-the-heck-is-jsonp</id>
   <content type="html">&lt;p&gt;Recently I stumbled across something called &lt;span class="caps"&gt;JSONP&lt;/span&gt;. I read that it was a hack that allowed for cross domain &lt;span class="caps"&gt;AJAX&lt;/span&gt; requests, which of course piqued my interest, but I had a really hard time finding out how it worked. After spending a few days experimenting and reading blog posts, I think I have a grasp on it.&lt;/p&gt;
&lt;p&gt;So here is my attempt at a pop-up book explanation:&lt;/p&gt;
&lt;h3&gt;What is &lt;span class="caps"&gt;JSON&lt;/span&gt;?&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;JSON&lt;/span&gt; stands for JavaScript Object Notation. It is simple a format for representing data, much like &lt;span class="caps"&gt;XML&lt;/span&gt;. Here is some data represented in &lt;span class="caps"&gt;XML&lt;/span&gt;:&lt;/p&gt;
&lt;script src="http://gist.github.com/45865.js"&gt;&lt;/script&gt;&lt;p&gt;and the same data represented in &lt;span class="caps"&gt;JSON&lt;/span&gt;:&lt;/p&gt;
&lt;script src="http://gist.github.com/45868.js"&gt;&lt;/script&gt;&lt;h3&gt;What is &lt;span class="caps"&gt;JSONP&lt;/span&gt;?&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;JSONP&lt;/span&gt; stands for &lt;span class="caps"&gt;JSON&lt;/span&gt; with Padding. It is basically a clever hack that allows for cross domain &lt;span class="caps"&gt;AJAX&lt;/span&gt; requests, but it requires the participation of the remote server you are requesting data from. It works something like this:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;You request a &lt;span class="caps"&gt;JSON&lt;/span&gt; document from a remote server and specify a callback parameter. This would look something like &lt;code&gt;http://search.twitter.com/trends.json?callback=handle_data&lt;/code&gt;.&lt;/li&gt;
	&lt;li&gt;This is the part that requires participation from the remote server. If they support &lt;span class="caps"&gt;JSONP&lt;/span&gt;, they will wrap the resulting &lt;span class="caps"&gt;JSON&lt;/span&gt; data in a JS function call, returning a script that looks something like this:&lt;/li&gt;
&lt;/ol&gt;
&lt;script src="http://gist.github.com/45869.js"&gt;&lt;/script&gt;&lt;h3&gt;How can I use this?&lt;/h3&gt;
&lt;p&gt;If you define a callback method in your document and then use a script tag to include a &lt;span class="caps"&gt;JSONP&lt;/span&gt; call, you can request and handle that &lt;span class="caps"&gt;JSON&lt;/span&gt; data, all from JS. Like so:&lt;/p&gt;
&lt;script src="http://gist.github.com/45878.js"&gt;&lt;/script&gt;&lt;p&gt;Yay! Cross domain JS request.&lt;/p&gt;
&lt;p&gt;If this went right over your head, as it did for me the first few times, here is a recap:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;You included a remote script (from Twitter in this case) that made a call to a JS function (whose name you specified with the callback parameter) with the &lt;span class="caps"&gt;JSON&lt;/span&gt; data that you wanted as an argument to that function.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is pretty neat, but it does have drawbacks:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Danger: You are allowing the remote server to execute arbitrary JS on your page. This is generally a bad idea and you have no way of verifying what that server is embedding in your document. If you trust the server then this technique works just fine :|&lt;/li&gt;
	&lt;li&gt;This technique requires that the remote server implement some logic to allow you to do this. This is becoming more prevalent however. Thus far I have discovered that Twitter and Flickr both support this. Anyone find others?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As a result of this stuff, I did a &lt;a href="http://jstorimer.github.com/flitter/"&gt;fun experiment&lt;/a&gt;. It grabs the latest trends from Twitter and searches for images tagged with the same at Flickr, all in JS! The source is on &lt;a href="http://github.com/jstorimer/twickr/tree/master"&gt;Github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/SknJnQqHQ7J-HcXZKtfGeQTsFa0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SknJnQqHQ7J-HcXZKtfGeQTsFa0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/SknJnQqHQ7J-HcXZKtfGeQTsFa0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SknJnQqHQ7J-HcXZKtfGeQTsFa0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/KVoJIqw1oX4" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/js/2009/01/12/what-the-heck-is-jsonp.html</feedburner:origLink></entry>
 
 <entry>
   <title>Environmentally Friendly Image Search</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/GhunH2VlWOY/environmentally-friendly-image-search.html" />
   <updated>2009-01-07T00:00:00-05:00</updated>
   <id>http://jstorimer.com/personal/2009/01/07/environmentally-friendly-image-search</id>
   <content type="html">&lt;p&gt;Recently I was looking for some stock images on Google Image Search and wasn&amp;#8217;t finding what I wanted. So I searched for other image search engines and found &lt;a href="http://picsearch.com"&gt;Picsearch&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Not only did it give me better results but they are apparently the &lt;a href="http://about.picsearch.com/p_releases/the-worlds-first-carbon-free-search-engine/"&gt;first search engine to go carbon neutral&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here is their 4 step program:&lt;/p&gt;
&lt;p&gt;1. Picsearch plants 1000 new trees for every gigawatt-hour consumed. &lt;br /&gt;
2. Picsearch buys and holds in trust 2 acres of old growth forest for every gigawatt-hour consumed. &lt;br /&gt;
3. Picsearch only uses electricity that is carbon free and follows the highest standard of production.&lt;br /&gt;
4. Picsearch buys carbon credits equivalent to all energy that Picsearch consumes.&lt;/p&gt;
&lt;p&gt;So next time Google Images isn&amp;#8217;t finding what you are after, try a &lt;a href="http://picsearch.com"&gt;friendly alternative&lt;/a&gt;.&lt;br /&gt;
&lt;p class="details"&gt;  &lt;span style="font-size: 10px;"&gt;  &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;   from &lt;a href="http://jstorimer.posterous.com/environmentally-friendly-image"&gt;Jesse's posterous&lt;/a&gt;  &lt;/span&gt;
&lt;br /&gt;
&lt;img src="http://static2.shopify.com/s/files/1/0024/7532/assets/earth.png?1232911139" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/0Jeq-8qLox1d7DSJeaSEKQXMwaI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0Jeq-8qLox1d7DSJeaSEKQXMwaI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/0Jeq-8qLox1d7DSJeaSEKQXMwaI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0Jeq-8qLox1d7DSJeaSEKQXMwaI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/GhunH2VlWOY" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/personal/2009/01/07/environmentally-friendly-image-search.html</feedburner:origLink></entry>
 
 <entry>
   <title>The Beginning</title>
   <link href="http://feedproxy.google.com/~r/jstorimer/~3/zkHOeQwuWMs/the-beginning.html" />
   <updated>2008-12-31T00:00:00-05:00</updated>
   <id>http://jstorimer.com/2008/12/31/the-beginning</id>
   <content type="html">&lt;p&gt;Whaddya know? My first blog post.&lt;/p&gt;
&lt;p&gt;This blog is coming to you live from &lt;a href="http://www.shopify.com"&gt;Shopify&lt;/a&gt;. The best in e-commerce and evidently a solid blogging platform as well.&lt;/p&gt;
&lt;p&gt;I&amp;#39;m really liking the &lt;del&gt;&lt;a href="http://vostoktheme.com/"&gt;Vostok theme&lt;/a&gt;&lt;/del&gt; I went with for this blog, not bad eh.&lt;/p&gt;
&lt;p&gt;Anyway, stay tuned as I hope to be bringing more actual content to this blog in the near future. I am currently really interested in Rails and new technologies that make web development easier and faster. I hope to be posting my findings on this blog.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: 10px;"&gt;  &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;   from &lt;a href="http://jstorimer.posterous.com/the-beginning-12"&gt;Jesse&amp;#8217;s posterous&lt;/a&gt;  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/aZw2piLnSrXCKrjBWnwrYpQRkQ4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aZw2piLnSrXCKrjBWnwrYpQRkQ4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/aZw2piLnSrXCKrjBWnwrYpQRkQ4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aZw2piLnSrXCKrjBWnwrYpQRkQ4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jstorimer/~4/zkHOeQwuWMs" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://jstorimer.com/2008/12/31/the-beginning.html</feedburner:origLink></entry>
 
 
</feed>

