<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>The Party Line</title>
    <link rel="alternate" type="text/html" href="http://blog.tobez.org/" />
    <link rel="self" type="application/atom+xml" href="http://blog.tobez.org/atom.xml" />
    <id>tag:blog.tobez.org,2010-01-06://3</id>
    <updated>2010-01-05T13:24:12Z</updated>
    <subtitle>tobez&apos;s personal weblog</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 5.01</generator>

<entry>
    <title>New smartmontools and munin</title>
    <link rel="alternate" type="text/html" href="http://blog.tobez.org/2010/01/new-smartmontools-and-munin.html" />
    <id>tag:blog.tobez.org,2010://3.116</id>

    <published>2010-01-05T13:00:26Z</published>
    <updated>2010-01-05T13:24:12Z</updated>

    <summary>With the recent (2009-12-23) update to FreeBSD&#8217;s sysutils/smartmontools port smartctl stopped working if run as non-root. I did not investigate whether it is because of the change in the way smartctl operates, or whether it just stopped to be setuid...</summary>
    <author>
        <name>tobez</name>
        
    </author>
    
        <category term="FreeBSD" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Hints" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="freebsd" label="freebsd" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="freebsdports" label="freebsd ports" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="munin" label="munin" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.tobez.org/">
        <![CDATA[<p>With the recent (2009-12-23) update to
<a href="http://www.freebsd.org/">FreeBSD</a>&#8217;s
<a href="http://www.freshports.org/sysutils/smartmontools/"><code>sysutils/smartmontools</code> port</a>
<code>smartctl</code>
stopped working if run as non-root.
I did not investigate whether it is because of the change
in the way <code>smartctl</code> operates,
or whether it just stopped to be setuid root.</p>

<p>Normally I don&#8217;t mind going root to run <code>smartctl</code> by hand,
but it presents a bit of a problem for the <code>hddtemp_smartctl</code>
<a href="http://www.linpro.no/projects/munin/">Munin</a>
plugin.</p>

<p>One possible solution is to add the <code>munin</code> user to the <code>operator</code> group,
add the following two lines to <code>/etc/devfs.conf</code>:</p>

<pre><code>perm ata 0660
perm xpt0 0660
</code></pre>

<p>And finally, run <code>sh /etc/rc.d/devfs restart</code>.</p>

<p>Being the dummy that I am, I only thought about a simpler solution
when composing this post: just add <code>user root</code> into the <code>[hddtemp_smartctl]</code> section
of your <code>munin/plugin-conf.d/plugins.conf</code> file.
Besides being simpler, this method has an added advantage: an updated
version of the
<a href="http://www.freshports.org/sysutils/munin-node/"><code>sysutils/munin-node</code> port</a>
can easily incorporate this change.
<a href="http://www.des.no/">Dag-Erling</a>: hint, hint.  :-)</p>
]]>
        

    </content>
</entry>

<entry>
    <title>How to time command execution in zsh</title>
    <link rel="alternate" type="text/html" href="http://blog.tobez.org/2009/03/how-to-time-command-execution-in-zsh.html" />
    <id>tag:blog.tobez.org,2009://3.86</id>

    <published>2009-03-19T18:55:14Z</published>
    <updated>2009-03-19T18:57:20Z</updated>

    <summary>Often I want to know how long it took for a particular command to finish. An obvious solution to use the time(1) command does not work without a degree of anticipation on my part that I do not normally posess....</summary>
    <author>
        <name>tobez</name>
        
    </author>
    
        <category term="Hints" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="hints" label="hints" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="howto" label="howto" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="time" label="time" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="unix" label="unix" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="woblomo" label="woblomo" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="zsh" label="zsh" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.tobez.org/">
        <![CDATA[<p>Often I want to know how long it took for a particular
command to finish.</p>

<p>An obvious solution to use the <a href="http://www.freebsd.org/cgi/man.cgi?time"><code>time(1)</code></a>
command does not work without a degree of
anticipation on my part that I do not normally
posess.</p>

<p>At some point I became sufficiently annoyed
to actually add some hooks to my <code>.zshrc</code>.
All commands executed in an iteractive shell
are timed, but the reporting is done
only for those that took longer than 10 seconds
to execute.</p>

<p>This ugly code does the job:</p>

<pre><code>note_remind=0
note_ignore="yes"
note_command="?"

note_report()
{
    echo ""
    echo "note_report: $note_command completed in $1 seconds"
}

preexec()
{
    if [ "x$TTY" != "x" ]; then
        note_remind="$SECONDS"
        note_ignore=""
        note_command="$2"
    fi
}

precmd()
{
    local xx
    if [ "x$TTY" != "x" ]; then
        if [ "x$note_ignore" = "x" ]; then
            note_ignore="yes"
            xx=$(($SECONDS-$note_remind))
            if [ $xx -gt 10 ]; then
                if [ $TTYIDLE -gt 10 ]; then
                    note_report $xx
                fi
            fi
        fi
    fi
}
</code></pre>

<p>Enjoy.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Unknown CPAN III: File::SortedSeek</title>
    <link rel="alternate" type="text/html" href="http://blog.tobez.org/2009/03/unknown-cpan-iii-filesortedseek.html" />
    <id>tag:blog.tobez.org,2009://3.81</id>

    <published>2009-03-13T22:34:05Z</published>
    <updated>2009-03-13T22:40:26Z</updated>

    <summary>Let&#8217;s suppose that you have a huge logfile and would like to quickly extract lines from it that relate to a given small time interval. How would you do it? Since the lines are ordered by time specification, the fastest...</summary>
    <author>
        <name>tobez</name>
        
    </author>
    
        <category term="Hints" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="cpan" label="CPAN" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perlmodules" label="Perl modules" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="unknowncpan" label="Unknown CPAN" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="logfiles" label="logfiles" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="woblomo" label="woblomo" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.tobez.org/">
        <![CDATA[<p>Let&#8217;s suppose that you have a huge
logfile and would like to quickly
extract lines from it that relate
to a given small time interval.
How would you do it?</p>

<p>Since the lines are ordered by time specification,
the fastest way (provided you do not
keep indexes of any sort) is to do
the old good binary search,
doing all necessary housekeeping to
account for line boundaries
and converting the <a href="http://search.cpan.org/~muir/Time-modules/lib/Time/ParseDate.pm">timestamp from whatever
format it is in the logfile</a>
to epoch seconds for comparison with the
target interval boundaries.</p>

<p>Since you are dealing with <a href="http://www.perl.org/">Perl</a> here,
it would be natural to first look
on <a href="http://www.cpan.org/">CPAN</a> for a module which somebody
else has already written to do just this.</p>

<p>And of course somebody has.
Enter <a href="http://search.cpan.org/~jfreeman/File-SortedSeek/lib/File/SortedSeek.pm">File::SortedSeek</a> by Dr. James Freeman.
The module interface is a bit weird,
so it pays off to read the documentation
carefully.</p>

<p>At any rate, here is a complete program that
handles the task, assuming that the timestamp
(in pretty much any format)
is at the beginning of each line of the logfile:</p>

<pre><code>
<span class="hi_comment">#! /usr/bin/perl</span>
<span class="hi_key1">use</span> strict;
<span class="hi_key1">use</span> warnings;
<span class="hi_key1">use</span> Getopt::Long;
<span class="hi_key1">use</span> File::SortedSeek;
<span class="hi_key1">use</span> Time::ParseDate;

<span class="hi_key1">my</span> ($from, $to);
usage() <span class="hi_key1">unless</span> GetOptions(<span class="hi_string">"from=s"</span> =&gt; \$from, <span class="hi_string">"to=s"</span> =&gt; \$to);
usage() <span class="hi_key1">unless</span> @<span class="hi_key1">ARGV</span> == <span class="hi_number">1</span>;
$from = parsedate($from) <span class="hi_key1">if</span> $from;
$to   = parsedate($to)   <span class="hi_key1">if</span> $to;

<span class="hi_key1">my</span> $filename = <span class="hi_key2">shift</span>;

<span class="hi_key2">open</span> L, <span class="hi_string">"&lt; $filename"</span> <span class="hi_key3">or</span> <span class="hi_key2">die</span> <span class="hi_string">"unable to open $filename: $!\n"</span>;
File::SortedSeek::set_silent(<span class="hi_number">1</span>);

<span class="hi_key1">my</span> $end = File::SortedSeek::numeric(*L, $to, \&amp;time2sec)   <span class="hi_key1">if</span> $to;
<span class="hi_key1">my</span> $beg = File::SortedSeek::numeric(*L, $from, \&amp;time2sec) <span class="hi_key1">if</span> $from;
$end ||= <span class="hi_number">0</span>;  $beg ||= <span class="hi_number">0</span>;
<span class="hi_key1">while</span> (&lt;L&gt;) {
    <span class="hi_key2">print</span>;
    $beg += <span class="hi_key2">length</span>($_);
    <span class="hi_key1">last</span> <span class="hi_key1">if</span> $end &amp;&amp; $beg &gt; $end;
}

<span class="hi_key1">sub</span> usage
{
    <span class="hi_key2">print</span> <span class="hi_key1">STDERR</span> &lt;&lt;EOF;
usage:
\t$<span class="hi_number">0</span> --from date-<span class="hi_key2">time</span> [--to date-<span class="hi_key2">time</span>] filename
\t$<span class="hi_number">0</span> -f date-<span class="hi_key2">time</span> [-t date-<span class="hi_key2">time</span>] filename
EOF
    <span class="hi_key2">exit</span> <span class="hi_number">1</span>;
}

<span class="hi_key1">sub</span> time2sec
{
    <span class="hi_key1">my</span> $line  = <span class="hi_key2">shift</span>;
    <span class="hi_key1">return</span> <span class="hi_key2">undef</span> <span class="hi_key1">unless</span> <span class="hi_key2">defined</span> $line;
    <span class="hi_key1">my</span> $r = parsedate($line, FUZZY =&gt; <span class="hi_number">1</span>);
    $r;
}
</code></pre>

<p>Nifty, eh?</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Unknown CPAN II: Time::ParseDate</title>
    <link rel="alternate" type="text/html" href="http://blog.tobez.org/2009/03/unknown-cpan-ii-timeparsedate.html" />
    <id>tag:blog.tobez.org,2009://3.77</id>

    <published>2009-03-09T16:39:09Z</published>
    <updated>2009-03-10T11:14:22Z</updated>

    <summary>There is a number of very good, but not very well known Perl modules on CPAN. Sometimes I&#8217;ll be writing short posts about such modules which I use and appreciate. When you are dealing with date and time in Perl,...</summary>
    <author>
        <name>tobez</name>
        
    </author>
    
        <category term="Hints" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="cpan" label="CPAN" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perlmodules" label="Perl modules" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="unknowncpan" label="Unknown CPAN" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="date" label="date" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="time" label="time" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="woblomo" label="woblomo" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.tobez.org/">
        <![CDATA[<p><em>There is a number of very good, but not very well
known <a href="http://www.perl.org/">Perl</a> modules on <a href="http://www.cpan.org/">CPAN</a>.</em></p>

<p><em>Sometimes I&#8217;ll be writing short posts about
such modules which I use and appreciate.</em></p>

<p>When you are dealing with date and time in Perl,
inevitably you will reach a point
when you need to do more than is immediately
available through <a href="http://perldoc.perl.org/perlfunc.html">Perl builtins</a> and
the <a href="http://perldoc.perl.org/POSIX.html"><code>POSIX</code></a> module.</p>

<p>Then you try to find a module for what you
want on CPAN, and you drown in literally
hundreds of modules dealing with dates and times.</p>

<p>Luckily, there is a clear winner in this &#8220;modules war&#8221; -
everybody (or at least everybody sane) recommends
to use the <a href="http://search.cpan.org/~drolsky/DateTime/lib/DateTime.pm"><code>DateTime</code></a> module,
and for the things that it cannot do,
various other modules from the <a href="http://search.cpan.org/search?query=datetime">same namespace</a>.</p>

<p>So life is bright for a perl programmer on the date/time front,
until you have a need to parse a date represented
in one of a multitude of &#8220;human-readable&#8221; formats,
and you don&#8217;t know in advance which one it is going to be.</p>

<p>The <code>DateTime</code> itself cleverly refuses to deal with
this task <em>at all</em>, and instead recommends to
use one of the <a href="http://search.cpan.org/search?query=datetime%3A%3Aformat&amp;mode=all"><code>DateTime::Format::</code></a>
modules.</p>

<p>You will be relieved to know that you can easily
and quickly create parsers for your own date formats -
that is, if you are able to remember that you should
use the module aptly named
<a href="http://search.cpan.org/~drolsky/DateTime-Format-Builder/lib/DateTime/Format/Builder/Parser/Regex.pm"><code>DateTime::Format::Builder::Parser::Regex</code></a>.</p>

<p>The documentation for <a href="http://search.cpan.org/~jhoblitt/DateTime-Format-Bork/lib/DateTime/Format/Bork.pod"><code>DateTime::Format::Bork</code></a>
is also very enlightening.</p>

<p>Aaaaanyway. </p>

<p>I prefer to go against the flow here,
and use a module somewhat unfortunately
named <a href="http://search.cpan.org/~muir/Time-modules/lib/Time/ParseDate.pm"><code>Time::ParseDate</code></a>.
I mean, it could just as easily be <code>Date::ParseTime</code> or something,
right?
Worse, for years I had trouble remembering what <em>distribution</em>
this modules comes from
(it, very obviously for everyone but me,
can be found in the <a href="http://search.cpan.org/~muir/Time-modules/"><code>Time-modules</code></a> distribution).</p>

<p>At any rate,
if we forget for a second about the funny names,
this module is truly a wonder:</p>

<pre><code>$ perl -MTime::ParseDate -le 'print parsedate("Sat Feb 14 00:31:30 2009")'
1234567890
$ perl -MTime::ParseDate -le 'print parsedate("2 days ago")'
1236443283
$ perl -MTime::ParseDate -le 'print parsedate("18:30")'
1236619800
</code></pre>

<p>It exports a single function, which takes a single parameter
(unless you want to specify some options which are rarely needed in practice),
and you get your epoch seconds back in return.
Very simple, very elegant, gets the job done.
I wish there were more &#8220;straight to the point&#8221; modules like this one.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Unknown CPAN I: Sys::RunAlone</title>
    <link rel="alternate" type="text/html" href="http://blog.tobez.org/2009/03/unknown-cpan-i-sysrunalone.html" />
    <id>tag:blog.tobez.org,2009://3.76</id>

    <published>2009-03-07T13:50:59Z</published>
    <updated>2009-03-07T13:55:52Z</updated>

    <summary>There is a number of very good, but not very well known Perl modules on CPAN. Sometimes I&#8217;ll be writing short posts about such modules which I use and appreciate. There is a common task of executing a script from...</summary>
    <author>
        <name>tobez</name>
        
    </author>
    
        <category term="Hints" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="cpan" label="CPAN" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perlmodules" label="Perl modules" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="unknowncpan" label="Unknown CPAN" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="cron" label="cron" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="locking" label="locking" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="woblomo" label="woblomo" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.tobez.org/">
        <![CDATA[<p><em>There is a number of very good, but not very well
known <a href="http://www.perl.org/">Perl</a> modules on <a href="http://www.cpan.org/">CPAN</a>.</em></p>

<p><em>Sometimes I&#8217;ll be writing short posts about
such modules which I use and appreciate.</em></p>

<p>There is a common task of executing a script
from <a href="http://www.freebsd.org/cgi/man.cgi?cron">cron</a> periodically,
subject to the following conditions:</p>

<ul>
<li>a script can occasionally run a relatively long
time (longer than the interval at which it
is launched by cron);</li>
<li>such long runs do not happen often;</li>
<li>running two or more instances of the
script at the same time will lead to
all sorts of strange things happening
and must be avoided;</li>
<li>skipping a single run is no big deal.</li>
</ul>

<p>A usual method to prevent strange things
from happening
is to use a lockfile, like in this example:</p>

<pre><code>use strict;
use warnings;

use Fcntl qw(:DEFAULT :flock);

sysopen(L, "/var/run/myprocess.lock", O_WRONLY | O_CREAT)
    or die "cannot open lockfile: $!";
flock(L, LOCK_EX | LOCK_NB)
    or die "cannot obtain lock: $!";

# ... do work here ...

unlink "/var/run/myprocess.lock"; # optional
close(L);
</code></pre>

<p>(You might want to silently exit when flock fails
in order to not spam yourself with useless cron
mails).</p>

<p>Nothing fancy, really.
But over time it becomes boring to write all this housekeeping
code in every little cronjob,
especially since in some cases the &#8220;do work here&#8221; part
can be comparable in size to the locking part.</p>

<p>The solution, of course, is to use the CPAN magic
and to find a module which sweeps all this complexity under
the rug, leaving us with a clean and simple interface,
so that we can concentrate on getting the job done.</p>

<p>As usual with CPAN, there is not one, but <a href="http://search.cpan.org/search?query=lockfile">several modules</a>
which were written to perform this task.
Most of them are rather powerful,
which is unfortunate, since we want simplicity of use above
all else.
The bells and whistles provided by those modules
might be needed in certain situations,
but for the purpose described above they just get in the way.</p>

<p>There is, however, a wonderfully simple (and a rather clever)
module by <a href="http://search.cpan.org/~elizabeth/">Elizabeth Mattijsen</a>,
<a href="http://search.cpan.org/~elizabeth/Sys-RunAlone/lib/Sys/RunAlone.pm"><code>Sys::RunAlone</code></a>.
To get the same functionality as the code above,
all you need to do is this:</p>

<pre><code>use strict;
use warnings;
use Sys::RunAlone;

# ... do work here ...

__END__
</code></pre>

<p>That&#8217;s it.  Nothing else to write.</p>

<p>There are only two minor things to remember about this module,
if you want to avoid problems.</p>

<p>First, it uses the script&#8217;s <code>DATA</code> handle to do the locking
(that is, it actually uses the script&#8217;s file itself).
So if you have several symlinks pointing to the same
script, you cannot run them at the same time for
it is still one physical file and one <code>DATA</code> handle.</p>

<p>Second, and for the same reason,
if you modify the script while it
is running and then launch it again,
it will fail to
detect that another instance is already running,
since the <code>DATA</code> handle will be different.</p>

<p>Just keep this in mind when you use it.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>rrdtool legend box rant</title>
    <link rel="alternate" type="text/html" href="http://blog.tobez.org/2009/03/rrdtool-legend-box-rant.html" />
    <id>tag:blog.tobez.org,2009://3.74</id>

    <published>2009-03-05T13:21:41Z</published>
    <updated>2009-03-05T16:21:33Z</updated>

    <summary>Last time I ranted about one thing that is wrong with rrdtool. It turns out that I, unfortunately, have more gripes to share. Let&#8217;s talk today about the legend control. The rrdtool&#8217;s language for controlling how the graph is going...</summary>
    <author>
        <name>tobez</name>
        
    </author>
    
        <category term="General" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Hints" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Rants" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="rants" label="rants" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="rrdtool" label="rrdtool" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="unixtools" label="unix tools" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="woblomo" label="woblomo" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.tobez.org/">
        <![CDATA[<p><a href="http://blog.tobez.org/2009/03/rrdtool-cdef-restrictions-rant.html">Last time</a>
I ranted about one thing that is wrong with <a href="http://oss.oetiker.ch/rrdtool/">rrdtool</a>.</p>

<p>It turns out that I, unfortunately, have more gripes
to share.  Let&#8217;s talk today about the legend control.</p>

<p>The rrdtool&#8217;s language for controlling how the graph
is going to look and feel is pretty rich and complex.
Among other things, it has a bunch of graphing commands
that are able to manipulate the legend section of the graph.
Some of those commands do nothing else,
while the other commands only modify the legend
as a side effect, and primarily exist for
doing something else.</p>

<p>Let&#8217;s take as an example the graph below:</p>

<pre><code>rrdtool graph x.png
  --end 1235800000 --start end-150000
  'DEF:data=some.rrd:data:AVERAGE'
  'CDEF:sine=data,POP,1235800000,TIME,-,10000,/,SIN'
  'LINE1:sine#0000ff:a sine of foo\l'
  'CDEF:cosine=data,POP,1235800000,TIME,-,5000,/,COS'
  'LINE1:cosine#00ff00:a cosine of bar'
</code></pre>

<p><img src="http://www.tobez.org/images/blog/rrdtool/sine.png" alt="" /></p>

<p>The trouble is that there is <em>no</em> instruction which
can produce a so called &#8220;legend box&#8221; (a small blue
box next to the &#8220;a sine of foo&#8221; legend text)
without doing something else in the process.
<em>All</em> of the commands that actually graph something
can optionally produce a legend box, but there
is no other way to make it.</p>

<p>If we extend our sine example with some nice
<a href="http://blog.tobez.org/2009/03/rrdtool-cdef-restrictions-rant.html">downtime background</a> (in Soviet Russia sines
can have a downtime!), we get a nice picture like this:</p>

<pre><code>rrdtool graph x.png
  --end 1235800000 --start end-150000
  'DEF:data=some.rrd:data:AVERAGE'
  'CDEF:downtime=data,0,0,IF,
    TIME,1235769489,GE,TIME,1235779489,LE,*,
    TIME,1235689489,GE,TIME,1235729489,LE,*,+,+'
  'CDEF:sine=data,POP,1235800000,TIME,-,10000,/,SIN'
  'LINE1:sine#0000ff:a sine of foo\l'
  'CDEF:cosine=data,POP,1235800000,TIME,-,5000,/,COS'
  'LINE1:cosine#00ff00:a cosine of bar\l'
  <strong>'TICK:downtime#ffe0e0:1.0:downtime'</strong>
</code></pre>

<p><img src="http://www.tobez.org/images/blog/rrdtool/sine-with-downtime.png" alt="" /></p>

<p>But let&#8217;s suppose that we&#8217;d also like to add background
coloring for uptime, and indicate that in a legend.
Let&#8217;s use another CDEF for uptime, which will be just
the opposite of our downtime CDEF:</p>

<pre><code>rrdtool graph x.png
  --end 1235800000 --start end-150000
  'DEF:data=some.rrd:data:AVERAGE'
  'CDEF:downtime=data,0,0,IF,
    TIME,1235769489,GE,TIME,1235779489,LE,*,
    TIME,1235689489,GE,TIME,1235729489,LE,*,+,+'
  <strong>'CDEF:uptime=downtime,0,1,IF'</strong>
  'CDEF:sine=data,POP,1235800000,TIME,-,10000,/,SIN'
  'LINE1:sine#0000ff:a sine of foo\l'
  'CDEF:cosine=data,POP,1235800000,TIME,-,5000,/,COS'
  'LINE1:cosine#00ff00:a cosine of bar\l'
  <strong>'TICK:uptime#e0ffe0:1.0:uptime'</strong>
  <strong>'TEXTALIGN:left'</strong>
  'TICK:downtime#ffe0e0:1.0:downtime'
</code></pre>

<p><img src="http://www.tobez.org/images/blog/rrdtool/uptime-no-sine.png" alt="" /></p>

<p>Oops.  Of course.  The graphing commands are processed
in sequence, so the uptime &#8220;background&#8221; has obscured
our actual sinusoidal data!
We will have to put the uptime TICK before anything else
to avoid this:</p>

<pre><code>rrdtool graph x.png
  --end 1235800000 --start end-150000
  'DEF:data=some.rrd:data:AVERAGE'
  'CDEF:downtime=data,0,0,IF,
    TIME,1235769489,GE,TIME,1235779489,LE,*,
    TIME,1235689489,GE,TIME,1235729489,LE,*,+,+'
  'CDEF:uptime=downtime,0,1,IF'
  'CDEF:sine=data,POP,1235800000,TIME,-,10000,/,SIN'
  <strong>'TICK:uptime#e0ffe0:1.0:uptime'</strong>
  'LINE1:sine#0000ff:a sine of foo\l'
  'CDEF:cosine=data,POP,1235800000,TIME,-,5000,/,COS'
  'LINE1:cosine#00ff00:a cosine of bar\l'
  'TICK:downtime#ffe0e0:1.0:downtime'
</code></pre>

<p><img src="http://www.tobez.org/images/blog/rrdtool/uptime-bad-legend.png" alt="" /></p>

<p>See the problem?  Now the legend boxes are not in the
right order.</p>

<p>Naturally, it is pretty trivial to solve - we just remove
the legend (it is optional) from the uptime TICK,
and add another graphing command in the end with the
right legend text.
We&#8217;ll simply have to make sure that this &#8220;graphing command&#8221;
does not actually graph anything:</p>

<pre><code>rrdtool graph x.png
  --end 1235800000 --start end-150000
  'DEF:data=some.rrd:data:AVERAGE'
  'CDEF:downtime=data,0,0,IF,
    TIME,1235769489,GE,TIME,1235779489,LE,*,
    TIME,1235689489,GE,TIME,1235729489,LE,*,+,+'
  'CDEF:uptime=downtime,0,1,IF'
  'CDEF:sine=data,POP,1235800000,TIME,-,10000,/,SIN'
  <strong>'TICK:uptime#e0ffe0:1.0'</strong>
  'LINE1:sine#0000ff:a sine of foo\l'
  'CDEF:cosine=data,POP,1235800000,TIME,-,5000,/,COS'
  'LINE1:cosine#00ff00:a cosine of bar\l'
  <strong>'TICK:uptime#e0ffe0:0.0:uptime'</strong>
  <strong>'TEXTALIGN:left'</strong>
  'TICK:downtime#ffe0e0:1.0:downtime'
</code></pre>

<p><img src="http://www.tobez.org/images/blog/rrdtool/nice-sine.png" alt="" /></p>

<p>Just like the last time - the problem is easily solvable,
but it annoys me, since rrdtool again forces us to work
against it instead of working with us.
It would be nicer to have a way to put a legend
box where we want it in some more direct way
(maybe a variant of the COMMENT command)?</p>
]]>
        

    </content>
</entry>

<entry>
    <title>rrdtool CDEF restrictions rant</title>
    <link rel="alternate" type="text/html" href="http://blog.tobez.org/2009/03/rrdtool-cdef-restrictions-rant.html" />
    <id>tag:blog.tobez.org,2009://3.73</id>

    <published>2009-03-03T19:40:06Z</published>
    <updated>2009-03-05T13:31:51Z</updated>

    <summary>Last time I spread some rrdtool love around. Love with no hate won&#8217;t do, however. Taking a page from the way the BBC and many other news outlets cover certain conflicts, it seems prudent to present an unbiased view of...</summary>
    <author>
        <name>tobez</name>
        
    </author>
    
        <category term="General" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Hints" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Rants" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="baddesign" label="bad design" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="rants" label="rants" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="rrdtool" label="rrdtool" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="unixtools" label="unix tools" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="woblomo" label="woblomo" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.tobez.org/">
        <![CDATA[<p><a href="http://blog.tobez.org/2009/03/some-rrdtool-love.html">Last time</a> I spread some <a href="http://oss.oetiker.ch/rrdtool/">rrdtool</a> love
around.
Love with no hate won&#8217;t do, however.
Taking a page from the way the BBC and many other news outlets
cover certain conflicts,
it seems prudent to present an unbiased view of rrdtool.
And what better way to do that if not by spreading some
hate this time?</p>

<p>Some time ago I had a task of adding background coloring
to the portions of a graph, representing downtime of a device.
This information was not available in the RRD archive
itself, but could be obtained from elsewhere.</p>

<p>The information was in the form of epoch ranges, like this:</p>

<pre><code>1235639489-1235646689,1235725889-1235729489
</code></pre>

<p>After some thought, I decided that making a CDEF
with some simple RPN magic, in combination with a
TICK graphing command would do the trick.
The TICK command draws a vertical line of a specified height
when a data point is not
a zero or an UNKNOWN value, so I na&iuml;vely thought
that this simple CDEF will achieve what I want
(one long line here is split into several lines for your browsing convenience):</p>

<pre><code>CDEF:downtime=0,TIME,1235639489,GE,
    TIME,1235646689,LE,*,
    TIME,1235725889,GE,
    TIME,1235729489,LE,*,+,+
</code></pre>

<p>The boolean values in rddtool&#8217;s RPN are represented using
the usual C-like convention (0 = false, 1 = true),
so for any given time point the result of the CDEF above
will be 0 if the point is outside any of the downtime
intervals, 1 if it is inside one of the intervals,
and more than 1 if it is inside several intervals
(which should not happen, but is possible if we specify
overlapping downtime epoch ranges).</p>

<p>If you did not understand how this is supposed to work,
<a href="http://oss.oetiker.ch/rrdtool/doc/rrdgraph_rpn.en.html">go read the rrdgraph_rpn manpage</a>.</p>

<p>Anyway, that was easy enough, even if it was not very clean.
So where is the promised hate, you&#8217;ll ask?  Here it is:</p>

<pre><code>rrdtool graph x.png --end 1235800000 --start end-150000
    'DEF:data=some.rrd:someds:AVERAGE'
    'CDEF:downtime=0,TIME,1235639489,GE,TIME,1235646689,LE,*,
     TIME,1235725889,GE,TIME,1235729489,LE,*,+,+'
    'TICK:downtime#ffe0e0:1.0'

ERROR: rpn expressions without DEF or CDEF variables are not supported
</code></pre>

<p>You&#8217;ve read that right!
Rrdtool insists that everything you put into a graph must ultimately come
from some data source in some RRD archive.
How stupid is that?</p>

<p>And the answer is - very stupid indeed, for at least two reasons.</p>

<p>First, it tries to pretend it knows what I might want to do better than me,
and I really hate that in software.
Whatever has happened to the idea that a tool must not get in the way of its user?</p>

<p>Secondly, this check is easily circumvented by adding a real DEF somewhere in
the CDEF and then (mis)using RPN language to get rid of any value which comes
from the DEF.
There are many ways to do it, some more creative than others, but even this
ham-fisted &#8220;solution&#8221; will do the job:</p>

<pre><code>CDEF:downtime=data,0,0,IF,TIME,1235639489,GE,
    TIME,1235646689,LE,*,
    TIME,1235725889,GE,
    TIME,1235729489,LE,*,+,+
</code></pre>

<p>So we have a pointless restriction, and we are forced to work around it.
Some might say that working against the tool to reach the goal is somehow
challenging and maybe even fun.
If you ask me, this is akin to programming in <a href="http://en.wikipedia.org/wiki/Brainfuck">Brainfuck</a> -
a kind of activity better performed as a hobby, if that&#8217;s your idea of
how to spend your copious free time.</p>

<p>To rephrase the Perl&#8217;s motto, <em>rrdtool makes simple things hard</em>.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Some rrdtool love</title>
    <link rel="alternate" type="text/html" href="http://blog.tobez.org/2009/03/some-rrdtool-love.html" />
    <id>tag:blog.tobez.org,2009://3.71</id>

    <published>2009-03-01T14:16:50Z</published>
    <updated>2009-03-05T13:31:11Z</updated>

    <summary>Everybody uses rrdtool. Everybody loves rrdtool. I love rrdtool as well. Sometimes it even pleasantly surprizes me. For example, it used to be the case that massive updates of a large number of RRD archives were a bit on the...</summary>
    <author>
        <name>tobez</name>
        
    </author>
    
        <category term="General" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Hints" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="performance" label="performance" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="rrdtool" label="rrdtool" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="unixtools" label="unix tools" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="woblomo" label="woblomo" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.tobez.org/">
        <![CDATA[<p>Everybody uses <a href="http://oss.oetiker.ch/rrdtool/">rrdtool</a>.
Everybody loves rrdtool.</p>

<p>I love rrdtool as well.
Sometimes it even pleasantly surprizes me.</p>

<p>For example,
it used to be the case that massive updates of
a large number of RRD archives were a bit on the
slow side (this operation is IO-bound, you see).</p>

<p>Quite unexpectedly I found that
this inconvenience can be easily circumvented
by throwing more RAM into the problem.
By itself, this statement is not at all suprizing - after all,
we all know about effects of disk caching.
It is the <em>magnitude</em> of the improvement that
simply astonished me:
on a moderately busy box with primary purpose entirely
different from doing RRD updates,
I am now routinely getting around 18500 RRD acrhives
updated in under 1 second.
The large majority of the archives has 40+ data sources each,
and the rest has 140+ data sources each.
The machine has measly 8G of RAM.</p>

<p>Sometimes,
when the box is busy doing something with its disks,
it might take 3 minutes to finish the updates.
In very rare instances it can take up to 15 minutes.
But in more than 80% of cases it takes under 1 second.</p>

<p>The setup is such that the actual data collection
is completely separated from the RRD update step.
In fact, the collection step actually occurs on a different machine,
for reasons I am not going to delve into in this post.
The collector generates an &#8220;RRD update order&#8221; file,
which is transferred to the target machine, where it
is parsed by a simple Perl script, which subsequently
executes the corresponding RRDs::update statements,
with a small degree of parallelism in this last operation.</p>

<p>The application has been running for some months now,
and every time I recall the numbers involved,
I cannot help but say &#8220;wow!&#8221;.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Version-independent location of a CPAN distribution&apos;s Changes file</title>
    <link rel="alternate" type="text/html" href="http://blog.tobez.org/2007/12/version-independent-location-of-a-cpan-distributions-changes-file.html" />
    <id>tag:blog.tobez.org,2007://3.65</id>

    <published>2007-12-20T11:43:39Z</published>
    <updated>2009-03-01T12:07:36Z</updated>

    <summary>Some time ago several people (most notably skv@) ranted about including a list of changes or a link to such list in the commit message for a port update. I thought it was a great idea and started including a...</summary>
    <author>
        <name>tobez</name>
        
    </author>
    
        <category term="FreeBSD" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Hints" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.tobez.org/">
        <![CDATA[<p>Some time ago several people (most notably skv@) ranted about including a 
list of changes or a link to such list in the commit message for a port
update.</p>

<p>I thought it was a great idea and started including a link to a <a href="http://www.cpan.org/">CPAN</a>&#8217;s 
distribution Changes file in my commits some time ago.</p>

<p>What I did not like was that those links looked like this:</p>

<p><a href="http://search.cpan.org/src/JESSE/Template-Declare-0.27/Changes">http://search.cpan.org/src/JESSE/Template-Declare-0.27/Changes</a></p>

<p>FreeBSD&#8217;s commit messages are preserved in our repository and mail archives
forever, for a suitable definition of &#8220;forever&#8221;.  On the other hand, CPAN
authors are encouraged to clean up old and obsolete versions promptly.</p>

<p>Thus there is a discrepancy between expected time of life of the link in the
commit message and the link contents.</p>

<p>While older CPAN distributions can still be found on 
<a href="http://backpan.cpan.org/">BackPAN</a>,
it only provides links to tarballs and not
individual files like Changes.</p>

<p>Luckily, it turns out that version-less links like</p>

<p><a href="http://search.cpan.org/dist/Template-Declare/Changes">http://search.cpan.org/dist/Template-Declare/Changes</a></p>

<p>work just fine, redirecting to the most recent version of the file.  This is 
acceptable, since Changes is expected to be a prepend-only file, so the
information the commit message was trying to link to can (almost) always be
found there.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Backing up Google Reader subscriptions as OPML, periodically and automatically</title>
    <link rel="alternate" type="text/html" href="http://blog.tobez.org/2007/10/backing-up-google-reader-subscriptions-as-opml-periodically-and-automatically.html" />
    <id>tag:blog.tobez.org,2007://3.64</id>

    <published>2007-10-31T21:07:42Z</published>
    <updated>2009-03-01T12:07:36Z</updated>

    <summary>A fellow former Bloglines user has asked me whether I found a way to backup Google Reader subscriptions into an OPML file from cron, as we used to do with our Bloglines accounts. A quick search turned up this, which,...</summary>
    <author>
        <name>tobez</name>
        
    </author>
    
        <category term="FreeBSD" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Hints" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Web" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.tobez.org/">
        <![CDATA[<p>A fellow former <a href="http://www.bloglines.com/">Bloglines</a> user has asked me whether
I found a way to backup <a href="http://reader.google.com/">Google Reader</a> subscriptions
into an <a href="http://en.wikipedia.org/wiki/OPML">OPML</a> file from <a href="http://www.freebsd.org/cgi/man.cgi?query=cron&amp;apropos=0&amp;sektion=8&amp;format=html">cron</a>, as we used to
do with our Bloglines accounts.</p>

<p>A quick search turned up <a href="http://googlesystem.blogspot.com/2007/08/blogroll-powered-by-google-reader.html">this</a>,
which,
from the look of it,
in order for it to work
requires every feed to be
explicitly marked with a tag which
is set up as public.</p>

<p>This by itself is rather cumbersome,
and you have to remember to do that for every new
feed you subscribe to,
otherwise you&#8217;ll defeat the purpose of making
periodic backups in the first place.</p>

<p>Luckily, there is a better solution.
There is a nice little module on <a href="http://www.cpan.org/">CPAN</a>,
<a href="http://search.cpan.org/~gray/WebService-Google-Reader/">WebService::Google::Reader</a> by <a href="http://search.cpan.org/~gray/">gray</a>,
which uses an unofficial <a href="http://code.google.com/p/pyrfeed/wiki/GoogleReaderAPI">Google Reader API</a>
to do various nifty things with your Google Reader
subscription,
<em>including</em> OPML export.</p>

<p>This means that after installing the module
you can simply put the following command
into your crontab (only command itself is shown,
see <a href="http://www.freebsd.org/cgi/man.cgi?query=crontab&amp;apropos=0&amp;sektion=5&amp;format=html">crontab(5) manual page</a> to find
out what else you will want to put in there):</p>

<pre><code>env GOOGLE_USERNAME=your-username-typically@gmail.com \
  GOOGLE_PASSWORD=your-user-password \
  perl -MWebService::Google::Reader -e \
  'print WebService::Google::Reader-&gt;new(
     username =&gt; $ENV{GOOGLE_USERNAME},
     password =&gt; $ENV{GOOGLE_PASSWORD})-&gt;opml' \
  &gt; /where/to/put/greader.opml
</code></pre>

<p>You will have to make the above to be one long line to satisfy
crontab syntax, and of course remember to use a real username,
password, and the path to the resulting OPML file.</p>

<p>Unfortunately, the most recent version
of the module (which is 0.03 at the time of this writing)
has a minor bug which prevents
the <code>opml()</code> method from working correctly.
So you will need to do a little patching.</p>

<p>Before installing the module,
edit the source file <code>lib/WebService/Google/Reader/Constants.pm</code>,
look for a string <code>subscribtions</code>,
and fix the spelling
(finding correct spelling is left as an exercise for the reader).
Then proceed installing the module as usual.</p>

<p>Hopefully, this step won&#8217;t be necessary in a couple of days&#8217; time
when a new version of the module is released.</p>

<p>If you are a <a href="http://www.freebsd.org/">FreeBSD</a> user like myself,
you may choose instead to
<a href="http://www.tobez.org/download/p5-WebService-Google-Reader-0.03.tgz">fetch a skeleton of the port of the module</a>.
Unpack it in <code>/usr/ports/www/</code>
and install it as you would any other port.</p>

<p>I intend to add the port to the ports collection as soon
as our <a href="http://www.freebsd.org/cgi/mid.cgi?id=20071030120901.GM45185%40droso.net&amp;db=mid">current ports freeze</a> is over.</p>

<p>Enjoy!</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Switching between X11 screens and workplaces with keyboard</title>
    <link rel="alternate" type="text/html" href="http://blog.tobez.org/2007/04/switching-between-x11-screens-and-workplaces-with-keyboard.html" />
    <id>tag:blog.tobez.org,2007://3.56</id>

    <published>2007-04-05T13:23:22Z</published>
    <updated>2009-03-01T12:07:29Z</updated>

    <summary> Some time ago I&#8217;ve got two monitors connected to my workstation at work. I do not like using Xinerama, so I have, in X11 terminology, two screens, :0.0 and :0.1. It bugged me that I had to move the...</summary>
    <author>
        <name>tobez</name>
        
    </author>
    
        <category term="Hints" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.tobez.org/">
        <![CDATA[<p><img src="http://www.tobez.org/images/blog/three-screens.jpg" alt="" /></p>

<p>Some time ago I&#8217;ve got two monitors connected to my workstation at work.
I do not like using <a href="http://en.wikipedia.org/wiki/Xinerama">Xinerama</a>, so I have, in X11 terminology,
two screens, <code>:0.0</code> and <code>:0.1</code>.</p>

<p>It bugged me that I had to move the mouse cursor to switch between
the screens.
There must be a way to do it with keyboard, I thought.
Some googling revealed <a href="http://wiki.gentoo-italia.net/index.php/Dual_Monitors">a wiki page about dual monitors setup</a>,
which had a reference to a little C program, <a href="http://homepages.paradise.net.nz/daveantl/dualmouse.c"><code>dualmouse.c</code></a>
by David Antliff.</p>

<p>It worked fine if all I wanted to do was to switch from my
current screen to &#8220;the other one&#8221;.
But I also wanted to be able to do things like
&#8220;switch to workplace 4 on screen 0&#8221;,
and the program could not be used for that.</p>

<p>Fortunately, the <a href="http://sweb.cz/tripie/utils/wmctrl/">wmctrl</a> utility could do things
like &#8220;switch to workplace 4 on the <em>current</em> screen&#8221;,
so all I had to do is to <a href="http://www.tobez.org/download/dualmouse.c">modify the <code>dualmouse.c</code> program</a>
to support &#8220;switch to screen N&#8221; functionality,
and the rest is, as they say, shell (or Perl) scripting.</p>

<p>The <code>~/.fluxbox/keys</code> file (if you are using something else than
<a href="http://www.fluxbox.org/">fluxbox</a>, you are on your own here) would have things like:</p>

<pre><code>Control F1 :Exec flux2workspace 0 1
Control F2 :Exec flux2workspace 0 2
Control F3 :Exec flux2workspace 0 3
Control F4 :Exec flux2workspace 0 4

Control Shift F1 :Exec flux2workspace 1 1
Control Shift F2 :Exec flux2workspace 1 2
Control Shift F3 :Exec flux2workspace 1 3
Control Shift F4 :Exec flux2workspace 1 4
</code></pre>

<p>And the <code>flux2workspace</code> script looks like this:</p>

<pre><code>#! /usr/bin/perl -w
exit unless @ARGV == 2;
system("dualmouse $ARGV[0]");
$ARGV[1]--;
$ENV{DISPLAY} = ":0.$ARGV[0]";
system("wmctrl -s $ARGV[1]");
</code></pre>

<p>Next time:
accomplishing the same feat with <a href="http://x2x.dottedmag.net/trac/do">x2x</a>-controlled displays.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>cd to a directory of a file</title>
    <link rel="alternate" type="text/html" href="http://blog.tobez.org/2007/04/cd-to-a-directory-of-a-file.html" />
    <id>tag:blog.tobez.org,2007://3.55</id>

    <published>2007-04-04T19:31:13Z</published>
    <updated>2009-03-01T12:07:28Z</updated>

    <summary> In zsh, define the following function: cd-() { local dir cd `dirname $1` } Then this: cd- /usr/ports/www/linux-opera/Makefile changes directory to /usr/ports/www/linux-opera/. Trivial pleasure, but pleasure nevertheless....</summary>
    <author>
        <name>tobez</name>
        
    </author>
    
        <category term="Hints" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.tobez.org/">
        <![CDATA[<p><img src="http://www.tobez.org/images/blog/shell.jpg" alt="" /></p>

<p>In <a href="http://www.zsh.org/">zsh</a>, define the following function:</p>

<pre><code>cd-()
{
    local dir
    cd `dirname $1`
}
</code></pre>

<p>Then this:</p>

<pre><code>cd- /usr/ports/www/linux-opera/Makefile
</code></pre>

<p>changes directory to <code>/usr/ports/www/linux-opera/</code>.</p>

<p>Trivial pleasure, but pleasure nevertheless.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Irssi events notifier with Erlang</title>
    <link rel="alternate" type="text/html" href="http://blog.tobez.org/2006/07/irssi-events-notifier-with-erlang.html" />
    <id>tag:blog.tobez.org,2006://3.50</id>

    <published>2006-07-25T18:04:28Z</published>
    <updated>2009-03-01T12:07:13Z</updated>

    <summary> Once upon a time I was a reasonably happy user of XChat. It had a feature: you could configure it to automatically popup a new window &#8220;in your face&#8221; for private messages. This was nice, since you would never...</summary>
    <author>
        <name>tobez</name>
        
    </author>
    
        <category term="Erlang" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Hints" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.tobez.org/">
        <![CDATA[<p><img src="http://www.tobez.org/images/blog/irssi-dockapp.png" alt="irssi dockapp" /></p>

<p>Once upon a time I was a reasonably happy user of 
<a href="http://www.xchat.org/">XChat</a>.  It had a feature: you could configure
it to automatically popup a new window &#8220;in your face&#8221;
for private messages.
This was nice, since you would never miss a message directed to you.
The feature also had drawbacks:</p>

<ul>
<li>once a window was there, no popping up occured;</li>
<li>popping up in your face was annoyingly intrusive;</li>
<li>it was common to be typing something else and pressing ENTER
without noticing;  the <code>:wq!</code>&#8217;s in chat windows were numerous;
parts of passwords for folks to see were not unheard of.</li>
</ul>

<p>After some time, and following an advice from friends,
I switched over to <strong>the</strong> IRC client, <a href="http://irssi.org/">irssi</a>,
and never looked back.</p>

<p>I, as many others, run irssi in text mode
(although it supposedly has a GUI, I was never tempted to try it).
Moreover, I run it 24/7 under <a href="http://www.gnu.org/software/screen/">screen</a> control on a reasonably
stable and well-connected machine.</p>

<p>Which presents me with the problem that XChat popup windows were
trying to solve: I miss stuff.  There are various notifiers
available for some instant messaging applications.
I would not be surprized if some of those are easy to integrate
with irssi.  But with <em>remote</em> irssi?  On one or more of my <em>several</em> desktops?
I never heard of such a beast, and so I decided to write one.</p>

<p>The question of presentation solved itself easily:
I use <a href="http://fluxbox.org/">fluxbox</a> window manager, which, among other things,
provides support for <a href="http://www.afterstep.org/">AfterStep</a> and <a href="http://www.windowmaker.info/">WindowMaker</a> dockapps.</p>

<p>Getting information about events from irssi itself turned out to be
a piece of cake, thanks to the tight integration of irssi and <a href="http://www.perl.org/">Perl</a>.</p>

<p>The question of delivering notifications from the machine irssi is being run on
to one or several desktops was somewhat trickier.
Initially, I thought that <a href="http://iswest.tobez.org/">a very-very simple web storage system I wrote</a>
will be the ticket.
It worked reasonably well,
but I did not want to perform the polling more often than every 30 seconds,
and I was not satisfied with the delay.
The help came from an unexpected side.</p>

<p>Some time ago I started to read up on <a href="http://www.erlang.org/">Erlang</a>,
and was impressed with its capabilities for concurrent and distributed processing.
So I sought to re-implement ISWEST-based irssi notifier in Erlang as a sort of a
novice programming project.</p>

<p>The end result is a piece of software called, not surprizingly, <strong>irssi-notifier</strong>,
which can be downloaded <a href="http://www.tobez.org/download/irssi-notifier-latest.tar.gz">here</a>.  It consists of three components.</p>

<h3>activity-notifier</h3>

<p>This is a Perl script which should be loaded in irssi.
Copy it into <code>~/.irssi/scripts</code> directory, and load it into irssi using
the following command:</p>

<pre><code>/script load activity-notifier.pl
</code></pre>

<p>You will need the <code>nc</code> program (netcat) installed,
since I could not be bothered with more socket programming in Perl.</p>

<h3>notifier-server</h3>

<p>This is a small (less than a hundred lines of code)
Erlang program that serves as a middle point between
irssi (with activity-notifier) and your desktop.
Normally, it should run on the same machine as irssi itself.</p>

<p>This is a server program, so it is supposed to run indefinitely.</p>

<p>Since I do not know (yet) how to create proper Erlang applications,
it should be started like this:</p>

<pre><code>$ cd irssi-notifier/notifier-server
$ erl
&gt; c(notifier).
&gt; notifier:start().
</code></pre>

<p>Then leave that Erlang instance running (background it, or something).</p>

<p>I intend to make this somewhat more convenient to use once I learn how
to package a proper Erlang application which runs as a daemon together with
Erlang runtime.</p>

<h3>irssi-dockapp</h3>

<p>This is a C program which actually implements the dockapp.</p>

<p>Compile it (a very simple Makefile is included).
You will need <a href="http://solfertje.student.utwente.nl/~dalroi/libdockapp/">libDockApp library</a> installed first.
Then run it like this:</p>

<pre><code>./irssi-dockapp -t host.where.notifier-server.runs -p 5679
</code></pre>

<p>When irssi receives a private message for you or a message that
it hilights (such as messages with your nick mentioned) an irregularly
shaped red blob will appear in your dockapp almost instantaneously.</p>

<p>There is no limit on the number of simultaneous dockapp connections to
the notifier server.</p>

<p>Enjoy!</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Extended del.icio.us bookmarklet</title>
    <link rel="alternate" type="text/html" href="http://blog.tobez.org/2005/11/extended-delicious-bookmarklet.html" />
    <id>tag:blog.tobez.org,2005://3.47</id>

    <published>2005-11-10T09:41:16Z</published>
    <updated>2009-03-01T12:07:12Z</updated>

    <summary> Dan Phiffer came up with a really neat Google/del.icio.us greasemonkey userscript idea: Use case: I search for &#8220;tuna sandwich&#8221; and Google brings up http://www.starkist.com/recipes/sandwiches/classictuna.html among a host of other tuna-related links. A Greasemonkey script pays attention to which link...</summary>
    <author>
        <name>tobez</name>
        
    </author>
    
        <category term="Hints" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Web" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.tobez.org/">
        <![CDATA[<p><img src="http://www.tobez.org/images/blog/delicious.42px.gif" alt="" /></p>

<p>Dan Phiffer <a href="http://mozdev.org/pipermail/greasemonkey/2005-November/006604.html">came up</a> with a really neat
<a href="http://www.google.com/">Google</a>/<a href="http://del.icio.us/">del.icio.us</a>
<a href="http://greasemonkey.mozdev.org/">greasemonkey</a> <a href="http://userscripts.org/">userscript</a> idea:</p>

<blockquote>
  <p>Use case: I search for &#8220;tuna sandwich&#8221; and Google brings up
  http://www.starkist.com/recipes/sandwiches/classictuna.html
  among a host of
  other tuna-related links. A Greasemonkey script pays attention to
  which link I click on and upon the click event, bookmarks this page
  with the tags &#8220;tuna&#8221; and &#8220;sandwich&#8221;.</p>
</blockquote>

<p>People agreed that it is neat, but then
Lenny Domnitser <a href="http://mozdev.org/pipermail/greasemonkey/2005-November/006613.html">replied</a> that the same could
be easily and more conveniently accomplished
with a simple modification of the
&#8220;Post to del.icio.us&#8221; bookmarklet:</p>

<pre><code>javascript:
var t,q=document.referrer.match(/q=([^&amp;]+)/);
if(q){t='&amp;tags='+q[1];}else{t=''}
location.href='http://del.icio.us/YOURDELICIOUS?url='+
encodeURIComponent(location.href)+'&amp;title='+
encodeURIComponent(document.title)+t;
</code></pre>

<p>Simply replace <code>YOURDELICIOUS</code> with your del.icio.us account name,
and make it one long line, then add it to your Firefox bookmarks.</p>

<p>Works like a charm, thanks, Lenny!</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Selecting words in xterm</title>
    <link rel="alternate" type="text/html" href="http://blog.tobez.org/2005/09/selecting-words-in-xterm.html" />
    <id>tag:blog.tobez.org,2005://3.42</id>

    <published>2005-09-13T07:50:46Z</published>
    <updated>2009-03-01T12:07:11Z</updated>

    <summary> I&#8217;ve been using this feature for years now, and it is surprizing that not many xterm users are aware of it. When one double-clicks in xterm, a &#8220;word&#8221; is selected. By default, one gets selection like this: http://blog.tobez.org/, if...</summary>
    <author>
        <name>tobez</name>
        
    </author>
    
        <category term="Hints" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.tobez.org/">
        <![CDATA[<p><img src="http://www.tobez.org/images/blog/xterm.png" alt="xterm" /></p>

<p>I&#8217;ve been using this feature for years now, and it is surprizing that not many xterm users are aware of it.
When one double-clicks in xterm, a &#8220;word&#8221; is selected.  By default, one gets selection like this: http://blog.<u>tobez</u>.org/, if one double-clicks on an <b>e</b> there.  This is OK for some usage patterns, but suboptimal for many others.  Fortunately, it is possible to override xterm&#8217;s notion of what to select, by using a <code>charClass</code> resource.
I have the following in my .Xdefaults file:
<code>
XTerm*charClass: 33:48,36-38:48,43-47:48,58:48,61:48,63-64:48,126:48
</code>
Admittedly, this is a bit cryptic.  That&#8217;s probably why this feature is so underused.
So please, go and read the &#8220;CHARACTER CLASSES&#8221; section in the xterm manual page, and tinker until satisfied.
Oh and by the way, this is a sole single thing which made me switch from rxvt and its various clones back to xterm.</p>
]]>
        

    </content>
</entry>

</feed>
