<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Otter Book</title>
	<atom:link href="http://www.otterbook.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.otterbook.com</link>
	<description>Automating System Administration with Perl</description>
	<lastBuildDate>Mon, 11 Jan 2010 16:18:49 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Speeding Up fsck/fsck_hsfs on OSX</title>
		<link>http://www.otterbook.com/blog/2010/01/speeding-up-an-fsckfsck_hsfs-on-osx/</link>
		<comments>http://www.otterbook.com/blog/2010/01/speeding-up-an-fsckfsck_hsfs-on-osx/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 01:15:39 +0000</pubDate>
		<dc:creator>dnb</dc:creator>
				<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[fsck]]></category>
		<category><![CDATA[osx]]></category>

		<guid isPermaLink="false">http://www.otterbook.com/?p=357</guid>
		<description><![CDATA[Here&#8217;s a quick tip on how to make an fsck (or specifically an fsck_hsfs) run much faster. I learned this as part of debugging some corruption with the backup image on my Time Capsule.
/bin/fsck_hfs -f -d -c {%mem} /dev/rdisk{N}
where {%mem} is  &#189; to 1&#8260;3rd the amount of memory you have in your computer. If [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Here&#8217;s a quick tip on how to make an <span class="command">fsck</span> (or specifically an <span class="command">fsck_hsfs</span>) run <em>much</em> faster. I learned this as part of debugging some corruption with the backup image on my Time Capsule.</p>
<pre class="brush: bash;">/bin/fsck_hfs -f -d -c {%mem} /dev/rdisk{N}</pre>
<p>where <span class="variable">{%mem}</span> is  &#189; to 1&#8260;3rd the amount of memory you have in your computer. If you need to determine the amount of memory in a machine from the command line, a great blog post on <a href="http://juretta.com/log/2007/02/04/mac_os_x_command_line_goodies/">Mac OS X Command Line Goodies</a> suggests you can  use:</p>
<pre class="brush: bash;">
/usr/sbin/system_profiler SPHardwareDataType | grep Memory
</pre>
<p>For example, you can use <span class="command">-c 512m</span> if you have a 1GB machine. </p>
<p>and  </p>
<p><span class="variable">{N}</span> is the correct device node. This command will show you the list of disk nodes:</p>
<pre class="brush: bash;">diskutil list</pre>
<p>For example, you might use <span class="command">/dev/rdisk0s2</span>.</p>
<p>The <span class="command">-d</span> turns on debugging and <span class="command">-f</span> instructs <span class="command">fsck_hsfs</span> to force a repair if it finds any problems.</p>
<p>In case you were curious, the <span class="command">-c</span> setting is the part of the incantation that gives it its real magic. It lets the command cache a considerable amount of information in memory and that speeds up any scan a tremendous amount. If you ever run a disk repair from Disk Utility, you&#8217;ll notice the <span class="command">fsck_hsfs</span> command it spawns lacks this option and hence is much slower.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.otterbook.com/blog/2010/01/speeding-up-an-fsckfsck_hsfs-on-osx/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Some lovely SSL resources</title>
		<link>http://www.otterbook.com/blog/2009/12/some-lovely-ssl-resources/</link>
		<comments>http://www.otterbook.com/blog/2009/12/some-lovely-ssl-resources/#comments</comments>
		<pubDate>Tue, 29 Dec 2009 20:25:47 +0000</pubDate>
		<dc:creator>dnb</dc:creator>
				<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[openssl]]></category>
		<category><![CDATA[ssl]]></category>

		<guid isPermaLink="false">http://www.otterbook.com/?p=351</guid>
		<description><![CDATA[Just had to deal with a total swap out of all of my SSL certificates at work thanks to the ipsCA screwup that also nailed Bob Plankers and Chris Siebenmann and I&#8217;m sure lots of other sites (especially .edu). I&#8217;m really peeved too, but rather than hissing and spitting like I really feel like doing, [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Just had to deal with a total swap out of all of my SSL certificates at work thanks to the ipsCA screwup that also nailed <a href="http://lonesysadmin.net/2009/12/22/ipsca-getting-what-you-pay-for/">Bob Plankers</a> and <a href="http://utcc.utoronto.ca/~cks/space/blog/web/SSLCAFailure">Chris Siebenmann</a> and I&#8217;m sure lots of other sites (especially .edu). I&#8217;m really peeved too, but rather than hissing and spitting like I really feel like doing, let me pass on a few SSL resources that I found useful while debugging the new chained certs we started using:</p>
<ul>
<li><a href="http://wiki.debian.org/SSLkeys">Debian&#8217;s SSL keys page</a> is a lovely resource for where and how each common open source package keeps its particular SSL-related configs. Your file system locations may vary but this at least gives you a start for the 30+ packages they list</li>
<li>UnixCraft&#8217;s <a href="http://www.cyberciti.biz/faq/test-ssl-certificates-diagnosis-ssl-certificate/">How To Verify SSL Certificate From a Shell Prompt</a> is a swell tutorial on the various <a href="http://www.openssl.org/">openssl</a> command line options you can use to debug certs. </li>
<li>Paul Heinlein&#8217;s <a href="http://www.madboa.com/geek/openssl/">OpenSSL Command-Line HOWTO</a> is a great HOWTO for all sorts of openssl operations.</li>
<li>The <a href="http://www.openssl.org/docs/apps/verify.html">OpenSSL verify manual page</a> lists the error messages you might get when attempting to verify, for example, a chained cert.</li>
<li><a href="http://www.sslshopper.com">SSLShopper.com</a>, in addition to being a good place to compare certificate authorities, has a surprising amount of really good technical information about all things SSL. For example, <a href="http://www.sslshopper.com/article-most-common-java-keytool-keystore-commands.html">The Most Common Java Keytool Keystore Commands</a> and 	<a href="http://www.sslshopper.com/article-most-common-openssl-commands.html">The Most Common OpenSSL Commands</a> are genuinely useful.</li>
</ul>
<p>Hope this are helpful to you should you get put in the same bind.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.otterbook.com/blog/2009/12/some-lovely-ssl-resources/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Where Have You Been All My Life? Rlwrap</title>
		<link>http://www.otterbook.com/blog/2009/12/where-have-you-been-all-my-life-rlwrap/</link>
		<comments>http://www.otterbook.com/blog/2009/12/where-have-you-been-all-my-life-rlwrap/#comments</comments>
		<pubDate>Mon, 14 Dec 2009 03:42:21 +0000</pubDate>
		<dc:creator>dnb</dc:creator>
				<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[rlwrap]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://www.otterbook.com/?p=342</guid>
		<description><![CDATA[Back in the days of yore (when sysadmins still had to bang two rocks together to do their job), we didn&#8217;t have command line history. No, we typed every command by hand. If we had to type the same 110-character command-line several times, we typed those 550 characters ourselves, mistakes and all, and by gum, [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Back in the days of yore (when sysadmins still had to bang two rocks together to do their job), we didn&#8217;t have command line history. No, we typed every command by hand. If we had to type the same 110-character command-line several times, we typed those 550 characters ourselves, mistakes and all, and by gum, we LIKED it! </p>
<p>And then shells became available with history functionality and, well, we kind of liked that too. And, um, then came along libraries like <a href="http://en.wikipedia.org/wiki/GNU_readline">GNU readline</a> that were written to provide even more pleasant, vizz-eee-ul history recall and editing to anything that presents a command line prompt, and well, ok, we REALLY that too. Because, quite frankly, typing long command line strings over and over again, sometimes because our typing skills aren&#8217;t always sharp, is a real drag.</p>
<p>But alas, not every program that provides a command-line prompt or handles interactive input provides this new-fangled user experience (I&#8217;m looking at you <a href="http://en.wikipedia.org/wiki/SQL*Plus">sqlplus</a>, maybe if scott had a real tiger&#8230;). In the past, a sysadmin had to look admonishingly at one of these programs, perhaps working around the lack of interface using something like <a href="http://expect.nist.gov/">Expect</a>.</p>
<p>Maybe I&#8217;m the last admin on the planet to hear about this idea, but it came as a pleasant surprise to find out that there are a number of programs out there whose whole purpose in life is to add the readline-yumminess to programs that don&#8217;t have it already. The first one I encountered was <a href="http://utopia.knoware.nl/~hlub/uck/rlwrap">rlwrap</a> by Hans Lub. Now you can type:</p>
<pre class="brush: bash;">
$ rlwrap sqlplus scott/tiger@oracle_instance
</pre>
<p>And you get a reasonable command-line environment even from within sqlplus.</p>
<p>I know I would have offered at least a vestigial body part several times in the past to have the &#8220;add readline to command X&#8221; super power several times during my career. (apparently this tip has been <a href="http://sysdba.wordpress.com/2006/10/08/how-to-use-rlwrap-to-get-a-command-history-in-sqlplus/">making people in the Oracle community happy</a> for a while now).  </p>
<p>The <a href="http://utopia.knoware.nl/~hlub/uck/rlwrap/README.txt">rlwrap README</a> mentions two other similar packages: rlfe which even ships with the GNU readline distribution and <a href="http://kaolin.unice.fr/Cle/">cle</a>. I note that cle hasn&#8217;t been touched for over ten years (the last release&#8217;s 10th birthday was just over a week ago). I can&#8217;t speak to how well rlfe works, but kudos to Lub for continuing to update the rlwrap package.</p>
<p>Hope this tip brings you a similar amount of joy.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.otterbook.com/blog/2009/12/where-have-you-been-all-my-life-rlwrap/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>But It&#8217;s Only A Slash: svn.access</title>
		<link>http://www.otterbook.com/blog/2009/09/but-its-only-a-slash-svn-access/</link>
		<comments>http://www.otterbook.com/blog/2009/09/but-its-only-a-slash-svn-access/#comments</comments>
		<pubDate>Fri, 11 Sep 2009 03:44:27 +0000</pubDate>
		<dc:creator>dnb</dc:creator>
				<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://www.otterbook.com/?p=336</guid>
		<description><![CDATA[I spent the good part of my morning today debugging an issue with a user&#8217;s access to a Subversion repository/trac service we provide. That person could not get even a basic svn checkout to work as expected. It would keep throwing errors like this:
Server sent unexpected return value (403 Forbidden) in response to OPTIONS request [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>I spent the good part of my morning today debugging an issue with a user&#8217;s access to a Subversion repository/trac service we provide. That person could not get even a basic svn checkout to work as expected. It would keep throwing errors like this:</p>
<p><code>Server sent unexpected return value (403 Forbidden) in response to OPTIONS request for {url}</code></p>
<p>I went up and down the stack, I poked and prodded the two web servers in question (Apache 2 and Lighttpd) and their authentication sources with multiple clients. I watched packet traces. I checked and rechecked every config I could lay my hands on to no avail. It was driving me crazy.</p>
<p>Finally, I realized that the mod_dav_svn file semantics for paths in an svn.access file distinguished between:</p>
<pre class="brush: plain;">
[repos:/dir/]
user1 = rw
user2 = rw</pre>
<p>and </p>
<pre class="brush: plain;">
[repos:/dir]
user1 = rw
user2 = rw</pre>
<p>The first only works if you&#8217;ve explicitly granted the same permissions to the parent directory as well, i.e.:</p>
<pre class="brush: plain;">
[repos:/]
user1 = rw
user2 = rw</pre>
<p>while the second &#8220;does the right thing&#8221; to allow the users to have access to that path component without having to permit the parent directory as well.</p>
<p>Hopes this saves you some time.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.otterbook.com/blog/2009/09/but-its-only-a-slash-svn-access/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Talk Amongst Yourselves</title>
		<link>http://www.otterbook.com/blog/2009/08/talk-amongst-yourselves/</link>
		<comments>http://www.otterbook.com/blog/2009/08/talk-amongst-yourselves/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 18:51:02 +0000</pubDate>
		<dc:creator>dnb</dc:creator>
				<category><![CDATA[tech]]></category>
		<category><![CDATA[DECT]]></category>
		<category><![CDATA[phone]]></category>

		<guid isPermaLink="false">http://www.otterbook.com/?p=329</guid>
		<description><![CDATA[We just purchased a few new phones to replace our aging tin cans on a string at home. On the sage advice of some other techies I know, we purchased a few phones based on the DECT standard. IMHO, one of the coolest things about the DECT phones is they freakin&#8217; talk to each other.
I [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>We just purchased a few new phones to replace our aging tin cans on a string at home. On the sage advice of some other techies I know, we purchased a few phones based on the DECT standard. IMHO, one of the coolest things about the DECT phones is they freakin&#8217; talk to each other.</p>
<p>I know this sounds like one of those &#8220;Primitive man fascinated by shiny objects&#8221; little exclamations (it sounds so ridiculously naive to even me as I say it, especially given my background), but hey, it is sooo COOL that the headsets sync stuff like phonebook information amongst themselves (I guess via the base station) and I didn&#8217;t have to do jack to make that happen besides provide one POTS connection and plug in a few power bricks. I guess I&#8217;m so used treating every single handset in my life as a completely separate entity that this idea really impressed me. I wanted to walk into the kitchen and stare reproachfully at all of the appliances there and say &#8220;So, what&#8217;s wrong with you guys? How come you aren&#8217;t sharing information? The phones can do it.&#8221;</p>
<p>The one other cool, though less unexpected thing these phones do is treat the caller id information that comes in every time the phone rings as something I might care about. I think it is a no-brainer that I might want to use this information to add information to the phones&#8217;(!) phonebooks or block subsequent calls from a certain caller and now that&#8217;s available.  They also keep their internal clock in sync with the telco&#8217;s signals, another nice touch.</p>
<p>I suppose you get all of this cool stuff if you start to play with VoIP (e.g. get into the <a href="http://www.asterisk.org/">Asterisk</a> game), but for a consumer experience it was a surprise.</p>
<p>No, really. They talk to each other.</p>
<p>P.S. Warning: DECT phones have some relatively recently discovered security vulnerabilities (I know, what doesn&#8217;t? but they were new to me, I hadn&#8217;t seen them in my usual infostream). It looks like the best source of info about these vulnerabilities is this site <a href="https://dedected.org">here</a>. See the thesis published (right hand column) for the best description of the issue and a list of phones they tested.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.otterbook.com/blog/2009/08/talk-amongst-yourselves/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Piracy, the Sincerest Form of Flattery?</title>
		<link>http://www.otterbook.com/blog/2009/08/piracy-the-sincerest-form-of-flattery/</link>
		<comments>http://www.otterbook.com/blog/2009/08/piracy-the-sincerest-form-of-flattery/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 00:33:26 +0000</pubDate>
		<dc:creator>dnb</dc:creator>
				<category><![CDATA[book]]></category>

		<guid isPermaLink="false">http://www.otterbook.com/?p=323</guid>
		<description><![CDATA[Well, I think the book has hit the big time because I randomly stumbled on not one, not two, but four separate places where people had uploaded my book to some of the grey matter (both kinds) sharing sites. In particular, there&#8217;s a Thai-speaking user whose been very busy being naughty. At least one site [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Well, I think the book has hit the big time because I randomly stumbled on not one, not two, but four separate places where people had uploaded my book to some of the grey matter (both kinds) sharing sites. In particular, there&#8217;s a Thai-speaking user whose been very busy being naughty. At least one site I found had a very pretty web gui for downloading the book. And while I admire the pluck of people who work that hard to make it easy for other people to engage in less than savory activities, it still leaves me feeling a little uneasy and perhaps a bit sad. </p>
<p>I&#8217;ve ready my fair share of articles about how &#8220;illegal&#8221; distribution can have all sorts of positive effects on book sales and other promotional activity which is why I&#8217;m not advocating the villagers grab their pitchforks and smokey torches and join me in storming these sites to demand justice. But you won&#8217;t find me giving my blessing any time soon.</p>
<p>If you happened to have stumbled upon this site through a chain of events related to one of these ehemm, distribution points, I&#8217;d ask two things:</p>
<ul>
<li>Enjoy the book. There&#8217;s a Yiddish phrase that roughly translates to &#8220;If you are going to do something wrong, at least enjoy it.&#8221; I didn&#8217;t write the book for the money, I wrote it so people could learn from it and take a little pleasure reading it. (though the small royalty check is kind of nice too).</li>
<li>Keep karma neutral. You don&#8217;t even have to right things by me by buying a copy of my book or attending one of my classes. Just go do something <em>giving</em> to offset the <em>taking</em>. It will make you, me and the person you give to happier.</li>
</ul>
<p>Thanks.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.otterbook.com/blog/2009/08/piracy-the-sincerest-form-of-flattery/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Fixing the SQLite DB for a Trac Instance</title>
		<link>http://www.otterbook.com/blog/2009/08/fixing-the-sqlite-db-for-a-trac-instance/</link>
		<comments>http://www.otterbook.com/blog/2009/08/fixing-the-sqlite-db-for-a-trac-instance/#comments</comments>
		<pubDate>Thu, 20 Aug 2009 12:57:15 +0000</pubDate>
		<dc:creator>dnb</dc:creator>
				<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[sqlite]]></category>

		<guid isPermaLink="false">http://www.otterbook.com/?p=305</guid>
		<description><![CDATA[&#8217;bout time I add some sysadmin content here.
If you ever have a trac instance go boom with an error like &#8220;DatabaseError: database disk image is malformed&#8221; you can often fix the problem by doing an sqlite dump/reload:

$ cd /path/to/trac-sqlite-db-directory # find the trac.db file
$ su www-data   # switch to the owner of the [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>&#8217;bout time I add some sysadmin content here.<br />
If you ever have a trac instance go boom with an error like &#8220;DatabaseError: database disk image is malformed&#8221; you can often fix the problem by doing an sqlite dump/reload:</p>
<pre class="brush: bash;">
$ cd /path/to/trac-sqlite-db-directory # find the trac.db file
$ su www-data   # switch to the owner of the db file
$ mv trac.db trac.db.damaged
$ sqlite3 trac.db.damaged .dump|sqlite3 trac.db
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.otterbook.com/blog/2009/08/fixing-the-sqlite-db-for-a-trac-instance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PMotD: Text::Balanced</title>
		<link>http://www.otterbook.com/blog/2009/07/pmotd-textbalanced/</link>
		<comments>http://www.otterbook.com/blog/2009/07/pmotd-textbalanced/#comments</comments>
		<pubDate>Fri, 31 Jul 2009 05:26:59 +0000</pubDate>
		<dc:creator>dnb</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[modules]]></category>

		<guid isPermaLink="false">http://www.otterbook.com/?p=285</guid>
		<description><![CDATA[If you&#8217;ve read Jeffrey Friedl&#8217;s Mastering Regular Expressions1 you&#8217;ll recall that one of the things that is a lot harder than it looks to get right using regexps is extracting the content from within some text-delimited string, especially when there are opening and closing delimiters2.
Text::Balanced originally by Damian Conway and now maintained by Adam Kennedy [...]]]></description>
			<content:encoded><![CDATA[<p></p><p style="clear: both">If you&#8217;ve read Jeffrey Friedl&#8217;s <a href="http://oreilly.com/catalog/9780596528126/">Mastering Regular Expressions</a><sup class='footnote'><a href='#fn-285-1' id='fnref-285-1'>1</a></sup> you&#8217;ll recall that one of the things that is a lot harder than it looks to get right using regexps is extracting the content from within some text-delimited string, especially when there are opening and closing delimiters<sup class='footnote'><a href='#fn-285-2' id='fnref-285-2'>2</a></sup>.</p>
<p style="clear: both"><a href="http://search.cpan.org/dist/Text-Balanced/" target="_blank">Text::Balanced</a> originally by Damian Conway and now maintained by <a href="http://search.cpan.org/~adamk/" target="_blank">Adam Kennedy</a> makes short work of this extraction for:</p>
<ul style="clear: both">
<li>strings delimited by the same single character</li>
<li>strings delimited by brackets of some sort (parens, square brackets, etc.)</li>
<li>strings delimited by XML or other kinds of tags</li>
<li>strings delimited by Perl quoting operators</li>
<li>code blocks</li>
</ul>
<p>Each kind of delimited string has its own function, e.g. <span class="function">extract_bracketed()</span>. For the most part, they all work like this:</p>
<pre class="brush: perl;">my ($extracted,$remainder) =
        extract_something($extract_from, $delimiter, $opt_prefix);</pre>
<p>where you have a function called <span class="function">extract_<em>something</em>()</span> that takes the string to extract the data from, the delimiter that surrounds the data in question, and an optional prefix. That last argument reveals a part of <span class="modulename">Text::Balanced</span> that tends to confuse people so we&#8217;ll look more at it in a second. The <span class="function">extract_<em>something()</em></span> functions return (in a list context) the first extracted piece of data and what was left over or just the extracted data in a scalar context (with alas, another twist).</p>
<p>There are two things about this module that tend to trip up newcomers:</p>
<ol>
<li>By default (i.e. without the optional third argument), the extraction functions all expect the data they are going to extract to be found either right at the beginning of the string or right at the position in the string that the last extraction left off. If you expect it to skip over non-delimited data that isn&#8217;t just whitespace, you will have to provide that third <span class="variable">$opt_prefix</span> argument.</li>
<li>When called in a scalar context, the extraction functions eat the text. Extracted strings are removed from the input text. Fans of functional or immutable data structure programming will not be pleased.</li>
</ol>
<p>If you do want to do <span class="function">split()</span> on steroids kind of stuff, <span class="modulename">Text::Balanced</span> also offers a <span class="function">extract_multiple()</span> function that takes a list of extraction functions, each of which gets run over the string, returning what they collectively find. <span class="modulename">Text::Balanced</span> can also make Friedl proud by generating optimal regular expressions for balanced matches that you can use with a minimum of head scratching.</p>
<p>If you need something to extract data matched delimiters of almost all sorts, this module will be spot on for you and will do its job like a laser beam.
<div class='footnotes'>
<div class='footnotedivider'></div>
<ol>
<li id='fn-285-1'>and if you haven&#8217;t&#8211;you really should. It is a bit light on plot and character development, but it is definitely required reading <span class='footnotereverse'><a href='#fnref-285-1'>&#8617;</a></span></li>
<li id='fn-285-2'>the other being validating email addresses, but that&#8217;s a post for another day <span class='footnotereverse'><a href='#fnref-285-2'>&#8617;</a></span></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.otterbook.com/blog/2009/07/pmotd-textbalanced/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PMotD: Devel::Deprecate</title>
		<link>http://www.otterbook.com/blog/2009/07/perl-module-of-the-day-develdeprecate/</link>
		<comments>http://www.otterbook.com/blog/2009/07/perl-module-of-the-day-develdeprecate/#comments</comments>
		<pubDate>Tue, 28 Jul 2009 03:51:29 +0000</pubDate>
		<dc:creator>dnb</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[hacks]]></category>
		<category><![CDATA[modules]]></category>

		<guid isPermaLink="false">http://www.otterbook.com/?p=246</guid>
		<description><![CDATA[Today&#8217;s interesting Perl module of the Day:  Devel::Deprecate by Curtis &#8220;Ovid&#8221; Poe.
Back in 2000, I started teaching a class called &#8220;Perl Saves the Day: Writing Small Perl Programs to Get Out of Big SysAdmin Pinches&#8221; which was essentially a class about Perl hacks and how to use them responsibly in System Administration. One of my slides [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Today&#8217;s interesting Perl module of the Day:  <a href="http://search.cpan.org/~ovid/Devel-Deprecate/">Devel::Deprecate</a> by Curtis &#8220;Ovid&#8221; Poe.</p>
<p>Back in 2000, I started teaching a <a href="http://www.otterbook.com/the-classes/">class</a> called &#8220;Perl Saves the Day: Writing Small Perl Programs to Get Out of Big SysAdmin Pinches&#8221; which was essentially a class about Perl hacks and how to use them responsibly in System Administration. One of my slides was &#8220;How to Get Rid of Hacks,&#8221; which started with:</p>
<blockquote><p>It can be hard. You may have to wait for the rewrite.<br />
Step one: remember you did it.</p>
<ul>
<li>Go back and document the code after the crisis.</li>
<li>Send yourself mail.</li>
<li>Set up an AT job.</li>
<li>Put it in your calendar.</li>
</ul>
</blockquote>
<p>Now there&#8217;s an even cooler way: <span class="modulename">Devel::Deprecate</span>. <span class="modulename">Devel::Deprecate</span> provides a <span class="function">deprecate()</span> function that let&#8217;s you write code like this (to quote the doc):</p>
<pre class="brush: perl;">deprecate (
    reason =&gt; 'Please use the set_name() method for setting names',
    warn   =&gt; '2008-11-01',    # also accepts DateTime objects
    die    =&gt; '2009-01-01',    # two month deprecation period
);</pre>
<p><span class="function">deprecate()</span> only comes into play when the code is run during a test (which you are writing, right?). Each time it is run under this condition (and only this condition, it never comes into play when the code is run outside of a test), it produces output that is crystal clear:</p>
<pre># DEPRECATION WARNING
#
# Package:     Our::Customer
# File:        lib/Our/Customer.pm
# Line:        58
# Subroutine:  Our::Customer::name
#
# Reason:      Please use the set_name() method for setting names
#
# This warning becomes FATAL on (2009-01-01)</pre>
<p>After the due date, it blows up just as promised with an equally verbose message. Very cool.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.otterbook.com/blog/2009/07/perl-module-of-the-day-develdeprecate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>And We Have a Winner!</title>
		<link>http://www.otterbook.com/blog/2009/07/and-we-have-a-winner/</link>
		<comments>http://www.otterbook.com/blog/2009/07/and-we-have-a-winner/#comments</comments>
		<pubDate>Mon, 13 Jul 2009 04:12:07 +0000</pubDate>
		<dc:creator>dnb</dc:creator>
				<category><![CDATA[book]]></category>
		<category><![CDATA[errata]]></category>

		<guid isPermaLink="false">http://www.otterbook.com/?p=213</guid>
		<description><![CDATA[Kudos goes to Thomas Leyer of Germany for finding the very first typo in the printed version of the book. Books like these have an amazing amount of detail so it is not uncommon for a few small things to slip through (in this case it was a single missing dash).
I&#8217;m very thankful when readers [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Kudos goes to Thomas Leyer of Germany for finding the very first typo in the printed version of the book. Books like these have an amazing amount of detail so it is not uncommon for a few small things to slip through (in this case it was a single missing dash).</p>
<p>I&#8217;m very thankful when readers take the time to report errors they find so I can correct them in a future printing. I really appreciate it when others are willing to help me make this book better in whatever fashion I can. If you do spot something, please report it through the book&#8217;s <a href="http://oreilly.com/catalog/9780596006396/errata/">errata page</a>. I&#8217;ll get a little note if you do and then I can make sure it is dealt with appropriately.</p>
<p>Thanks, Thomas!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.otterbook.com/blog/2009/07/and-we-have-a-winner/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
