<?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>searching for signal &#187; agriffis</title>
	<atom:link href="http://blog.n01se.net/?feed=rss2&#038;author=2" rel="self" type="application/rss+xml" />
	<link>http://blog.n01se.net</link>
	<description>theoretically unambiguous</description>
	<lastBuildDate>Sun, 29 Aug 2010 20:21:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>How to capture httplib2 debug in a threaded app</title>
		<link>http://blog.n01se.net/?p=218</link>
		<comments>http://blog.n01se.net/?p=218#comments</comments>
		<pubDate>Sun, 29 Aug 2010 20:06:35 +0000</pubDate>
		<dc:creator>agriffis</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[httplib]]></category>

		<guid isPermaLink="false">http://blog.n01se.net/?p=218</guid>
		<description><![CDATA[A couple months ago I blogged about my frustration with httplib logging. Andrew Dalke left a comment suggesting that I should replace sys.stdout, something I hadn't considered as a possibility. His suggestion sent me googling, which turned up this old email from Guido. Add threading.local and we have a solution! What we need is a [...]]]></description>
			<content:encoded><![CDATA[<p>A couple months ago I blogged about <a href="http://blog.n01se.net/?p=213">my frustration with httplib logging</a>. Andrew Dalke <a href="http://blog.n01se.net/?p=213#comment-2315">left a comment</a> suggesting that I should replace <a href="http://docs.python.org/library/sys.html#sys.stdout">sys.stdout</a>, something I hadn't considered as a possibility. His suggestion sent me googling, which turned up this <a href="http://n01se.net/paste/sM72">old email from Guido</a>. Add <a href="http://docs.python.org/library/threading.html#threading.local">threading.local</a> and we have a solution!</p>
<p>What we need is a duck-typed replacement for sys.stdout that behaves like a writeable file, but also provides the ability to capture to thread-local storage. One of the ways to use threading.local is to subclass it. An instance of this subclass will have per-thread attributes, even if the instance itself is common to multiple threads.</p>
<p>Since <a href="http://docs.python.org/library/stringio.html">StringIO</a> intentionally doesn't implement isatty(), we need to make sure that gets passed through to the underlying file (we do this by catching the exception in getattr). And since we like seeing HTTP transactions when we're debugging, we include a writethrough mode that provides simultaneous capture and print.</p>
<pre class="brush:python;gutter:false">
import cStringIO, threading

class LocalCapturingWriter(threading.local):
    def __init__(self, fp, writethrough=False):
        self.__dict__['_fp'] = fp
        self.__dict__['_stringio'] = None
        self.__dict__['_writethrough'] = writethrough

    def start_capture(self):
        self.__dict__['_stringio'] = cStringIO.StringIO()

    def stop_capture(self):
        v = self._stringio.getvalue()
        self._stringio.close()
        self.__dict__['_stringio'] = None
        return v

    def write(self, s):
        if self._stringio:
            result = self._stringio.write(s)
        if not self._stringio or self._writethrough:
            result = self._fp.write(s)
        return result

    def __getattr__(self, name):
        if self._stringio is not None:
            try:
                return getattr(self._stringio, name)
            except:
                pass
        return getattr(self._fp, name)

    def __setattr__(self, name, value):
        if self._stringio:
            setattr(self._stringio, name, value)
        if not self._stringio or self._writethrough:
            setattr(self._fp, name, value)
</pre>
<p>And here's how to use it. First, the global settings:</p>
<pre class="brush:python;gutter:false">
import httplib2, sys

httplib2.debuglevel = 1

sys.stdout = LocalCapturingWriter(sys.stdout)
</pre>
<p>Then the code that runs in a thread to capture the debugging output. This will work as expected even in multiple threads simultaneously.</p>
<pre class="brush:python;gutter:false">
sys.stdout.start_capture()
try:
    response, content = \
        httplib2.Http().request("http://n01se.net")
finally:
    debug_trace = sys.stdout.stop_capture()

# Note that httplib2 doesn't include the content in its
# debug output.
debug_trace += "content: %r\n" % content
</pre>
<p>We're now using this in our Django app, with a custom Exception class (to hold the captured trace) and middleware that knows to look for it. The end result is that every time an exception occurs due to a problem talking to a backend server, the exception email includes the httplib2 trace. Yeah!</p>
<p>P.S. I wrote this entry less than a week after my previous entry, but then went on vacation and never managed to get it posted. Sorry for the delay...</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.n01se.net/?feed=rss2&amp;p=218</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python&#8217;s httplib uses print for debugging. Oh, it hurts&#8230;</title>
		<link>http://blog.n01se.net/?p=213</link>
		<comments>http://blog.n01se.net/?p=213#comments</comments>
		<pubDate>Sun, 04 Jul 2010 18:12:24 +0000</pubDate>
		<dc:creator>agriffis</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[grumpy]]></category>
		<category><![CDATA[httplib]]></category>

		<guid isPermaLink="false">http://blog.n01se.net/?p=213</guid>
		<description><![CDATA[At work we have a production site that uses httplib (via httplib2) on the server to communicate with internal servers using a RESTful API. When something doesn't work as expected in this process, we like to know about it, so our app sends email with the exception traceback and whatever relevant data we can pull [...]]]></description>
			<content:encoded><![CDATA[<p>At work we have a production site that uses httplib (via httplib2) on the server to communicate with internal servers using a RESTful API. When something doesn't work as expected in this process, we like to know about it, so our app sends email with the exception traceback and whatever relevant data we can pull together.</p>
<p>One of the pieces of data I'd like to add to the email is the conversation between our server and the internal servers. On a development server, this is easy: Set httplib2.debuglevel=1 and watch the HTTP conversations scroll past on stdout.</p>
<p>On a staging or production server, one quickly discovers a crippling mistake made by the httplib authors: the library uses Python's "print" for debugging!</p>
<p>If the application were single-threaded, we could capture the trace by temporarily redirecting sys.stdout to an instance of StringIO (maybe using a context manager). Sure, it's more load on the server to capture the debug on every transaction, but I'll gladly pay that price for the hours we'll save when something goes wrong and we have the ability to debug it.</p>
<p>But it doesn't matter, because we haven't this option. Our app is multi-threaded and sys.stdout is global. We would have to serialize our HTTP transactions to prevent traces from being mixed together. Or fork to isolate sys.stdout. These aren't realistic approaches.</p>
<p>This sort of unfortunate shortcoming is to be expected in add-on libraries. After all, part of the reason they're not included with Python is that they don't necessarily meet the quality requirements of the core distribution. But I'm taken off-guard to find such an obvious shortcoming in the Python standard library. One of the things I'd hope to assume by using the standard library is a trust in the quality of the implementation, but a discovery like this forces me to question that assumption.</p>
<p>I'm pretty new to Python, so maybe I'm missing something. Is httplib a particularly poor example of the Python standard library? The existence of httplib2 seems to imply that (and also seems to imply that it's hard to get problems fixed in the core distribution). Maybe I need to find an add-on networking library that ignores httplib entirely...?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.n01se.net/?feed=rss2&amp;p=213</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>a common css mistake</title>
		<link>http://blog.n01se.net/?p=203</link>
		<comments>http://blog.n01se.net/?p=203#comments</comments>
		<pubDate>Sat, 15 May 2010 03:39:13 +0000</pubDate>
		<dc:creator>agriffis</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.n01se.net/?p=203</guid>
		<description><![CDATA[I'm playing with febootstrap this evening, part of a continuing migration away from Ubuntu toward Debian and Fedora. I googled my way to Rich's febootstrap page. On my browser, it looks like this: The problem is that the page's css has the following rules: h1, h2, h3, h4 { color: #333; } pre { background-color: [...]]]></description>
			<content:encoded><![CDATA[<p>I'm playing with febootstrap this evening, part of a continuing migration away from Ubuntu toward Debian and Fedora. I googled my way to <a href="http://people.redhat.com/~rjones/febootstrap/">Rich's febootstrap page</a>. On my browser, it looks like this:</p>
<p><a href="http://blog.n01se.net/wp-content/uploads/2010/05/febootstrap-css-mistake2.png"><img src="http://blog.n01se.net/wp-content/uploads/2010/05/febootstrap-css-mistake2-e1273894578460.png" alt="" title="febootstrap-css-mistake" width="399" height="256" class="aligncenter size-full wp-image-209" /></a></p>
<p>The problem is that the page's css has the following rules:</p>
<pre class="brush:css;gutter:false">
h1, h2, h3, h4 {
  color: #333;
}

pre {
  background-color: #fcfcfc;
}
</pre>
<p>Both these rules assume the usual black-on-white color scheme, but I'm using a gtk theme with a dark background and light foreground, which firefox respects.  (Chromium doesn't have the issue because it enforces black-on-white defaults regardless of the gtk theme. I'm not sure how I feel about that; it fixes the problem but at the expense of ignoring my theme.)</p>
<p>This isn't to say anything bad about febootstrap, of course. I'm thrilled that somebody has finally written for Fedora what the excellent debootstrap has been providing for Debian and Ubuntu users for years! But I've come across this mistake enough times that Rich's site drew the unlucky number. <img src='http://blog.n01se.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.n01se.net/?feed=rss2&amp;p=203</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>daemonizing bash</title>
		<link>http://blog.n01se.net/?p=145</link>
		<comments>http://blog.n01se.net/?p=145#comments</comments>
		<pubDate>Tue, 20 Apr 2010 16:32:07 +0000</pubDate>
		<dc:creator>agriffis</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[APUE]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[daemon]]></category>
		<category><![CDATA[setsid]]></category>

		<guid isPermaLink="false">http://blog.n01se.net/?p=145</guid>
		<description><![CDATA[Before we jump into this, let's be clear about intent: There are better languages for writing daemons than bash. Honestly, any other language is probably a better choice. Writing a daemon implies that you're writing a sufficiently complex program that bash is already the wrong language, with or without daemonization! But if you find yourself [...]]]></description>
			<content:encoded><![CDATA[<p>Before we jump into this, let's be clear about intent: There are better languages for writing daemons than <a href="http://tiswww.case.edu/php/chet/bash/bashtop.html">bash</a>. Honestly, <i>any other language</i> is probably a better choice. Writing a daemon implies that you're writing a sufficiently complex program that bash is already the wrong language, with or without daemonization!</p>
<p>But if you find yourself in the unfortunate position of needing to daemonize an existing bash program, and you'd rather put off rewriting it in a more suitable language, keep reading! I found myself in that position recently and kept some notes.</p>
<p>Daemonizing a process consists of two primary tasks: forking to the background to return control to the shell, and preventing undesirable interaction between the process and the host. Rich Stevens enumerated the steps in his classic <a href="http://www.apuebook.com/">Advanced Programming in the UNIX Environment</a>. Here's my summary of his formula with implementation notes for bash.</p>
<ol>
<li><i>Call <a href="http://linux.die.net/man/2/fork">fork</a> (to guarantee the child is not a process group leader, necessary for setsid) and have the parent exit (to allow control to return to the shell).</i></p>
<p>Forking in bash is a simple matter of putting a command in the background using "&#038;". To put a sequence of commands in the background, use a subshell: "( commands ) &#038;". Note that bash doesn't provide any method for the child process to continue the same execution path as the parent, so the entirety of the child must be contained in the subshell. The easiest way to do this is implement the child as a bash function: "childfunc &#038;".</li>
<li><i>Call <a href="http://linux.die.net/man/2/setsid">setsid</a> to create a new session so the child has no controlling terminal. This simultaneously prevents the child from gaining access to the controlling terminal (using /dev/tty) and protects the child from signals originating from the controlling terminal (HUP and INT, for example).</i>
<p>Bash provides no method to call the setsid syscall for the current process. We have two less-than-ideal alternatives:</p>
<ol type=a>
<li>The <a href="http://userweb.kernel.org/~kzak/util-linux-ng/">util-linux-ng</a> package provides an external <a href="http://linux.die.net/man/1/setsid">setsid</a> command but this daemonizes an external command rather than the currently running script. It also makes collecting the PID of the child tricky because the setsid command will fork internally.</p>
<p>Having said all that, if your application allows you to use the setsid command, it's a good choice because bash can't otherwise fully protect against the child process opening /dev/tty. It's still a good idea to redirect std* to prevent stray output to the terminal.</li>
<li>Lacking the setsid syscall, there are steps we can take to partially protect the child process from the effects of the controlling terminal:
<ol type=i>
<li>Redirect std* to files or /dev/null</li>
<li>Guard against HUP and INT by signal handler in child</li>
<li>Guard against HUP by disown -h in parent</li>
</ol>
<p>Unfortunately without setsid there is no way to guard completely against a subchild opening /dev/tty until the terminal emulator exits, then /dev/tty will become unavailable.</li>
</ol>
<li><i>Change working directory to / to prevent the daemon from holding a mounted filesystem open.</i>
<p>Bash is good at this. <img src='http://blog.n01se.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </li>
<li><i>Set umask to 0 to clear file mode creation mask.</i>
<p>I have to admit that I can't understand the point of this, in bash or any other language. It seems to me that the child will either set its umask explicitly before creating files, or it will set individual file permissions explicitly, or it will fall back on the caller's umask. In the last case, I want my inherited umask, not the wide-open zero.</p>
<p>If anybody wants to explain a good reason for step 4, I'm all ears... Until then, it's commented out in my implementation below.</li>
<li><i>Close unneeded file descriptors.</i>
<p>This step is fun in bash using eval and brace expansion...</li>
</ol>
<p>With those notes in-hand, here's my implementation. There are two<br />
functions here, "daemonize" for an external command using setsid,<br />
"daemonize-job" for a function in the running script.</p>
<pre class="brush:bash;gutter:false">
# redirect tty fds to /dev/null
redirect-std() {
    [[ -t 0 ]] &amp;&amp; exec &lt;/dev/null
    [[ -t 1 ]] &amp;&amp; exec &gt;/dev/null
    [[ -t 2 ]] &amp;&amp; exec 2&gt;/dev/null
}

# close all non-std* fds
close-fds() {
    eval exec {3..255}\&gt;\&amp;-
}

# full daemonization of external command with setsid
daemonize() {
    (                   # 1. fork
        redirect-std    # 2.1. redirect stdin/stdout/stderr before setsid
        cd /            # 3. ensure cwd isn't a mounted fs
        # umask 0       # 4. umask (leave this to caller)
        close-fds       # 5. close unneeded fds
        exec setsid "$@"
    ) &amp;
}

# daemonize without setsid, keeps the child in the jobs table
daemonize-job() {
    (                   # 1. fork
        redirect-std    # 2.2.1. redirect stdin/stdout/stderr
        trap '' 1 2     # 2.2.2. guard against HUP and INT (in child)
        cd /            # 3. ensure cwd isn't a mounted fs
        # umask 0       # 4. umask (leave this to caller)
        close-fds       # 5. close unneeded fds
        if [[ $(type -t "$1") != file ]]; then
            "$@"
        else
            exec "$@"
        fi
    ) &amp;
    disown -h $!       # 2.2.3. guard against HUP (in parent)
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.n01se.net/?feed=rss2&amp;p=145</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>clock trick</title>
		<link>http://blog.n01se.net/?p=125</link>
		<comments>http://blog.n01se.net/?p=125#comments</comments>
		<pubDate>Wed, 10 Mar 2010 13:01:41 +0000</pubDate>
		<dc:creator>agriffis</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.n01se.net/?p=125</guid>
		<description><![CDATA[I bought a Sony &#34;Dream Machine&#34; Clock Radio about a year ago and have liked it except for one problem: even when the brightness is set to &#34;low&#34;, it's still too bright for my taste. Each night I have to rotate the clock away from me on the nightstand so I can fall asleep. This [...]]]></description>
			<content:encoded><![CDATA[
<div class="document">


<!-- -*- mode: rst -*- -->
<p>I bought a <a class="reference" href="http://www.sonystyle.com/webapp/wcs/stores/servlet/ProductDisplay?catalogId=10551&amp;storeId=10151&amp;productId=11033593&amp;langId=-1">Sony &quot;Dream Machine&quot; Clock Radio</a>
about a year ago and have liked it except for one problem: even when the
brightness is set to &quot;low&quot;, it's still too bright for my taste. Each night
I have to rotate the clock away from me on the nightstand so I can fall asleep.</p>
<p>This morning I applied <a class="reference" href="http://www.amazon.com/Insta-Cling-Windshield-Strip-Professional-Tint/dp/B000EBICN2">Insta-Cling Windshield Strip Professional Tint Film</a>
to the front and I think it's not bad for $4.88 and a few minutes with an x-acto
knife!</p>
<p>Here's the before/after (&quot;before&quot; courtesy of Amazon since I didn't think of
taking a photo):</p>
<img alt="http://agriffis.n01se.net/blog-images/clock-before-after.jpg" src="http://agriffis.n01se.net/blog-images/clock-before-after.jpg" />
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.n01se.net/?feed=rss2&amp;p=125</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>weechat, nopaste and tagver</title>
		<link>http://blog.n01se.net/?p=116</link>
		<comments>http://blog.n01se.net/?p=116#comments</comments>
		<pubDate>Mon, 22 Feb 2010 22:01:51 +0000</pubDate>
		<dc:creator>agriffis</dc:creator>
				<category><![CDATA[ramble]]></category>
		<category><![CDATA[bitlbee]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[irssi]]></category>
		<category><![CDATA[nopaste]]></category>
		<category><![CDATA[pidgin]]></category>
		<category><![CDATA[screen]]></category>
		<category><![CDATA[tagver]]></category>
		<category><![CDATA[weechat]]></category>

		<guid isPermaLink="false">http://blog.n01se.net/?p=116</guid>
		<description><![CDATA[This weekend I switched from irssi to weechat. The main reason I switched away from irssi was to gain support for protocols other than IRC. On the way to weechat, I tried Pidgin but I was immediately frustrated by two things. First, I really love running my IM client in screen. I move regularly between [...]]]></description>
			<content:encoded><![CDATA[
<div class="document">


<!-- -*- mode: rst -*- -->
<p>This weekend I switched from <a class="reference" href="http://irssi.org">irssi</a> to <a class="reference" href="http://weechat.org">weechat</a>. The main reason I switched away from irssi was to gain
support for protocols other than IRC. On the way to weechat, I tried <a class="reference" href="http://pidgin.im">Pidgin</a> but I was immediately frustrated by two things.</p>
<p>First, I really love running my IM client in <a class="reference" href="http://www.gnu.org/software/screen/">screen</a>. I move regularly between three machines
and I want persistent connectivity despite changing work context. Screen has
provided that beautifully over the years and I don't know of any truly
comparable technology for graphical programs.</p>
<p>Second, Pidgin seems to be barely customizable. For example, how would you like
your timestamps? You have three choices:</p>
<ul class="simple">
<li>(HH:MM:SS)</li>
<li>occasional iChat-style interruptions</li>
<li>no timestamps</li>
</ul>
<p>The Pidgin FAQ <a class="reference" href="http://developer.pidgin.im/wiki/Using%20Pidgin#WhathappenedtomytimestampsCanIchangethem">calls out plugins</a>
to customize timestamps but they're woefully underpowered. What I want
is to supply a strftime-style format string: %H:%M. It seems
preposterous to me that Pidgin wouldn't provide this capability, so maybe I'm
just missing it?</p>
<p>In any case, irssi and weechat both make this and other customizations easy. It
took about one minute to find and change the setting in weechat:</p>
<pre class="literal-block">
/set weechat.look.buffer_time_format &quot;%H:%M&quot;
</pre>
<p>Once I got weechat running, I found to my chagrin that I'd imagined weechat's
support for other protocols. The front page mentions Jabber but it's still
a work in progress; there's no stable support for anything other than IRC.</p>
<p>I was saved by <a class="reference" href="http://www.bitlbee.org/main.php/news.r.html">bitlbee</a>, a standalone server that
gateways IM protocols (XMPP/Jabber, MSN Messenger, Yahoo! Messenger, AIM and
ICQ) to IRC.  Installing and configuring bitlbee took all of five minutes
since <a class="reference" href="http://packages.ubuntu.com/bitlbee">it's in Ubuntu</a> and there's
a super-easy <a class="reference" href="http://princessleia.com/bitlbee.php">quickstart guide</a>.</p>
<p>Of course this means that I could have stayed on
irssi! But weechat seems to be a worthy replacement.  It
has a built in nicklist which has always been missing from irssi. It
handles filtering better than irssi; whereas irssi's /ignore discards
information, weechat's /filter simply hides it and you can <a class="reference" href="http://weechat.org/files/doc/stable/weechat_user.en.html#key_bindings_other">toggle
filtered text with alt+=</a>.
That means I can filter <em>more</em> aggressively because I don't have to worry about
irretrievably missing something important.</p>
<p>We are, after all, searching for signal. (And good luck finding it in this
post.)</p>
<p>One thing I liked from my brief experience with pidgin was libnotify alerts. You
know, that little box that pops up so you don't need to keep your IM client on
the screen at all times:</p>
<img alt="http://agriffis.n01se.net/blog-images/libnotify-chuck.png" src="http://agriffis.n01se.net/blog-images/libnotify-chuck.png" />
<p>There's a <a class="reference" href="http://weechat.org/files/scripts/notify.py">weechat notify script</a> that provides this
functionality but it had some bugs. No problem, fixed them, then tried
to <a class="reference" href="http://weechat.org/scripts/update/">submit my update to the site</a>. The upload form suggests using
pastebin, so I broke out my own <a class="reference" href="http://agriffis.n01se.net/nopaste">nopaste tool</a> and...</p>
<p>It failed. Where I expected to get a link, I got nothing! It seems
<a class="reference" href="http://pastebin.com">Pastebin.com</a> <a class="reference" href="http://twitter.com/pastebincom/status/9345479627">recently switched</a> to a custom
httpd:</p>
<pre class="literal-block">
$ curl -I http://pastebin.com/
HTTP/1.1 200 OK
Content-Type: text/html; charset=iso-8859-1
Date: Mon, 22 Feb 2010 20:37:36 GMT
Server: TorrentFly.org Custom Httpd
</pre>
<p>Curl sees &quot;HTTP/1.1&quot; and tries to be polite by using the
<a class="reference" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.3">100-continue Expect request-header field</a>.
Unfortunately the TorrentFly.org Custom Httpd doesn't grok the request
and halts the transaction with <a class="reference" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.20">417 (Expectation Failed)</a>.</p>
<p>Fine, it's an easy fix to force HTTP/1.0 and work around the broken server:</p>
<pre class="literal-block">
--- a/nopaste
+++ b/nopaste
&#64;&#64; -52,7 +52,7 &#64;&#64; main() {

 docurl() {
     declare u
-    u=$(curl --silent --show-error -o /dev/null -w &quot;%{redirect_url}\n&quot; \
+    u=$(curl -0 --silent --show-error -o /dev/null -w &quot;%{redirect_url}\n&quot; \
         --form-string &quot;poster=$opt_nick&quot; --form-string &quot;format=$opt_language&quot; \
         --form-string &quot;expiry=$expire&quot; \
         ${opt_parent:+--form-string &quot;parent_pid=$opt_parent&quot;} \
</pre>
<p>This reminded me that nopaste should be in externally-available source
control so I created a <a class="reference" href="http://github.com/agriffis/nopaste">github project</a> for it. This is the first time
I've used github to publish a project of my own and I can only say:
Wow, that was easy.</p>
<p>I thought it would also be nice to publish proper releases of nopaste.
In the past I've simply provided the individual file with a version
number appended. Since I'm using git, I should be able to do something
nifty with tags, right?</p>
<p>Enter <a class="reference" href="http://github.com/agriffis/tagver">tagver</a>, a script to
generate a &quot;meaningful&quot; version number based on tags, revisions and
dirt. I've re-invented this wheel a few times, for example <a class="reference" href="http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=3dce174cfcba11026b028d33bed0438b80e37124;hp=2f4b489b77c68b9cba1bd9dec5a1bbf0ab3c47f8">adding
mercurial support to setlocalversion</a>,
but this is the first time I've made it a project in its own right.</p>
<p>Using tagver I released tarballs and an
rpm for nopaste version 2.3 containing this trivial fix. You can find them both
at <a class="reference" href="http://agriffis.n01se.net/nopaste">http://agriffis.n01se.net/nopaste</a>. I'm
not really satisfied with the <a class="reference" href="http://github.com/agriffis/nopaste/blob/master/Makefile">Makefile</a> that calls tagver,
but it'll do for now, at least until I look into integrating tagver into an
autotools-driven distribution. Or <a class="reference" href="http://cmake.org">cmake</a> or <a class="reference" href="http://scons.org">scons</a> or <a class="reference" href="http://www.dsmit.com/cons/">cons</a> or whatever...</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.n01se.net/?feed=rss2&amp;p=116</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Live migration to RAID-1</title>
		<link>http://blog.n01se.net/?p=51</link>
		<comments>http://blog.n01se.net/?p=51#comments</comments>
		<pubDate>Mon, 09 Nov 2009 01:12:56 +0000</pubDate>
		<dc:creator>agriffis</dc:creator>
				<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[lvm]]></category>
		<category><![CDATA[md]]></category>
		<category><![CDATA[parted]]></category>
		<category><![CDATA[raid]]></category>

		<guid isPermaLink="false">http://blog.n01se.net/?p=51</guid>
		<description><![CDATA[I've blogged about using md with lvm before. This weekend I came to appreciate it even more when I migrated a live system from single disk to RAID-1 without needing to unmount or reboot. Here's the overview of the steps I used: Create a RAID-1 on the second disk (sdb). It's initially degraded, meaning that [...]]]></description>
			<content:encoded><![CDATA[
<div class="document">


<!-- -*- mode: rst -*- -->
<p>I've blogged about <a class="reference" href="http://blog.n01se.net/?p=6">using md with lvm</a> before.
This weekend I came to appreciate it even more when I migrated a live system
from single disk to RAID-1 without needing to unmount or reboot.  Here's the
overview of the steps I used:</p>
<ol class="arabic simple">
<li>Create a RAID-1 on the second disk (sdb). It's initially degraded, meaning
that even though we're accessing it as md0, there's only one disk in the
array.</li>
<li>Migrate data from the first disk (sda) to the newly-created md0.</li>
<li>Now that sda is freed up, add it to the array to make it a mirror.</li>
</ol>
<p>Reviewing my system inventory, I have two 500G disks but I'm only using one of
them, hosting logical volumes for root, swap, four nfsroots, and two (running)
KVM virtual machines.  Apart from the large partition holding the logical
volumes, I also have a couple small partitions for Windows 7 (I don't actually
use it but it's there in case I need to call for warranty support). The other
disk is blank and idle.  I installed it some time back when I had the machine
powered off, though I could have attached it with eSATA to avoid even that
interruption.</p>
<p>Here's the partition table from that first disk:</p>
<pre class="literal-block">
$ sudo parted /dev/sda
(parted) unit kB
(parted) print
Model: ATA WDC WD5000AAKS-6 (scsi)
Disk /dev/sda: 500107862kB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number  Start       End          Size         Type      File system  Flags
 1      1049kB      6443500kB    6442451kB    primary   ntfs         boot
 2      6443500kB   46443500kB   40000000kB   primary   ntfs
 3      46448156kB  47443415kB   995259kB     primary   ext3
 4      47443415kB  500105249kB  452661834kB  extended
 5      47443447kB  500105249kB  452661802kB  logical                lvm
</pre>
<p>and here's the volume groups and logical volumes, annotated a bit:</p>
<pre class="literal-block">
$ sudo vgs
  VG   #PV #LV #SN Attr   VSize   VFree
  vg0    1  10   0 wz--n- 421.57G 250.40G

$ sudo lvs
LV         VG   Attr   LSize
jabberwock vg0  -wi-ao  9.31G  # host root filesystem
swap       vg0  -wi-ao  1.86G  # host swap
jubjub     vg0  -wi-ao 20.00G  # jubjub VM disk
agriffis   vg0  -wi-ao 50.00G  # my $HOME, jubjub VM second disk
oliva      vg0  -wi-a- 20.00G  # oliva VM disk
amg        vg0  -wi-a- 50.00G  # Amy's $HOME, oliva VM second disk
nord       vg0  -wi-ao  5.00G  # thin client nfsroot
sud        vg0  -wi-ao  5.00G  # thin client nfsroot
parmigiano vg0  -wi-ao  5.00G  # thin client nfsroot
romano     vg0  -wi-ao  5.00G  # thin client nfsroot
</pre>
<p>For the partition listing, I used units of kB because that makes it easier to
be sure the partitions are exactly the same size when I apply them to the second
disk.  I'll initially create the RAID-1 with only sdb5 (a degraded array), then
later I'll add sda5 to md0 to make it a mirror.  For this reason, it's important
that the two partitions that will eventually make up md0 are exactly the same
size.</p>
<p>Here's the application of that partition table to the second disk.  Note I'm not
going to actually use the first few partitions there, but I create them anyway
for the sake of symmetry:</p>
<pre class="literal-block">
$ sudo parted /dev/sdb
(parted) unit kB
(parted) mklabel msdos
(parted) mkpart primary  1049kB     6443500kB
(parted) mkpart primary  6443500kB  46443500kB
(parted) mkpart primary  46448156kB 47443415kB
(parted) mkpart extended 47443415kB 500105249kB
(parted) mkpart logical  47443447kB 500105249kB
(parted) set 5 raid on
(parted) print
Model: ATA ST3500418AS (scsi)
Disk /dev/sdb: 500107862kB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number  Start       End          Size         Type      File system  Flags
 1      1049kB      6443500kB    6442451kB    primary
 2      6443500kB   46443500kB   40000000kB   primary
 3      46448156kB  47443415kB   995259kB     primary
 4      47443415kB  500105249kB  452661834kB  extended               lba
 5      47443447kB  500105249kB  452661802kB  logical                raid
</pre>
<p>Now create the RAID-1 and extend the volume group to it:</p>
<pre class="literal-block">
$ sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb5 missing
$ sudo pvcreate /dev/md0
$ sudo vgextend vg0 /dev/md0
</pre>
<p>Move the data hosted on sda5 to md0. Note pvmove reports an error, but when
I try to continue the operation, it reports that it's already done, so I don't
think this is a real problem:</p>
<pre class="literal-block">
$ sudo pvmove /dev/sda5 /dev/md0
/dev/sda5: Moved: 99.9%
ABORTING: Can't find mirror LV in vg0 for /dev/sda5

$ sudo pvmove /dev/sda5 /dev/md0
No data to move for vg0
</pre>
<p>Now remove sda5 from the volume group and add it to md0:</p>
<pre class="literal-block">
$ sudo vgreduce vg0 /dev/sda5
$ sudo pvremove /dev/sda5
$ sudo parted /dev/sda set 5 lvm off set 5 raid on
$ sudo mdadm /dev/md0 --add /dev/sda5
</pre>
<p>And see that it's working:</p>
<pre class="literal-block">
$ cat /proc/mdstat
Personalities : [raid1]
md0 : active raid1 sda5[2] sdb5[0]
      442052416 blocks [2/1] [U_]
      [&gt;....................]  recovery =  0.0% (288512/442052416)
      finish=153.1min speed=48085K/sec
</pre>
<p>Finally, add the info
to the mdadm config and regenerate the initrd to make sure md0 is found when the
system eventually reboots. I found that I had to remove the &quot;metadata&quot; tag from
the generated config line, YMMV:</p>
<pre class="literal-block">
$ sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf
ARRAY /dev/md0 level=raid1 num-devices=2 metadata=00.90 UUID=4aa66439:62c76598:cb06150d:d44aeb51
$ sudo vim /etc/mdadm/mdadm.conf  # to remove &quot;metadata=00.90&quot;
$ sudo update-initramfs -u -k all
</pre>
<p>All this without any interruption to the system operation!</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.n01se.net/?feed=rss2&amp;p=51</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>SHA1 broken by US Government</title>
		<link>http://blog.n01se.net/?p=40</link>
		<comments>http://blog.n01se.net/?p=40#comments</comments>
		<pubDate>Tue, 07 Jul 2009 15:08:15 +0000</pubDate>
		<dc:creator>agriffis</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.n01se.net/?p=40</guid>
		<description><![CDATA[...but not in the way you might expect. One of us noisers (Gerry Leach) tried to use the Argonne National Laboratory's implementation of SHA1 to double-check his own computations. What he found was a bit of a surprise, to say the least... Given the input string 1316798755 the above site returns DA39A3EE5E6B4BD3255BFEF95601890AFD879. One wouldn't normally [...]]]></description>
			<content:encoded><![CDATA[
<div class="document">


<!-- -*- mode: rst -*- -->
<p>...but not in the way you might expect.  One of us noisers (Gerry Leach) tried to
use the <a class="reference" href="http://www.anl.gov/">Argonne National Laboratory's</a> <a class="reference" href="http://bioinformatics.anl.gov/ws/sha1.asmx?op=SHA1B16Digest">implementation
of SHA1</a> to
double-check his own computations.  What he found was a bit of a surprise, to
say the least...</p>
<p>Given the input string <tt class="docutils literal"><span class="pre">1316798755</span></tt> the above site returns
<tt class="docutils literal"><span class="pre">DA39A3EE5E6B4BD3255BFEF95601890AFD879</span></tt>.  One wouldn't normally question this
result, coming from a national laboratory, except that it didn't match Gerry's
local tests, nor does it match mine:</p>
<pre class="literal-block">
$ echo -n 1316798755 | sha1sum | tr '[:lower:]' '[:upper:]'
A897C3B9E5A64D609A1D7DB3D1D7F4C03C3F00A1  -
</pre>
<p>Bob Bell quickly pointed out the similarity of the site's computation to the
SHA1 of the empty string:</p>
<pre class="literal-block">
$ sha1sum &lt;/dev/null | tr '[:lower:]' '[:upper:]'
DA39A3EE5E6B4B0D3255BFEF95601890AFD80709  -
DA39A3EE5E6B4BD3255BFEF95601890AFD879 (output from ANL)
</pre>
<p>After a few more tests, Bob enumerated the issues with the site's computation:</p>
<ul class="simple">
<li>First, it strips any non-alpha characters from the input, including digits and
whitespace.</li>
<li>Then it converts lowercase input to uppercase, so the result for &quot;foobar&quot; is
the same as the result for &quot;FOOBAR&quot;, but even so the final answer is wrong
because...</li>
<li>It prints the result as a string of bytes using <tt class="docutils literal"><span class="pre">%X</span></tt> instead of <tt class="docutils literal"><span class="pre">%02X</span></tt>, so
the output drops leading zeroes in the hex representation of each byte.</li>
</ul>
<!-- Here's a shell implementation of the ANL's SHA1 algorithm.  It takes some effort -->
<!-- to screw up so badly:: -->
<!--  -->
<!-- tr -cd '[:alpha:]' | tr '[:lower:]' '[:upper:]' | sha1sum | \ -->
<!-- for ((i=0; i<20; i++)); do read -n2 byte; printf "%X" $((0x$byte)); done; echo -->
<p>I wonder what Argonne is doing with this particular calculator...  Dare we hope for...  nothing?</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.n01se.net/?feed=rss2&amp;p=40</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Firefox profiles on Ubuntu</title>
		<link>http://blog.n01se.net/?p=28</link>
		<comments>http://blog.n01se.net/?p=28#comments</comments>
		<pubDate>Tue, 10 Jun 2008 20:18:28 +0000</pubDate>
		<dc:creator>agriffis</dc:creator>
				<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://blog.n01se.net/?p=28</guid>
		<description><![CDATA[Running multiple simultaneous Firefox profiles is broken on Ubuntu. It works fine on Debian and Gentoo, among others. I don't know if the Ubuntu maintainer is refusing to fix it on the basis that it's an upstream problem, or if they just haven't looked at what the other distros are doing... Anyway, it's pretty easy [...]]]></description>
			<content:encoded><![CDATA[
<div class="document">


<!-- -*- mode: rst -*- -->
<p>Running multiple simultaneous Firefox profiles is
<a class="reference" href="https://bugs.launchpad.net/firefox/+bug/31746">broken on Ubuntu</a>.  It works fine on Debian and Gentoo, among others.  I don't
know if the Ubuntu maintainer is refusing to fix it on the basis that it's an
upstream problem, or if they just haven't looked at what the other distros are
doing...</p>
<p>Anyway, it's pretty easy to fix with a <tt class="docutils literal"><span class="pre">/usr/local/bin/firefox</span></tt> wrapper:</p>
<pre class="literal-block">
#!/bin/bash
[[ &quot; $*&quot; == *&quot; -P&quot;* ]] &amp;&amp; export MOZ_NO_REMOTE=1
exec /usr/bin/firefox &quot;$&#64;&quot;
</pre>
<p>This prevents the binary from attempting to contact the running instance, which
allows the <tt class="docutils literal"><span class="pre">-P</span></tt> and <tt class="docutils literal"><span class="pre">-ProfileManager</span></tt> options to work.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.n01se.net/?feed=rss2&amp;p=28</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>using the reStructuredText plugin for WordPress</title>
		<link>http://blog.n01se.net/?p=26</link>
		<comments>http://blog.n01se.net/?p=26#comments</comments>
		<pubDate>Thu, 15 May 2008 15:32:35 +0000</pubDate>
		<dc:creator>agriffis</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.n01se.net/?p=26</guid>
		<description><![CDATA[The first thing I did after migrating content from our old blog was to install the reStructuredText WordPress plugin. The second thing I did was convert a few entries to use it. And the third thing, well, the third thing was to spend a couple hours trying to figure out why it insisted on rendering [...]]]></description>
			<content:encoded><![CDATA[
<div class="document">


<!-- -*- mode: rst -*- -->
<p>The first thing I did after migrating content from our old blog was to install
the
<a class="reference" href="https://launchpad.net/rest-wordpress/">reStructuredText WordPress plugin</a>.
The second thing I did was convert a few entries to use it.  And the third
thing, well, the third thing was to spend a couple hours trying to figure out
why it insisted on rendering headings as <tt class="docutils literal"><span class="pre">&lt;h1&gt;</span></tt> instead of <tt class="docutils literal"><span class="pre">&lt;h3&gt;</span></tt> even
though I had set <tt class="docutils literal"><span class="pre">$rst2html_options</span> <span class="pre">=</span> <span class="pre">'--initial-header-level=3</span>
<span class="pre">--no-doc-title</span> <span class="pre">...'</span></tt>.</p>
<p>Finally found it!  <tt class="docutils literal"><span class="pre">$rst2html_options</span></tt> is global but the rendering function
was using an unitialized local value.  Here's the patch:</p>
<pre class="literal-block">
--- rest.php.old 2008-05-15 08:14:52.000000000 -0700
+++ rest.php     2008-05-15 08:15:00.000000000 -0700
&#64;&#64; -76,6 +76,7 &#64;&#64;
  */
 function reST($text) {
   global $rst2html;
+  global $rst2html_options;
   global $cachedir;
   global $usepipes;
   global $tmpdir;
</pre>
<p>I'll try to get this upstream, but the launchpad project doesn't provide any
contact information and claims it doesn't use a bug database.  Best I've been
able to figure out so far is to leave a comment
<a class="reference" href="http://goldenspud.com/rotr/index.php/2007/12/11/restructuredtext-plugin-weirdness-here/#comment-13412">here</a>.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.n01se.net/?feed=rss2&amp;p=26</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 2.282 seconds -->
