<?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>Silas Sewell</title>
    <link>http://silas.sewell.org</link>
    <atom:link href="http://silas.sewell.org/rss2.xml" rel="self" type="application/rss+xml" />
    <description>Silas Sewell's blog</description>
    <language>en-us</language>
    <pubDate>Thu, 04 Apr 2013 04:47:33 PDT</pubDate>
    <lastBuildDate>Thu, 04 Apr 2013 04:47:33 PDT</lastBuildDate>

    
    <item>
      <title>Getting Started with Cloud Foundry's Warden</title>
      <link>http://silas.sewell.org/blog/2012/10/06/getting-started-with-cloud-foundrys-warden/</link>
      <pubDate>Sat, 06 Oct 2012 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2012/10/06/getting-started-with-cloud-foundrys-warden</guid>
      <description>&lt;p&gt;&lt;a href=&quot;https://github.com/cloudfoundry/warden/tree/master/warden#readme&quot;&gt;warden&lt;/a&gt; is a framework that allows you to spawn containers in
seconds and programmatically control resource isolation (memory, bandwidth,
disk), mounts, proccesses and other things.&lt;/p&gt;

&lt;p&gt;At its core warden is a Ruby daemon and collection of clients developed and
maintained as part of VMware&amp;#39;s open source &lt;a href=&quot;http://en.wikipedia.org/wiki/Platform_as_a_service&quot;&gt;PaaS&lt;/a&gt; &lt;a href=&quot;http://www.cloudfoundry.org/&quot;&gt;Cloud Foundry&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this post I&amp;#39;ll cover setting up warden in a &lt;a href=&quot;http://vagrantup.com/&quot;&gt;Vagrant&lt;/a&gt; box and
laundry list of commands via builtin &lt;a href=&quot;http://en.wikipedia.org/wiki/REPL&quot;&gt;repl&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To get started you&amp;#39;ll need &lt;a href=&quot;http://vagrantup.com/v1/docs/getting-started/index.html&quot;&gt;Vagrant&lt;/a&gt; and &lt;a href=&quot;http://git-scm.com/&quot;&gt;Git&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once those are installed grab &lt;a href=&quot;https://github.com/silas/vagrant-warden&quot;&gt;vagrant-warden&lt;/a&gt; and up the box:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;$ git clone git://github.com/silas/vagrant-warden.git
$ cd vagrant-warden
$ git submodule init
$ git submodule update
$ vagrant up
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After the box finishes booting you want to open another terminal, one to run
the server and the other to run the repl.&lt;/p&gt;

&lt;p&gt;In the server terminal ssh to the vagrant box and start the warden server:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;$ vagrant ssh
$ sudo warden-server
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the client terminal ssh to the box again and start the warden repl:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;$ vagrant ssh
$ sudo warden-repl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally step through the commands below to get an idea of what you can do with
warden.&lt;/p&gt;

&lt;p&gt;Create container&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;warden&amp;gt; create
handle : 16bcqds1452
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;List containers&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;warden&amp;gt; list
handles[0] : 16bcqds1452
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Get info on a container&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;warden&amp;gt; info --handle 16bcqds1452
state : active
host_ip : 10.254.0.9
container_ip : 10.254.0.10
container_path : /opt/warden/warden/data/containers/16bcqds1452
...
memory_stat.rss : 2863104
memory_stat.swap : 0
...
cpu_stat.usage : 201273681
cpu_stat.user : 0
cpu_stat.system : 0
disk_stat.bytes_used : 20480
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Map a host port to a container port&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;warden&amp;gt; net_in --handle 16bcqds1452 --container_port 8000
host_port : 61001
container_port : 8000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Spawn a process in a container&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;warden&amp;gt; spawn --handle 16bcqds1452 --script &amp;#39;echo hello | nc -l 8000&amp;#39;
job_id : 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Interact with a mapped port (in a third terminal)&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;$ vagrant ssh
$ echo world | nc 10.254.0.9 61001
hello
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Get results of spawned proccess&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;warden&amp;gt; link --handle 16bcqds1452 --job_id 2
exit_status : 0
stdout : world

stderr :
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Copy data into and out of a container&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;warden&amp;gt; copy_in --handle 16bcqds1452 --src_path /tmp --dst_path /tmp/bla
warden&amp;gt; copy_out --handle 16bcqds1452 --src_path /tmp/bla --dst_path /tmp/bla-out
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And more via the help command&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;warden&amp;gt; help
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Updated liquid-inheritance (liquid-blocks)</title>
      <link>http://silas.sewell.org/blog/2012/09/07/updated-liquid-inheritance-liquid-blocks/</link>
      <pubDate>Fri, 07 Sep 2012 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2012/09/07/updated-liquid-inheritance-liquid-blocks</guid>
      <description>&lt;p&gt;I&amp;#39;ve updated Dan Webb&amp;#39;s &lt;a href=&quot;https://rubygems.org/gems/liquid-inheritance&quot;&gt;liquid-inheritance&lt;/a&gt; to work with the
latest version of the &lt;a href=&quot;http://liquidmarkup.org/&quot;&gt;Liquid templating language&lt;/a&gt; and published the
result as &lt;a href=&quot;https://rubygems.org/gems/liquid-blocks&quot;&gt;liquid-blocks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It includes an example &lt;a href=&quot;https://github.com/silas/liquid-blocks/tree/master/examples/sinatra&quot;&gt;Sinatra project&lt;/a&gt; for anyone looking to get
started quickly.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Building RPMs using brpm</title>
      <link>http://silas.sewell.org/blog/2012/07/15/build-rpms-using-brpm/</link>
      <pubDate>Sun, 15 Jul 2012 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2012/07/15/build-rpms-using-brpm</guid>
      <description>&lt;p&gt;Building RPMs for Fedora or the Enterprise Linux variants is a pain in the
butt. My attempt at remedying this problem is a little command line tool
called &lt;code&gt;brpm&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The idea is to have sane defaults and do as much of the manual work as
possible.&lt;/p&gt;

&lt;p&gt;So if you have a spec file named &lt;code&gt;bla.spec&lt;/code&gt; in the current working directory,
you just run &lt;code&gt;brpm&lt;/code&gt; and the tool will download all your sources, create a
source and binary RPMs for your current distro (ex: Fedora 17) and
architecture (ex: x86_64). The log files for the build will be in &lt;code&gt;./build&lt;/code&gt;
and a yum repository with the build results will be created in
&lt;code&gt;../build/&amp;lt;distro-name&amp;gt;/&amp;lt;distro-version&amp;gt;/&amp;lt;arch&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The reason for creating a yum repository is to make it easy to chain builds of
RPMs that require their precursed to build.&lt;/p&gt;

&lt;p&gt;Setup&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install the latest version of Fedora (local or vm)&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the following yum repository&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;sudo curl http://dl.sewell.org/rpm/sewell/fedora/sewell.repo \
  -O /etc/yum.repos.d/sewell.repo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install &lt;code&gt;brpm&lt;/code&gt; RPM&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;sudo yum install brpm -y
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add yourself to the mock group&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;sudo usermod -G mock $USER
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Usage&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create an rpm and spec directory&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;mkdir -p rpm/python-ssh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Switch to the directory and grab a spec&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;cd rpm/python-ssh

curl https://raw.github.com/silas/rpms/master/python-ssh/python-ssh.spec \
  -O python-ssh.spec
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build the RPM&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;brpm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For more information see &lt;code&gt;brpm --help&lt;/code&gt; and the
&lt;a href=&quot;https://github.com/silas/brpm&quot;&gt;brpm&lt;/a&gt; page.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Setup Gitolite on Ubuntu (Maverick)</title>
      <link>http://silas.sewell.org/blog/2011/01/08/setup-gitolite-on-ubuntu/</link>
      <pubDate>Sat, 08 Jan 2011 00:00:00 PST</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2011/01/08/setup-gitolite-on-ubuntu</guid>
      <description>&lt;p&gt;Below is a quick guide to installing &lt;a href=&quot;https://github.com/sitaramc/gitolite&quot;&gt;Gitolite&lt;/a&gt; on Ubuntu.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create an SSH public/private key pair&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[silas@client]$ ssh-keygen -t rsa
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upload the public key to the server&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[silas@client]$ scp ~/.ssh/id_rsa.pub user@server.example.org:/tmp/user.pub
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SSH to the server and become &lt;code&gt;root&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[silas@client]$ ssh user@server.example.org
[silas@server]$ sudo su -
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install &lt;code&gt;gitolite&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[root@server]# apt-get install gitolite
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Switch to the &lt;code&gt;gitolite&lt;/code&gt; user&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[root@server]# su - gitolite
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run the Gitolite setup script&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[gitolite@server]$ gl-setup /tmp/user.pub
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;From your client computer clone the &lt;code&gt;gitolite-admin&lt;/code&gt; repository&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[silas@client]$ git clone gitolite@server.example.org:gitolite-admin
Cloning into gitolite-admin...
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (6/6), done.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Switch to the &lt;code&gt;gitolite-admin&lt;/code&gt; directory&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[silas@client]$ cd gitolite-admin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a &lt;code&gt;test&lt;/code&gt; repository&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[silas@client]$ vim conf/gitolite.conf
[silas@client]$ git commit -a -m &amp;quot;Add test repository&amp;quot;
[master 507045a] Add test repository
 1 files changed, 3 insertions(+), 0 deletions(-)
[silas@client]$ git push
Counting objects: 7, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 376 bytes, done.
Total 4 (delta 1), reused 0 (delta 0)
remote: Already on &amp;#39;master&amp;#39;
remote: creating test...
remote: Initialized empty Git repository in /var/lib/gitolite/repositories/test.git/
To gitolite@server.example.org:gitolite-admin
   87cc470..507045a  master -&amp;gt; master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clone the &lt;code&gt;test&lt;/code&gt; repository&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[silas@client]$ git clone gitolite@server.example.org:test
Cloning into test...
warning: You appear to have cloned an empty repository.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a &lt;code&gt;README&lt;/code&gt; file to the &lt;code&gt;test&lt;/code&gt; repository&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[silas@client]$ echo &amp;quot;Test Repo&amp;quot; &amp;gt; README
[silas@client]$ git commit -a -m &amp;quot;Initial commit&amp;quot;
[master (root-commit) 4a49ee0] Initial commit
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 README
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Push the changes to the server&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[silas@client]$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 218 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To gitolite@server.example.org:test
 * [new branch]      master -&amp;gt; master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Check out the Gitolite &lt;a href=&quot;https://github.com/sitaramc/gitolite/wiki/&quot;&gt;wiki&lt;/a&gt; for more documentation.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>txsrv: Message-based Twisted Services</title>
      <link>http://silas.sewell.org/blog/2010/09/12/txsrv-message-based-twisted-services/</link>
      <pubDate>Sun, 12 Sep 2010 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2010/09/12/txsrv-message-based-twisted-services</guid>
      <description>&lt;p&gt;I&amp;#39;ve started work on &lt;a href=&quot;http://github.com/silas/txsrv&quot; title=&quot;txsrv&quot;&gt;txsrv&lt;/a&gt;, a Python library that aims to make
developing message-based services in Twisted easy.&lt;/p&gt;

&lt;p&gt;The code is still pretty rough, but might be of interest to someone hacking on
AMQP-based Twisted services.&lt;/p&gt;

&lt;p&gt;Sample Usage&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a new service and change to the project directory.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;$ txsrv create mytest
$ cd mytest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Edit the &lt;code&gt;mytest.conf&lt;/code&gt; file so that the &lt;code&gt;spec_file&lt;/code&gt; option is valid.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[connection:amqp]
type = amqp
host = localhost
port = 5672
vhost = /
user = guest
password = guest
spec_file = /usr/share/amqp/amqp.0-8.xml

[handler:hello]
connection = amqp
exchange = hello
routing_key = default
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Edit the &lt;code&gt;mytest.py&lt;/code&gt; file so that it prints the message body twice.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;import txsrv

class Service(txsrv.Service):
    @txsrv.handler(&amp;#39;hello&amp;#39;)
    def hello(self, message):
        print message.body * 2

class ServiceMaker(txsrv.ServiceMaker):
    tapname = &amp;#39;mytest&amp;#39;
    description = &amp;#39;A mytest txsrv example.&amp;#39;
    service_type = Service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start the &lt;code&gt;mytest&lt;/code&gt; service and send a message to the &lt;code&gt;hello&lt;/code&gt; exchange.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;$ twistd -n mytest -c mytest.conf
2010-09-12 00:41:10-0400 [-] Log opened.
2010-09-12 00:41:10-0400 [-] twistd 10.1.0 (/usr/bin/python 2.6.4) starting up.
2010-09-12 00:41:10-0400 [-] reactor class: twisted.internet.selectreactor.SelectReactor.
2010-09-12 00:41:10-0400 [-] Starting factory &amp;lt;txsrv.protocol.amqp.AmqpFactory instance at 0x2cce950&amp;gt;
2010-09-12 00:41:10-0400 [AmqpProtocol,client] hellohello
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>Go Programming Language: Hello World (Fedora 13)</title>
      <link>http://silas.sewell.org/blog/2010/07/28/go-programming-language-hello-world-fedora-13/</link>
      <pubDate>Wed, 28 Jul 2010 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2010/07/28/go-programming-language-hello-world-fedora-13</guid>
      <description>&lt;p&gt;If you&amp;#39;re interested in trying the &lt;a href=&quot;http://golang.org/&quot;&gt;Go Programming Language&lt;/a&gt; I&amp;#39;ve created
an RPM for Fedora 13 to get you started quick (this package is in no way
suitable for submission to Fedora).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Download the &lt;a href=&quot;http://silas.fedorapeople.org/packages/go/go-0.0.0-0.1.release.2010.07.14.fc13.x86_64.rpm&quot;&gt;x86_64&lt;/a&gt; (or &lt;a href=&quot;http://silas.fedorapeople.org/packages/go/go-0.0.0-0.1.release.2010.07.14.fc13.i686.rpm&quot;&gt;i386&lt;/a&gt;) RPM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install the Go package using yum.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;sudo yum localinstall --nogpgcheck go-0.0.0*.rpm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open a new shell.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a file named &lt;code&gt;hello.go&lt;/code&gt; and enter the following code:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;package main

import &amp;quot;fmt&amp;quot;

func main() {
  fmt.Printf(&amp;quot;Hello World!&amp;quot;)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compile, link and run (replace &lt;code&gt;6&lt;/code&gt; with &lt;code&gt;8&lt;/code&gt; if you&amp;#39;re using i386).&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;$ 6g hello.go
$ 6l hello.6
$ ./6.out
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can view the latest RPM source on &lt;a href=&quot;http://github.com/silas/rpms/tree/master/go/&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update&lt;/em&gt;: It looks like someone has already created a much better
&lt;a href=&quot;https://bugzilla.redhat.com/show_bug.cgi?id=610934&quot;&gt;package&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>GNU Screen Profiles</title>
      <link>http://silas.sewell.org/blog/2010/07/14/gnu-screen-profiles/</link>
      <pubDate>Wed, 14 Jul 2010 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2010/07/14/gnu-screen-profiles</guid>
      <description>&lt;p&gt;If you&amp;#39;re a regular &lt;a href=&quot;http://www.gnu.org/software/screen/&quot; title=&quot;GNU Screen&quot;&gt;GNU Screen&lt;/a&gt; user might find this hack for creating
profiles useful.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a &lt;code&gt;.screen&lt;/code&gt; directory in your home directory.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;mkdir &amp;quot;$HOME/.screen&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the following to your &lt;code&gt;.bashrc&lt;/code&gt; or &lt;code&gt;.bash_profile&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;sp() {
  if [[ -z &amp;quot;$1&amp;quot; ]]; then
    screen
  elif [[ -f &amp;quot;$HOME/.screen/$1&amp;quot; ]]; then
    screen -c &amp;quot;$HOME/.screen/$1&amp;quot;
  else
    echo &amp;quot;Unknown screen profile &amp;#39;$1&amp;#39;.&amp;quot;
  fi
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a file in the &lt;code&gt;~/.screen&lt;/code&gt; directory with whatever profile name you
 would like to use (below is a sample profile named &lt;code&gt;tyrion&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;You should copy the first line into each profile as it loads your default
 GNU Screen settings.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;source &amp;quot;$HOME/.screenrc&amp;quot;

chdir &amp;quot;$HOME/src/tyrion/src&amp;quot;
screen -t code  0

chdir &amp;quot;$HOME/src/tyrion&amp;quot;
screen -t build  1

chdir &amp;quot;$HOME/src/tyrion/tests&amp;quot;
screen -t tests  2

chdir &amp;quot;$HOME/src/tyrion&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reload your shell and test your profile (replace &lt;code&gt;tyrion&lt;/code&gt; with whatever
 name you picked).&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;sp tyrion
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>Introduction to Tyrion</title>
      <link>http://silas.sewell.org/blog/2010/07/07/introduction-to-tyrion/</link>
      <pubDate>Wed, 07 Jul 2010 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2010/07/07/introduction-to-tyrion</guid>
      <description>&lt;p&gt;Today I wanted to introduce Tyrion to the Fedora Planet and anyone who happens
to read my blog.&lt;/p&gt;

&lt;p&gt;Tyrion is in short a lightweight &lt;a href=&quot;https://fedorahosted.org/func/&quot;&gt;Func&lt;/a&gt; replacement.&lt;/p&gt;

&lt;h3&gt;Why Tyrion?&lt;/h3&gt;

&lt;p&gt;I created Tyrion because Func didn&amp;#39;t meet some of my needs, specifically the
points outlined below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(1) Asynchronous&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tyrion was built using a protocol which is inherently asynchronous. This has
lead to lower latency operations and better scalability.&lt;/p&gt;

&lt;p&gt;That isn&amp;#39;t to say Func couldn&amp;#39;t be updated to be asynchronous (using the Twisted
XML-RPC libraries for example), but I think current toolsets highly favor
protocols which were designed from the beginning to be asynchronous.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(2) Language Agnostic&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;From a technical perspective Func is also language agnostic (it uses XML-RPC as
a transport protocol) and although you could write a client or server in any
language, from a pragmatic standpoint you&amp;#39;re stuck writing services in Python.&lt;/p&gt;

&lt;p&gt;On the other hand Tyrion is written in C++ and each service is a simple
executable.  This lends itself nicely to writing services in whatever language
is most appropriate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(3) Low memory footprint&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Func is written in Python and as such suffers from a dynamic language&amp;#39;s higher
memory usage.&lt;/p&gt;

&lt;p&gt;For example, the following Python application uses ~4.2MB memory on my Fedora 13
box.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;#!/usr/bin/env python

import time

time.sleep(60)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;While the complete &lt;code&gt;tyrion-node&lt;/code&gt; application uses ~4.5MB.&lt;/p&gt;

&lt;p&gt;For many systems administrators the difference between Func and &lt;code&gt;tyrion-node&lt;/code&gt;&amp;#39;s
memory usage will be negligible, but if you running an infrastructure with
several hundred or several thousand hosts the resource difference can be
enormous.&lt;/p&gt;

&lt;p&gt;A lower memory footprint is also advantageous to companies who heavily utilize
virtualization. If you have 5 servers and you slice those up into 4 virtual
machines each, you&amp;#39;ve just jumped from 5 to 20 daemons. Lets say Func uses 15MB
memory, that&amp;#39;s a 60MB to 300MB jump compared to &lt;code&gt;tyrion-node&lt;/code&gt;&amp;#39;s 22.5MB to 90MB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(4) Permissions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The protocol that Tyrion uses has built-in support for users. This allows Tyrion
to support user specific permissions on a service level and opens up some really
cool possibility, such as exposing services to partially trusted users.&lt;/p&gt;

&lt;p&gt;In addition because Tyrion uses a process model to run each service, a
configuration setting can be defined to specify under which user and group a
service is run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(5) Cloud&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a somewhat stupid bullet, but it does have some credibility. Func was
created to rely on a hostname/certificate combindation and the assumption that
we could communicate to a managed host on a defined port. This setup works great
when you have full control over your network.&lt;/p&gt;

&lt;p&gt;Unfortunately many of us use external resources (AWS, Linode, Slicehost, etc...)
where some or much of the network and infrastructure configuration is out of our
control.&lt;/p&gt;

&lt;p&gt;Tyrion was built on the &lt;a href=&quot;http://en.wikipedia.org/wiki/Xmpp&quot;&gt;XMPP&lt;/a&gt; protocol, this means that Tyrion connects
to a XMPP server and just listens for events.&lt;/p&gt;

&lt;p&gt;With XMPP we also get authentication, an encrypted transport, some
decentralization, federation, a solid selection of open source and scalable
servers and clients for pretty much every language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(6) Hot Reloads&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The ability to update configuration settings and install services without a
daemon restart.&lt;/p&gt;

&lt;h3&gt;Overview&lt;/h3&gt;

&lt;p&gt;This will briefly overview how Tyrion works.&lt;/p&gt;

&lt;p&gt;The Tyrion package has two primary parts, the &lt;code&gt;tyrion&lt;/code&gt; client and the
&lt;code&gt;tyrion-node&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tyrion-node&lt;/code&gt; is daemon which runs on each managed server. It boots with the
host, connects to an XMPP server and listens for service requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tyrion-node Configuration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Below is the general configuration settings for &lt;code&gt;tyrion-node&lt;/code&gt; which are located
in the &lt;code&gt;node.conf&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[general]
acl_path = /etc/tyrion/acl.conf                 ; ACL configuration file
log_path = /var/log/tyrion/node.log             ; Logging path
log_level = info                                ; Logging level
service_path = /usr/share/tyrion/service        ; Service directory

[xmpp]
jid = test.node@example.org/tyrion              ; Tyrion node JID
password = test.node.pass                       ; Tyrion node password
;server = example.org                            ; Server address if different from JID domain
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;node.conf&lt;/code&gt; file also lets you define default values for installed services.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[service:org.tyrion.service.bash]
timeout = 300                                   ; Default service timeout (seconds)
timeout_lock = false                            ; Lock default timeout setting
user = mike                                     ; Default user to run service as
user_lock = false                               ; Lock default user setting
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This tells Tyrion that the &lt;code&gt;org.tyrion.service.bash&lt;/code&gt; service should have a
default timeout of &lt;code&gt;300&lt;/code&gt; seconds and run as the user &lt;code&gt;mike&lt;/code&gt;. In this case
because we haven&amp;#39;t locked the &lt;code&gt;timeout&lt;/code&gt; or &lt;code&gt;user&lt;/code&gt; option they can be overriden
by the requester.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tyrion-node Service&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you were to look in the &lt;code&gt;service_path&lt;/code&gt; directory you would see an executable
file named &lt;code&gt;org.tyrion.service.bash&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[silas@example.org]$ cat /usr/share/tyrion/service/org.tyrion.service.bash 
#!/usr/bin/env sh

/usr/bin/env bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Obviously this service is a bit redundant and not all that interesting, but
serves as a good example of how a service works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tyrion Client&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First we&amp;#39;ll cover the basics of the &lt;code&gt;tyrion&lt;/code&gt; client. Then we&amp;#39;ll use that
information to make a basic service request and follow that request from the
client to the node and back again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tyrion Client Configuration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First the &lt;code&gt;client.conf&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[xmpp]
jid = test.client@example.org                   ; Tyrion node JID
password = test.client.pass                     ; Tyrion node password
;server = example.org                            ; Server address if different from JID domain

[profile:test]
jid = test.node@example.org/tyrion              ; Default destination JID
service = org.tyrion.service.bash               ; Default service type
timeout = 300                                   ; Default timeout
user = usertest                                 ; Default user
group = grouptest                               ; Default group
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can see that like the &lt;code&gt;node.conf&lt;/code&gt; file we have our XMPP options under the
&lt;code&gt;xmpp&lt;/code&gt; section. Below that we also have a default profile called &lt;code&gt;test&lt;/code&gt;. Similiar
to the service section in the &lt;code&gt;node.conf&lt;/code&gt; file this lets us setup some basic
defaults. Here we&amp;#39;re defining a destination jid, service, timeout, user and
group.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tyrion Client Options&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Additionally if we ran the help option on &lt;code&gt;tyrion&lt;/code&gt; we would see the following:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[silas@example.org]$ tyrion --help
Usage: tyrion [OPTION]...
Example: tyrion -c client.conf

Configuration options:
  -c, --config-file         the node configuration file
  -p, --profile             default service options

Service options:
  -j, --jid                 destination JID(s)
  -s, --service             service type
  -t, --timeout             max service run time
  -u, --user                run service as user
  -g, --group               run service as group

Misc options:
  --debug                   show debug information
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;tyrion Client Usage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So an example usage of &lt;code&gt;tyrion&lt;/code&gt; might be:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[silas@example.org]$ echo &amp;quot;echo test&amp;quot; | tyrion -c client.conf -p test
test.node@example.org/tyrion (0): test
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we&amp;#39;ve run &lt;code&gt;tyrion&lt;/code&gt; with the &lt;code&gt;client.conf&lt;/code&gt; configuration file and the profile
&lt;code&gt;test&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We sent &lt;code&gt;echo test&lt;/code&gt; to the &lt;code&gt;org.tyrion.service.bash&lt;/code&gt; service and got the exit
code &lt;code&gt;0&lt;/code&gt; and the result &lt;code&gt;test&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tyrion-node Handler&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;From the other side &lt;code&gt;tyrion-node&lt;/code&gt; sees a request from &lt;code&gt;test.client@example.org&lt;/code&gt;
to use the service &lt;code&gt;org.tyrion.service.bash&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[org.tyrion.service.bash]
test.client@example.org = true

[org.tyrion.service.python]
test.client@example.org = true

[org.tyrion.service.ruby]
test.client@example.org = true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After validating that request against the above &lt;code&gt;acl_path&lt;/code&gt; file it runs the
&lt;code&gt;/usr/share/tyrion/service/org.tyrion.service.bash&lt;/code&gt; executable and pipes
&lt;code&gt;echo test&lt;/code&gt; to stdin.&lt;/p&gt;

&lt;p&gt;When the service request completes or reaches the defined timeout it sends the
exit code, stdout and stderr back to the client.&lt;/p&gt;

&lt;h3&gt;txtyrion&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;tyrion&lt;/code&gt; client is really just for testing and one-off hacks. It not suppose
to be used in scripts or anything in production.&lt;/p&gt;

&lt;p&gt;Because of this I created &lt;code&gt;txtyrion&lt;/code&gt;, a Twisted-based Tyrion client library.&lt;/p&gt;

&lt;p&gt;A simple client application might look like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;from twisted.internet import defer, reactor

import txtyrion

class ExampleClient(txtyrion.Client):

    def success(self, response):
        print &amp;#39;=&amp;#39; * 80
        print &amp;#39;     ID:&amp;#39;, response.id
        print &amp;#39;    JID:&amp;#39;, response.jid
        print &amp;#39;   Code:&amp;#39;, response.code
        print &amp;#39;Service:&amp;#39;, response.service
        print &amp;#39; Output:&amp;#39;, response.output
        print &amp;#39;  Error:&amp;#39;, response.error

    def error(self, error):
        print &amp;#39;=&amp;#39; * 80
        print &amp;#39;Error:&amp;#39;, error

    def done(self, x):
        print &amp;#39;=&amp;#39; * 80
        reactor.stop()

    def run(self):
        jid = &amp;#39;test.node@example.org/tyrion&amp;#39;

        command = &amp;quot;&amp;quot;&amp;quot;
        sleep 1
        echo bash says hello stdout
        echo bash says hello stderr &amp;gt;&amp;amp;2
        false
        &amp;quot;&amp;quot;&amp;quot;
        d1 = self.request(jid, &amp;#39;org.tyrion.service.bash&amp;#39;, command)
        d1.addCallbacks(self.success, self.error)

        d2 = self.request(
            jid,
            &amp;#39;org.tyrion.service.python&amp;#39;,
            &amp;#39;print &amp;quot;python says hello&amp;quot;&amp;#39;,
        )
        d2.addCallbacks(self.success, self.error)

        dl = defer.DeferredList([d1, d2])
        dl.addCallback(self.done)

if __name__ == &amp;#39;__main__&amp;#39;:
    client = ExampleClient(
        &amp;#39;test.client@example.org&amp;#39;,
        &amp;#39;test.client.pass&amp;#39;,
        debug=True,
    )
    reactor.run()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;txtyrion also comes with a node library for creating custom Tyrion nodes
(see &lt;a href=&quot;https://github.com/silas/graveyard/tree/master/python-txtyrion/examples/example_node.py&quot;&gt;example&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;TyrionHub&lt;/h3&gt;

&lt;p&gt;It&amp;#39;s my goal to keep Tyrion simple; to let people utilize it for as much or as
little as is appropriate for their situation.&lt;/p&gt;

&lt;p&gt;That said I&amp;#39;ve created a separate project called TyrionHub which will provide a
Twisted-based system for managing nodes and a library of Python-based services
for systems automation.&lt;/p&gt;

&lt;p&gt;The immediate goals for TyrionHub are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User authentication using &lt;code&gt;twisted.cred&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Node authentication using &lt;code&gt;twisted.cred&lt;/code&gt; and an integration script for
ejabbard &lt;/li&gt;
&lt;li&gt;Node enrollment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&amp;#39;m currently building TyrionHub with the following technologies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Server: Twisted&lt;/li&gt;
&lt;li&gt;Database: MongoDB (although this may change)&lt;/li&gt;
&lt;li&gt;Web GUI: Google Closure Tools (JavaScript/Ajax/JSON)&lt;/li&gt;
&lt;li&gt;Services: Python with JSON serialization (simple as possible, avoid
frameworks and all unnecessary libraries)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Status&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://github.com/silas/tyrion&quot;&gt;Tyrion&lt;/a&gt; - working and &lt;a href=&quot;http://github.com/silas/rpms/tree/master/tyrion/&quot;&gt;packaged&lt;/a&gt; (not in any repo),
although it could use some code reviews by people comfortable with C++&lt;/li&gt;
&lt;li&gt;TyrionHub - just getting started, lots of work to do&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/silas/graveyard/tree/master/python-txtyrion&quot;&gt;txtyrion&lt;/a&gt; - working with various tweaks here and there&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Participation&lt;/h3&gt;

&lt;p&gt;If anyone is interesting in participating in the development/testing process or
would like to be contacted when TyrionHub is more feature complete, please
contact me at &lt;code&gt;silas@sewell.org&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;License&lt;/h3&gt;

&lt;p&gt;Everything will be BSD.&lt;/p&gt;

&lt;h3&gt;Follow-up&lt;/h3&gt;

&lt;p&gt;I&amp;#39;ll be posting a follow-up with a step-by-step explanation on how to setup a
basic working version of Tyrion in the next week or two.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>txmpp: A BSD Licensed C++ XMPP Library</title>
      <link>http://silas.sewell.org/blog/2010/06/16/txmpp-a-bsd-licensed-cpp-xmpp-library/</link>
      <pubDate>Wed, 16 Jun 2010 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2010/06/16/txmpp-a-bsd-licensed-cpp-xmpp-library</guid>
      <description>&lt;p&gt;&lt;a href=&quot;https://github.com/silas/txmpp&quot;&gt;txmpp&lt;/a&gt; is a permissively licensed (BSD) C++ XMPP library based on
&lt;a href=&quot;http://code.google.com/p/libjingle/&quot;&gt;libjingle&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The goals for txmpp and why it&amp;#39;s a separate project from libjingle are as
follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All code is under a single, unified namespace&lt;/li&gt;
&lt;li&gt;All code is permissively licensed&lt;/li&gt;
&lt;li&gt;Good build and install support for POSIX operating systems&lt;/li&gt;
&lt;li&gt;Focus on core XMPP components (the &lt;a href=&quot;http://xmpp.org/extensions/xep-0166.html&quot;&gt;XEP-0166&lt;/a&gt; related code has been removed)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&amp;#39;ve currently got the library building on Fedora 13, CentOS 5 and OS X. In the
near future I&amp;#39;m going to focus on removing the Windows code and reducing the
amount of code not directly tied to core XMPP functionality.&lt;/p&gt;

&lt;p&gt;With all that said I want to keep the core as close to libjingle as possible. I
think it&amp;#39;s important that txmpp can track and integrate changes from libjingle
in a relatively simple way.&lt;/p&gt;

&lt;p&gt;If you&amp;#39;re interested in messing around with the library I&amp;#39;d recommend checking
out the sample code in the &lt;a href=&quot;http://github.com/silas/txmpp/tree/master/src/examples/&quot;&gt;examples&lt;/a&gt; directory.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>node.js HTTPS (SSL) Server Example</title>
      <link>http://silas.sewell.org/blog/2010/06/03/node-js-https-ssl-server-example/</link>
      <pubDate>Thu, 03 Jun 2010 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2010/06/03/node-js-https-ssl-server-example</guid>
      <description>&lt;p&gt;A simple HTTPS server using node.js:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;const crypto = require(&amp;#39;crypto&amp;#39;),
      fs = require(&amp;quot;fs&amp;quot;),
      http = require(&amp;quot;http&amp;quot;);

var privateKey = fs.readFileSync(&amp;#39;privatekey.pem&amp;#39;).toString();
var certificate = fs.readFileSync(&amp;#39;certificate.pem&amp;#39;).toString();

var credentials = crypto.createCredentials({key: privateKey, cert: certificate});

var handler = function (req, res) {
  res.writeHead(200, {&amp;#39;Content-Type&amp;#39;: &amp;#39;text/plain&amp;#39;});
  res.end(&amp;#39;Hello World\n&amp;#39;);
};

var server = http.createServer();
server.setSecure(credentials);
server.addListener(&amp;quot;request&amp;quot;, handler);
server.listen(8000);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can generate the &lt;code&gt;privatekey.pem&lt;/code&gt; and &lt;code&gt;certificate.pem&lt;/code&gt; files using the
following commands:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;openssl genrsa -out privatekey.pem 1024 
openssl req -new -key privatekey.pem -out certrequest.csr 
openssl x509 -req -in certrequest.csr -signkey privatekey.pem -out certificate.pem
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Update: Thanks to &lt;a href=&quot;http://www.geekceo.com/&quot; title=&quot;Kord Campbell&quot;&gt;Kord Campbell&lt;/a&gt; for spotting an issue and sending a fix!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Auto-reload node.js (OS X)</title>
      <link>http://silas.sewell.org/blog/2010/05/16/auto-reload-node-js-os-x/</link>
      <pubDate>Sun, 16 May 2010 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2010/05/16/auto-reload-node-js-os-x</guid>
      <description>&lt;p&gt;&lt;a href=&quot;https://github.com/silas/graveyard/tree/master/python-restarter&quot; title=&quot;restarter&quot;&gt;restarter&lt;/a&gt; is a simple Python application which runs a specified
command and restarts the command each time a file event occurs in a specified
directory.&lt;/p&gt;

&lt;p&gt;I created restarter because there isn&amp;#39;t auto-reload functionality built into
&lt;a href=&quot;http://nodejs.org/&quot; title=&quot;node.js&quot;&gt;node.js&lt;/a&gt; (at the time of this post).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[silas@pluto keyfu.js]$ restarter node keyfu.js
Express started at http://localhost:3000/ in development mode
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Usage&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;Usage: restarter [options] command

Options:
  -h, --help     show this help message and exit
  --path=PATH    directory to watch for file event changes
  --ignore=PATH  specifies events to ignore
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Jinja2 Markdown Extension</title>
      <link>http://silas.sewell.org/blog/2010/05/10/jinja2-markdown-extension/</link>
      <pubDate>Mon, 10 May 2010 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2010/05/10/jinja2-markdown-extension</guid>
      <description>&lt;p&gt;Below is an example of a Markdown extension for &lt;a href=&quot;http://jinja.pocoo.org/2/documentation/&quot; title=&quot;Jinja2&quot;&gt;Jinja2&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;import jinja2
import jinja2.ext
import markdown2

class Markdown2Extension(jinja2.ext.Extension):
    tags = set([&amp;#39;markdown2&amp;#39;])

    def __init__(self, environment):
        super(Markdown2Extension, self).__init__(environment)
        environment.extend(
            markdowner=markdown2.Markdown()
        )   

    def parse(self, parser):
        lineno = parser.stream.next().lineno
        body = parser.parse_statements(
            [&amp;#39;name:endmarkdown2&amp;#39;],
            drop_needle=True
        )
        return jinja2.nodes.CallBlock(
            self.call_method(&amp;#39;_markdown_support&amp;#39;),
            [],
            [],
            body
        ).set_lineno(lineno)

    def _markdown_support(self, caller):
        return self.environment.markdowner.convert(caller()).strip()

env = jinja2.Environment(extensions=[Markdown2Extension])

text = &amp;quot;&amp;quot;&amp;quot; 
{ % markdown2 %}
Hello World
===========

 1. One
 2. 
 3. Three
{ % endmarkdown2 %}
&amp;quot;&amp;quot;&amp;quot;

html = env.from_string(text).render(two=&amp;#39;Two&amp;#39;)

print html
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Which would result in the following output:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;&amp;lt;h1&amp;gt;Hello World&amp;lt;/h1&amp;gt;

&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;One&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Two&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Three&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Google App Engine Middleware (gaem)</title>
      <link>http://silas.sewell.org/blog/2009/12/29/google-app-engine-middleware-gaem/</link>
      <pubDate>Tue, 29 Dec 2009 00:00:00 PST</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2009/12/29/google-app-engine-middleware-gaem</guid>
      <description>&lt;p&gt;&lt;a href=&quot;https://github.com/silas/graveyard/tree/master/python-gaem&quot; title=&quot;Google App Engine Middleware&quot;&gt;Google App Engine Middleware&lt;/a&gt; (gaem) is a collection of utilities for
hosting external sites on Google App Engine.&lt;/p&gt;

&lt;p&gt;I created gaem because I wanted to host my blog on an unreliable server and let
Google App Engine serve the content while my server was down or in maintenance
mode.&lt;/p&gt;

&lt;p&gt;The basic design is similar to that of &lt;a href=&quot;http://docs.djangoproject.com/en/dev/topics/http/middleware/&quot; title=&quot;Django&amp;#39;s middleware&quot;&gt;Django&amp;#39;s middleware&lt;/a&gt;. A request
travels through a list of components which can either manipulate the request or
provide a response. The response is filtered back through the components and
served to the requester.&lt;/p&gt;

&lt;p&gt;A basic implementation looks something like&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;import gaem
import gaem.middleware
import gaem.middleware.cache
import gaem.middleware.dos
import gaem.middleware.fetch

URL = &amp;#39;http://www.example.org&amp;#39;

MIDDLEWARE_CLASSES = (
    gaem.middleware.cache.Memcache(),
    gaem.middleware.cache.Datastore(),
    gaem.middleware.dos.DoS(),
    gaem.middleware.fetch.Fetch(url=URL),
)

application = gaem.Application(MIDDLEWARE_CLASSES)

if __name__ == &amp;#39;__main__&amp;#39;:
    application.run()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When a request first hits this application it is handled by the Memcache
component. This basic caching component checks the Google App Engine Memcache
service to see if the page is in the cache. If so it simply returns the cached
response, otherwise the request proceeds to the Datastore component which does
pretty much the same thing except it uses Google Datastore for persistence. If
both caching components fail the the request goes through a DoS protection
component and is finally retrieved from the backend server by the Fetch
component.&lt;/p&gt;

&lt;p&gt;Using a setup like this gaem acts as a rudimentary reverse proxy and while most
of the functionality I&amp;#39;ve implemented thus far is for this type setup, I plan
on adding features not traditionally found in a reverse proxy.&lt;/p&gt;

&lt;h3&gt;Current Features&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/silas/graveyard/blob/master/python-gaem/gaem/middleware/cache.py&quot; title=&quot;Caching&quot;&gt;Caching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/silas/graveyard/blob/master/python-gaem/gaem/middleware/fetch.py&quot; title=&quot;Backend fetch&quot;&gt;Backend fetch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Gracefully handle a dead backend&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/silas/graveyard/blob/master/python-gaem/gaem/middleware/dos.py&quot; title=&quot;DoS protection&quot;&gt;DoS protection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/silas/graveyard/blob/master/python-gaem/gaem/middleware/api.py&quot; title=&quot;API for expiring content&quot;&gt;API for expiring content&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Possible Future Features&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Initial and periodic crawler (pre-cache and other hooks)&lt;/li&gt;
&lt;li&gt;RESTful API for managing content (put, delete, etc...)&lt;/li&gt;
&lt;li&gt;Web interface&lt;/li&gt;
&lt;li&gt;XSS protection&lt;/li&gt;
&lt;li&gt;Some ESI support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But what makes gaem really cool for developers is how easy it is to create
custom components.&lt;/p&gt;

&lt;p&gt;A basic component looks like&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;from gaem import middleware

class DoesNothing(middleware.Base):

    def process_request(self, request):
        return request

    def process_response(self, response, request):
        return response
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A default gaem component should inherit from &lt;code&gt;gaem.middleware.Base&lt;/code&gt; and
implement &lt;code&gt;process_request&lt;/code&gt; and/or &lt;code&gt;process_response&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;process_request&lt;/code&gt; function lets you either manipulate the request (ex:
strip the &amp;quot;cookie&amp;quot; header) and pass it along or use the request to create and
return a response (ex: do a fetch to the backend server). The
&lt;code&gt;process_response&lt;/code&gt; function lets you filter the response (ex: translate body
into pig latin) and do side affects (ex: store response in memcache) before the
response is sent to the requester.&lt;/p&gt;

&lt;p&gt;The Request/Response objects are borrowed from &lt;a href=&quot;http://pythonpaste.org/webob/&quot; title=&quot;WebOb&quot;&gt;WebOb&lt;/a&gt; and can be
manipulated using the interfaces defined in the &lt;a href=&quot;http://pythonpaste.org/webob/modules/webob.html&quot; title=&quot;WebOb documentation&quot;&gt;WebOb documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;gaem is currently pretty rough and likely to change over the next couple of
months, but if you&amp;#39;re a Python hacker I&amp;#39;d love to hear some feedback
(&lt;a href=&quot;/about/contact/&quot; title=&quot;Contact Silas Sewell&quot;&gt;contact me&lt;/a&gt; or &lt;a href=&quot;https://github.com/silas/graveyard/issues&quot; title=&quot;gaem issues&quot;&gt;submit an issue&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;P.S. You can see the application I created for this site in the &lt;a href=&quot;https://github.com/silas/graveyard/tree/master/python-gaem/examples/wordpress&quot; title=&quot;gaem WordPress example&quot;&gt;examples directory&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Stomping with Python and ActiveMQ (Stomp Framework)</title>
      <link>http://silas.sewell.org/blog/2009/08/27/stomping-with-python-and-activemq-stomp-framework/</link>
      <pubDate>Thu, 27 Aug 2009 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2009/08/27/stomping-with-python-and-activemq-stomp-framework</guid>
      <description>&lt;p&gt;&lt;a href=&quot;http://silassewell.googlecode.com/svn/trunk/projects/python-stomping&quot; title=&quot;Python Stomping&quot;&gt;python-stomping&lt;/a&gt; is a simple &lt;a href=&quot;http://en.wikipedia.org/wiki/Streaming_Text_Orientated_Messaging_Protocol&quot; title=&quot;Stomp&quot;&gt;Stomp&lt;/a&gt; framework I wrote which makes
creating stomp services in Python easy.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Install requirements&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;$ sudo yum install python-twisted python-stomper
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Checkout stomping&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;$ svn export http://silassewell.googlecode.com/svn/trunk/projects/python-stomping python-stomping
$ cd python-stomping
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the &lt;code&gt;example.py&lt;/code&gt; file to use your &lt;code&gt;host&lt;/code&gt;, &lt;code&gt;port&lt;/code&gt;, &lt;code&gt;username&lt;/code&gt; and
&lt;code&gt;password&lt;/code&gt; ActiveMQ/Stomp broker settings&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;from stomping import Stomping, route

class MyStomping(Stomping):

def init(self):
    self.send(&amp;#39;/queue/test1&amp;#39;, &amp;#39;init test1&amp;#39;)
    self.send(&amp;#39;/queue/test2&amp;#39;, &amp;#39;init test2&amp;#39;)

@route(&amp;#39;/queue/test1&amp;#39;)
def a_test(self, message):
    print &amp;#39;a_test: %s&amp;#39; % message[&amp;#39;body&amp;#39;]

@route(&amp;#39;/queue/test1&amp;#39;)
@route(&amp;#39;/queue/test2&amp;#39;)
def b_test(self, message):
    print &amp;#39;b_test: %s&amp;#39; % message[&amp;#39;body&amp;#39;]

if __name__ == &amp;#39;__main__&amp;#39;:
    stomp = MyStomping(host=&amp;#39;127.0.0.1&amp;#39;, port=61613, username=&amp;#39;guest&amp;#39;, password=&amp;#39;guest&amp;#39;)
    stomp.run()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run &lt;code&gt;example.py&lt;/code&gt; (Ctrl+c to quit)&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;$ python example.py 
a_test: init test1
b_test: init test1
b_test: init test2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;NOTE: python-stomping is just a light wrapper around Twisted and stomper and is
based on an &lt;a href=&quot;http://code.google.com/p/stomper/source/browse/trunk/lib/stomper/examples/sender.py&quot; title=&quot;sender example&quot;&gt;example&lt;/a&gt; provided in the stomper code.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Qpid on CentOS 5</title>
      <link>http://silas.sewell.org/blog/2009/06/16/qpid-on-centos-5/</link>
      <pubDate>Tue, 16 Jun 2009 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2009/06/16/qpid-on-centos-5</guid>
      <description>&lt;h3&gt;Build using Fedora&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Install the RPM development tools&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;sudo yum install rpmdevtools mock
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add yourself to the &lt;code&gt;mock&lt;/code&gt; group&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;sudo /usr/sbin/usermod --groups mock --append $USER
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Setup build directories&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;rpmdev-setuptree
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install spec and source files (or get latest &lt;a href=&quot;ftp://ftp.redhat.com/pub/redhat/linux/enterprise/5Server/en/RHEMRG/SRPMS/&quot; title=&quot;RHEMRG SRPMS&quot;&gt;here&lt;/a&gt;)&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;rpm -i ftp://ftp.redhat.com/pub/redhat/linux/enterprise/5Server/en/RHEMRG/SRPMS/qpidc-0.5.752581-17.el5.src.rpm
rpm -i ftp://ftp.redhat.com/pub/redhat/linux/enterprise/5Server/en/RHEMRG/SRPMS/amqp-1.0.750054-1.el5.src.rpm
rpm -i ftp://ftp.redhat.com/pub/redhat/linux/enterprise/5Server/en/RHEMRG/SRPMS/python-qpid-0.5.752581-3.el5.src.rpm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build qpidc&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;rpmbuild -bs --nodeps ~/rpmbuild/SRPM/qpidc.spec
mock -vr epel-5-x86_64 ~/rpmbuild/SRPMS/qpidc-*.src.rpm
scp /var/lib/mock/epel-5-x86_64/result/*.rpm CENTOS_HOST:SOME_PATH
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build amqp&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;rpmbuild -bs --nodeps ~/rpmbuild/SPECS/amqp.spec
mock -vr epel-5-x86_64 ~/rpmbuild/SRPMS/amqp-*.src.rpm
scp /var/lib/mock/epel-5-x86_64/result/*.rpm CENTOS_HOST:SOME_PATH
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build python-qpid&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;rpmbuild -bs --nodeps ~/rpmbuild/SPECS/python-qpid.spec
mock -vr epel-5-x86_64 ~/rpmbuild/SRPMS/python-qpid-*.src.rpm
scp /var/lib/mock/epel-5-x86_64/result/*.rpm CENTOS_HOST:SOME_PATH
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;Install on CentOS&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Become root&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;sudo su -
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install Qpid server and Python client packages&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;cd SOME_PATH
yum localinstall --nogpgcheck qpidc-*.el5.x86_64.rpm qpidd-*.el5.x86_64.rpm amqp-*.el5.noarch.rpm python-qpid-*.el5.noarch.rpm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Disable auth for testing&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;echo &amp;#39;auth=no&amp;#39; &amp;gt;&amp;gt; /etc/qpidd.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start qpidd&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;service qpidd start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test using these &lt;a href=&quot;/blog/2009/03/29/getting-started-with-amqp-qpid-python-fedora/&quot; title=&quot;Getting Started with AMQP with Python&quot;&gt;instructions&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;NOTE: I realize you can build the SRPMs without installing them.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Python Line-by-line Profiler (line_profiler and kernprof)</title>
      <link>http://silas.sewell.org/blog/2009/05/28/python-line-by-line-profiler-line_profiler-and-kernprof/</link>
      <pubDate>Thu, 28 May 2009 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2009/05/28/python-line-by-line-profiler-line_profiler-and-kernprof</guid>
      <description>&lt;p&gt;The following is a quick and dirty guide to getting started with
&lt;a href=&quot;http://packages.python.org/line_profiler/&quot; title=&quot;line profiler&quot;&gt;line_profiler&lt;/a&gt;, a Python line-by-line profiler, on Fedora.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/silassewell/wiki/PackagingRPMs&quot; title=&quot;Packaging RPMS&quot;&gt;Build&lt;/a&gt; and install the &lt;a href=&quot;http://silassewell.googlecode.com/files/python-line_profiler-1.0-0.1.b2.fc10.src.rpm&quot; title=&quot;line profiler SRPM&quot;&gt;python-line_profiler&lt;/a&gt; package&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a file called &lt;code&gt;test.py&lt;/code&gt; with the code below&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;import random, time

def sleep():
    seconds = random.randint(0, 5)
    print &amp;#39;Sleeping %s seconds&amp;#39; % seconds
    time.sleep(seconds)

@profile
def test():
    sleep()
    sleep()
    sleep()

test()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Profile &lt;code&gt;test.py&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[silas@pluto ~]$ kernprof.py -l test.py
Sleeping 4 seconds
Sleeping 5 seconds
Sleeping 2 seconds
Wrote profile results to test.py.lprof
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;View the results&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[silas@pluto ~]$ python -m line_profiler test.py.lprof
Timer unit: 1e-06 s

File: test.py
Function: test at line 8
Total time: 10.9994 s

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     8                                           @profile
     9                                           def test():
    10         1      3999416 3999416.0     36.4      sleep()
    11         1      4999982 4999982.0     45.5      sleep()
    12         1      1999990 1999990.0     18.2      sleep()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;NOTE: I have a &lt;a href=&quot;https://bugzilla.redhat.com/show_bug.cgi?id=502978&quot; title=&quot;Package Review&quot;&gt;package review&lt;/a&gt; up for line_profiler and it should be
available via yum eventually.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Pipe Apache (or any) Logs to Scribe</title>
      <link>http://silas.sewell.org/blog/2009/05/12/pipe-apache-or-any-logs-to-scribe/</link>
      <pubDate>Tue, 12 May 2009 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2009/05/12/pipe-apache-or-any-logs-to-scribe</guid>
      <description>&lt;p&gt;I created a simple Python script called &lt;a href=&quot;http://github.com/silas/scribe_log&quot; title=&quot;scribe_log&quot;&gt;scribe_log&lt;/a&gt; to tail a log
file and pipe it to Scribe.&lt;/p&gt;

&lt;p&gt;I use &lt;a href=&quot;http://supervisord.org/&quot; title=&quot;Supervisor&quot;&gt;supervisor&lt;/a&gt; to start and keep the pipe running.&lt;/p&gt;

&lt;p&gt;Relevant supervisord.conf configuration:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[program:scribe.apache.access]
command=/usr/local/sbin/scribe_log --category apache.access --file /var/log/httpd/access_log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Options&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;usage: scribe_log [options]

options:
  -h, --help           show this help message and exit
  --file=FILE          file to tail into Scribe
  --category=CATEGORY  Scribe category
  --host=HOST          destination Scribe host server
  --port=PORT          destination Scribe port
  --prefix=PREFIX      add to the beginning of each log line
  --postfix=POSTFIX    add to the end of each log line
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Scribe - Scalable Real Time Log Aggregation for CentOS 5 / RHEL 5</title>
      <link>http://silas.sewell.org/blog/2009/05/07/scribe-scalable-real-time-log-aggregation-for-centos-5-rhel-5/</link>
      <pubDate>Thu, 07 May 2009 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2009/05/07/scribe-scalable-real-time-log-aggregation-for-centos-5-rhel-5</guid>
      <description>&lt;p&gt;&amp;quot;&lt;a href=&quot;http://developers.facebook.com/scribe/&quot; title=&quot;Scribe&quot;&gt;Scribe&lt;/a&gt; is a server for aggregating log data streamed in real time
from a large number of servers. It is designed to be scalable, extensible
without client-side modification, and robust to failure of the network or any
specific machine. Scribe was developed at Facebook and
&lt;a href=&quot;http://www.facebook.com/note.php?note_id=32008268919&amp;amp;#038;id=9445547199&amp;amp;#038;index=0&quot; title=&quot;Scribe Released as Open Source&quot;&gt;released as open source&lt;/a&gt;.&amp;quot;&lt;/p&gt;

&lt;p&gt;I&amp;#39;ve packaged &lt;a href=&quot;http://incubator.apache.org/thrift/&quot; title=&quot;Thrift&quot;&gt;Thrift&lt;/a&gt;, &lt;a href=&quot;http://svn.apache.org/repos/asf/incubator/thrift/trunk/contrib/fb303/README&quot;&gt;fb303&lt;/a&gt; and &lt;a href=&quot;http://developers.facebook.com/scribe/&quot; title=&quot;Scribe&quot;&gt;Scribe&lt;/a&gt; for CentOS 5 / RHEL 5.&lt;/p&gt;

&lt;h3&gt;SRPM&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://silassewell.googlecode.com/files/thrift-0.0-0.el5.20090505svn770888.src.rpm&quot;&gt;Thrift&lt;/a&gt; (&lt;a href=&quot;http://silassewell.googlecode.com/svn/trunk/2009/05/05/scribe-for-el5/thrift/&quot; title=&quot;Thrift Source&quot;&gt;Source&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://silassewell.googlecode.com/files/fb303-0.0-0.el5.20090505svn770888.src.rpm&quot; title=&quot;fb303 SRPM&quot;&gt;fb303&lt;/a&gt; (&lt;a href=&quot;http://silassewell.googlecode.com/svn/trunk/2009/05/05/scribe-for-el5/fb303/&quot; title=&quot;fb303 Source&quot;&gt;Source&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://silassewell.googlecode.com/files/scribe-2.01-2.el5.src.rpm&quot; title=&quot;Scribe SRPM&quot;&gt;Scribe&lt;/a&gt; (&lt;a href=&quot;http://silassewell.googlecode.com/svn/trunk/2009/05/05/scribe-for-el5/scribe/&quot; title=&quot;Scribe Source&quot;&gt;Source&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Scribe depends on fb303 which in turns depends on Thrift so you&amp;#39;ll need to
setup a local repository and build them in that order. To build the above
packages for Fedora 9+ you&amp;#39;ll need to tweak the Python sub-packages to include
the egg files.&lt;/p&gt;

&lt;p&gt;Both fb303 and Scribe need some tweaks upstream before they&amp;#39;re suitable for a
package review, but I&amp;#39;d like to get them in Fedora shortly (I&amp;#39;ve already
&lt;a href=&quot;https://bugzilla.redhat.com/show_bug.cgi?id=498873&quot; title=&quot;Thrift Review&quot;&gt;submitted Thrift&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;If you&amp;#39;d like to hack around with my latest Fedora specs you can grab them &lt;a href=&quot;http://github.com/silas/rpms&quot; title=&quot;GitHub RPM&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Managing Large Networks with Puppet</title>
      <link>http://silas.sewell.org/blog/2009/05/04/managing-large-networks-with-puppet/</link>
      <pubDate>Mon, 04 May 2009 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2009/05/04/managing-large-networks-with-puppet</guid>
      <description>&lt;p&gt;&lt;a href=&quot;http://projects.puppetlabs.com/projects/puppet&quot; title=&quot;Puppet&quot;&gt;Puppet&lt;/a&gt; is an open source configuration management tool written in
Ruby. It allows a systems administrator to define how a system should be
configured using &lt;a href=&quot;http://docs.reductivelabs.com/guides/language_tutorial.html&quot; title=&quot;Puppet Language Tutorial&quot;&gt;Puppet&amp;#39;s&lt;/a&gt; &lt;a href=&quot;http://en.wikipedia.org/wiki/Declarative_programming&quot; title=&quot;Declarative Programming&quot;&gt;declarative language&lt;/a&gt;. Each Puppet
client pulls its &lt;a href=&quot;http://projects.puppetlabs.com/projects/puppet/wiki/Glossary_Of_Terms#catalog&quot; title=&quot;Puppet Catalog&quot;&gt;catalog&lt;/a&gt; at a regular interval and figures out how
to make the catalog definitions true for the local operating system.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://docs.puppetlabs.com/guides/introduction.html&quot; title=&quot;Puppet Introduction&quot;&gt;Puppet Introduction&lt;/a&gt; uses the following diagram to show how
Puppet works.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/puppet_star.png&quot; alt=&quot;Puppet&quot; title=&quot;Puppet&quot;&gt;&lt;/p&gt;

&lt;p&gt;Currently Puppet is most useful when you have lots of nodes with similar setups. Unfortunately Puppet&amp;#39;s declarative language is a bit weak when it comes to inheritance and users familiar with true object oriented systems will soon become frustrated (at least I did). I&amp;#39;m assuming this issue will be addressed in the future, but for now I&amp;#39;m going to tell you how I setup a 100+ node system while adhering to &lt;a href=&quot;http://en.wikipedia.org/wiki/Don%27t_repeat_yourself&quot; title=&quot;DRY principles&quot;&gt;DRY principles&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A quick note, I&amp;#39;m assuming you already know how to use Puppet.&lt;/p&gt;

&lt;p&gt;First lets start with the Puppetmaster configuration layout:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;puppet/
 - fileserver.conf
 - manifests/
   - classes/
     - initialize.pp
   - nodes/
     - net/
       - example/
         - web01.pp   # web01.example.net
   - site.pp
   - templates.pp
 - modules/           # application specific modules
   - httpd/
     - files/         # static assets (ex: default HTML file)
     - manifests/     # application configuration logic
     - templates/     # dynamic configuration files (ex: httpd.conf)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;small&gt;The layout was adapted from recommendations in &lt;a href=&quot;http://www.amazon.com/Pulling-Strings-Puppet-Configuration-Management/dp/1590599780&quot; title=&quot;Pulling Strings with Puppet&quot;&gt;Pulling Strings with Puppet&lt;/a&gt; by James Turnbull.&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;When I was initially designing my Puppet setup the common practice was to define and initialize the various Puppet types and classes throughout the inheritance tree. So if you had a generic resolv.conf configuration you would include it at the top of the inheritance tree. This worked great until I needed to change one attribute of a class further down. I initially tackled this problem by hacking in if/case statements, but eventually it became unmanageable.&lt;/p&gt;

&lt;p&gt;After a couple of rewrites I came up with the idea of wrapping the internals of each class in a conditional statement and initializing all classes at the end of each node.&lt;/p&gt;

&lt;p&gt;The key components of my setup were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;import all modules in the site.pp manifest&lt;/li&gt;
&lt;li&gt;wrap the code of each class in a conditional statement&lt;/li&gt;
&lt;li&gt;define and extend attributes throughout the inheritance tree (including the class conditional)&lt;/li&gt;
&lt;li&gt;include all classes at the end of each node&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This lets you both arbitrarily redefine or extend class attributes (including the on/off state) throughout the inheritance tree.&lt;/p&gt;

&lt;p&gt;I&amp;#39;ve created a &lt;a href=&quot;http://silassewell.googlecode.com/svn/trunk/2009/05/03/puppet/&quot; title=&quot;Simple Example&quot;&gt;simple example&lt;/a&gt; to show how this setup works. The main files are listed below (you&amp;#39;ll want to go through each in order):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://raw.github.com/silas/graveyard/master/puppet-tree-example/manifests/site.pp&quot; title=&quot;site.pp&quot;&gt;site.pp&lt;/a&gt; - import modules&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://raw.github.com/silas/graveyard/master/puppet-tree-example/manifests/templates.pp&quot; title=&quot;template.pp&quot;&gt;templates.pp&lt;/a&gt; - define and extend class attributes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://raw.github.com/silas/graveyard/master/puppet-tree-example/manifests/nodes/nar/co/web01.pp&quot; title=&quot;web01.pp&quot;&gt;web01.pp&lt;/a&gt; - make use of defaults&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://raw.github.com/silas/graveyard/master/puppet-tree-example/manifests/nodes/nar/co/ns01.pp&quot; title=&quot;ns01.pp&quot;&gt;ns01.pp&lt;/a&gt; - disable a class&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://raw.github.com/silas/graveyard/master/puppet-tree-example/manifests/classes/initialize.pp&quot; title=&quot;initialize.pp&quot;&gt;initialize.pp&lt;/a&gt; - initialize all classes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://raw.github.com/silas/graveyard/master/puppet-tree-example/modules/resolv/manifests/client.pp&quot; title=&quot;client.pp&quot;&gt;client.pp&lt;/a&gt; - class implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also note that I designed this setup about 8 months ago and I haven&amp;#39;t kept as up-to-date on recent developments as I should. If there is a better way to do this please let me know.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>funcshell - A Shell Interface to Func</title>
      <link>http://silas.sewell.org/blog/2009/04/22/funcshell-a-shell-interface-to-func/</link>
      <pubDate>Wed, 22 Apr 2009 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2009/04/22/funcshell-a-shell-interface-to-func</guid>
      <description>&lt;h3&gt;Features&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;advanced client selection (you can use + and - to add/remove hosts/groups)&lt;/li&gt;
&lt;li&gt;tab completion&lt;/li&gt;
&lt;li&gt;persistent history&lt;/li&gt;
&lt;li&gt;a command sub-shell&lt;/li&gt;
&lt;li&gt;quick help (just hit the &amp;quot;?&amp;quot; key)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;funcshell&lt;/strong&gt; took a similar approach to features as Func; it allows developers to easily extend and customize its functionality using a plugin system. It also assumes the most useful commands will be the ones you write yourself. That being said, funcshell currently comes with both the command and service module.&lt;/p&gt;

&lt;p&gt;Here are some things you can do with funcshell.&lt;/p&gt;

&lt;p&gt;Get a list of all clients (not very useful if you have hundreds):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;funcshell&amp;gt; set clients *
funcshell&amp;gt; get clients
webapp001.example.net
webapp002.example.net
webapp003.example.net
webstatic001.example.net
webstatic002.example.net
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Assuming &lt;code&gt;webapp00[1-3].example.net&lt;/code&gt; are in the &lt;code&gt;app&lt;/code&gt; and &lt;code&gt;bpstatic00[1-2].example.net1&lt;/code&gt; are in the &lt;code&gt;static&lt;/code&gt; groups; remove some clients and restart a service:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;funcshell&amp;gt; set clients - @static;webapp001*
funcshell&amp;gt; get clients
webapp002.example.net
webapp003.example.net
funcshell&amp;gt; service httpd restart
==&amp;gt; webapp003.example.net &amp;lt;==
True
==&amp;gt; webapp002.example.net &amp;lt;==
True
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Run a command and get the results:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;funcshell&amp;gt; set clients - webapp003*
funcshell&amp;gt; set clients + webstatic002*
funcshell&amp;gt; command run grep MemTotal /proc/meminfo | awk &amp;#39;{ print $2/1024 }&amp;#39;
==&amp;gt; webstatic002.example.net :: 0 &amp;lt;==
4099.44
==&amp;gt; webapp002.example.net :: 0 &amp;lt;==
8198.88
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Get help:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;funcshell&amp;gt; command &amp;lt;TAB&amp;gt;&amp;lt;TAB&amp;gt;
exists   run      shell
funcshell&amp;gt; command ?
  exists Check if a command exists
  run    Run a command
  shell  Run a command shell
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Run a couple of commands in a row:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;funcshell&amp;gt; set c&amp;lt;TAB&amp;gt; @static
funcshell&amp;gt; command shell
&amp;gt; du -sh /tmp
==&amp;gt; webstatic002.example.net :: 0 &amp;lt;==
7.2M    /tmp
==&amp;gt; webstatic001.example.net :: 0 &amp;lt;==
3.4M    /tmp
&amp;gt; cp -r /tmp /tmp
==&amp;gt; webstatic002.example.net :: 1 &amp;lt;==
cp: cannot copy a directory, &amp;#39;/tmp&amp;#39;, into itself, &amp;#39;/tmp/tmp&amp;#39;
==&amp;gt; webstatic001.example.net :: 1 &amp;lt;==
cp: cannot copy a directory, &amp;#39;/tmp&amp;#39;, into itself, &amp;#39;/tmp/tmp&amp;#39;
&amp;gt; asdf
==&amp;gt; webstatic002.example.net :: 127 &amp;lt;==
/bin/sh: asdf: command not found
==&amp;gt; webstatic001.example.net :: 127 &amp;lt;==
/bin/sh: asdf: command not found
&amp;gt; &amp;lt;CTRL-D&amp;gt;
funcshell&amp;gt; exit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://github.com/silas/funcshell&quot; title=&quot;funcshell&quot;&gt;funcshell&lt;/a&gt; is a shell interface to &lt;a href=&quot;https://fedorahosted.org/func/&quot; title=&quot;func&quot;&gt;Func&lt;/a&gt; which provides some useful features for managing a large number of machines.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Getting Started with AMQP, Qpid, Python &amp; Fedora</title>
      <link>http://silas.sewell.org/blog/2009/03/29/getting-started-with-amqp-qpid-python-fedora/</link>
      <pubDate>Sun, 29 Mar 2009 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2009/03/29/getting-started-with-amqp-qpid-python-fedora</guid>
      <description>&lt;p&gt;The &lt;a href=&quot;http://en.wikipedia.org/wiki/AMQP&quot; title=&quot;Advanced Message Queuing Protocol&quot;&gt;Advanced Message Queuing Protocol&lt;/a&gt; (AMQP) is the first open
standard for Enterprise Messaging and has been adopted by Cisco,
&lt;a href=&quot;http://www.microsoft.com/presspass/press/2008/oct08/10-24AMQPPR.mspx&quot; title=&quot;Microsoft&quot;&gt;Microsoft&lt;/a&gt;, Novel, &lt;a href=&quot;http://www.redhat.com/solutions/specifications/amqp/&quot; title=&quot;Red Hat&quot;&gt;Red Hat&lt;/a&gt; and &lt;a href=&quot;http://jira.amqp.org/confluence/display/AMQP/AMQP+Working+Group&quot; title=&quot;others&quot;&gt;others&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One implementation of AMQP currently packaged by &lt;a href=&quot;http://www.redhat.com/mrg/messaging/&quot; title=&quot;Red Hat&quot;&gt;Red Hat&lt;/a&gt; and Fedora is
Qpid. &lt;a href=&quot;http://qpid.apache.org/&quot; title=&quot;Qpid&quot;&gt;Qpid&lt;/a&gt; is a collection of brokers (C++, Java) and clients (C++,
Java, Python, Ruby) which &lt;a href=&quot;http://qpid.apache.org/amqp-compatibility.html&quot;&gt;aims to be 100% AMQP Compliant&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Below is a step-by-step tutorial on getting started with Qpid and the Python
client in Fedora.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Install the Qpid broker and Python client&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;yum install qpidd python-qpid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start the broker&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;service qpidd start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a message producer (&lt;code&gt;producer.py&lt;/code&gt;)&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;from qpid.connection import Connection
from qpid.datatypes import Message, uuid4
from qpid.util import connect

# Create connection and session
socket = connect(&amp;#39;localhost&amp;#39;, 5672)
connection = Connection(sock=socket, username=&amp;#39;guest&amp;#39;, password=&amp;#39;guest&amp;#39;)
connection.start()
session = connection.session(str(uuid4()))

# Setup queue
session.queue_declare(queue=&amp;#39;message_queue&amp;#39;)
session.exchange_bind(exchange=&amp;#39;amq.direct&amp;#39;, queue=&amp;#39;message_queue&amp;#39;, binding_key=&amp;#39;routing_key&amp;#39;)

# Setup routing properties
properties = session.delivery_properties(routing_key=&amp;#39;routing_key&amp;#39;)

# Send messages
session.message_transfer(destination=&amp;#39;amq.direct&amp;#39;, message=Message(properties, &amp;#39;Message one&amp;#39;))
session.message_transfer(destination=&amp;#39;amq.direct&amp;#39;, message=Message(properties, &amp;#39;Message two&amp;#39;))
session.message_transfer(destination=&amp;#39;amq.direct&amp;#39;, message=Message(properties, &amp;#39;Done&amp;#39;))

# Close session
session.close(timeout=10)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a message consumer (&lt;code&gt;consumer.py&lt;/code&gt;)&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;from qpid.connection import Connection
from qpid.datatypes import RangedSet, uuid4
from qpid.util import connect

# Create connection and session
socket = connect(&amp;#39;localhost&amp;#39;, 5672)
connection = Connection(sock=socket, username=&amp;#39;guest&amp;#39;, password=&amp;#39;guest&amp;#39;)
connection.start()
session = connection.session(str(uuid4()))

# Define local queue
local_queue_name = &amp;#39;my_local_queue&amp;#39;

# Create local queue
queue = session.incoming(local_queue_name)

# Route messages from message_queue to my_local_queue
session.message_subscribe(queue=&amp;#39;message_queue&amp;#39;, destination=local_queue_name)
queue.start()

content = &amp;#39;&amp;#39;

while content != &amp;#39;Done&amp;#39;:
    # Get message from the local queue
    message = queue.get(timeout=10)
    # Get body of the message
    content = message.body
    # Accept message (removes it from the queue)
    session.message_accept(RangedSet(message.id))
    # Print message content
    print content

# Close session
session.close(timeout=10)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;First run the producer and then the consumer&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;Message one
Message two
Done
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Source: &lt;a href=&quot;https://svn.apache.org/repos/asf/qpid/trunk/qpid/python/examples/direct/&quot; title=&quot;Qpid direct example&quot;&gt;Qpid direct example&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>String Slicing in Bash (like Python)</title>
      <link>http://silas.sewell.org/blog/2009/03/12/string-slicing-in-bash-like-python/</link>
      <pubDate>Thu, 12 Mar 2009 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2009/03/12/string-slicing-in-bash-like-python</guid>
      <description>&lt;p&gt;A simple function to slice strings in Bash similar to Python&amp;#39;s string slicing functionality.&lt;/p&gt;

&lt;h3&gt;Examples&lt;/h3&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[silas@pluto ~]$ string_slice &amp;quot;12345&amp;quot; 0 1
1
[silas@pluto ~]$ string_slice &amp;quot;12345&amp;quot; 0 3
123
[silas@pluto ~]$ string_slice &amp;quot;12345&amp;quot; 2 3
3
[silas@pluto ~]$ string_slice &amp;quot;12345&amp;quot; 2 -2
3
[silas@pluto ~]$ string_slice &amp;quot;12345&amp;quot; -3
345
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Implementation&lt;/h3&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;function string_slice {
    STRING=&amp;quot;$1&amp;quot;
    declare -i LENGTH=&amp;quot;${#STRING}&amp;quot;
    declare -i START=&amp;quot;$2&amp;quot;
    declare -i END=&amp;quot;$3&amp;quot;
    if [ $START -lt 0 ]; then
        START=$[ $LENGTH + $START ]
    fi
    if [ $END -le 0 ]; then
        END=$[ $LENGTH + $END ]
    fi
    START=$[ $START + 1 ]
    (printf &amp;quot;%s\n&amp;quot; &amp;quot;$STRING&amp;quot; | cut -c $START-$END) 2&amp;gt; /dev/null
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Profile Management with Git and GitHub</title>
      <link>http://silas.sewell.org/blog/2009/03/08/profile-management-with-git-and-github/</link>
      <pubDate>Sun, 08 Mar 2009 00:00:00 PST</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2009/03/08/profile-management-with-git-and-github</guid>
      <description>&lt;p&gt;The following describes a simple way to manage you profile configuration files using GitHub.&lt;/p&gt;

&lt;h3&gt;Features&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Centralized configuration management&lt;/li&gt;
&lt;li&gt;Files live in their native locations (no symbolic linking)&lt;/li&gt;
&lt;li&gt;Home directory is not a Git repository&lt;/li&gt;
&lt;li&gt;All the power of git with a simple alias&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Setup Repository&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Log into &lt;a href=&quot;http://github.com/&quot; title=&quot;GitHub&quot;&gt;GitHub&lt;/a&gt; and create a repository named config&lt;/li&gt;
&lt;li&gt;Add your &lt;a href=&quot;http://github.com/guides/providing-your-ssh-key&quot; title=&quot;Public Keys to GithHub&quot;&gt;public keys to GitHub&lt;/a&gt; (if you haven&amp;#39;t done so already)&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open a terminal and switch to your home directory&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;cd ~
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a configuration directory&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;mkdir .config.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the following alias to your current session and your &lt;code&gt;.bash_profile&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;alias config=&amp;#39;git --git-dir=$HOME/.config.git/ --work-tree=$HOME&amp;#39;
echo &amp;quot;alias config=&amp;#39;git --git-dir=$HOME/.config.git/ --work-tree=$HOME&amp;#39;&amp;quot; &amp;gt;&amp;gt; .bash_profile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add your &lt;code&gt;.bash_profile&lt;/code&gt; to the configuration repository&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;config add .bash_profile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Commit the changes&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;config commit -m &amp;#39;Initial commit&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the origin to GitHub&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;config remote add origin git@github.com:GITHUB_USERNAME/config.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Push the changes&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;config push origin master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you get an error when running &lt;code&gt;config pull&lt;/code&gt; to the effect of &lt;code&gt;You asked me to pull without...&lt;/code&gt; run the follow:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;    echo -e &amp;#39;[branch &amp;quot;master&amp;quot;]\n  remote = origin\n  merge = refs/heads/master&amp;#39; &amp;gt;&amp;gt; ~/.config.git/config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Setup Configuration Management on a Different System&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Add your &lt;a href=&quot;http://github.com/guides/providing-your-ssh-key&quot; title=&quot;Public Keys to GithHub&quot;&gt;public keys to GitHub&lt;/a&gt; (if you haven&amp;#39;t done so already)&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Switch to your home directory&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;cd ~
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Backup your local configuration files, example:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;mv .bash_profile .bash_profile.bk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clone your configuration repository&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;git clone git@github.com:GITHUB_USERNAME/config.git config.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move the git metadata to &lt;code&gt;~/.config.git&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;mv config.git/.git .config.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable dotglob&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;shopt -s dotglob
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move your configuration files to your home directory&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;mv -i config.git/* .
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete the &lt;code&gt;config.git&lt;/code&gt; directory&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;rmdir config.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Logout and log back in&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;Basic Usage&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;config pull&lt;/code&gt; - get latest configuration changes&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config add FILENAME&lt;/code&gt; - add a configuration file&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config commit -a&lt;/code&gt; - save all configuration changes&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config push&lt;/code&gt; - push configuration changes to GitHub&lt;/li&gt;
&lt;li&gt;and any other &lt;code&gt;config GIT_OPTION&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see my configuration repository at &lt;a href=&quot;http://github.com/silas/config&quot; title=&quot;config&quot;&gt;http://github.com/silas/config&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Source: &lt;a href=&quot;http://robescriva.com/2009/01/manage-your-home-with-git/&quot; title=&quot;source&quot;&gt;Manage your $HOME with git&lt;/a&gt; by Robert Escriva&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Upgrade the Android Developer Phone (ADP) to RC33 Manually</title>
      <link>http://silas.sewell.org/blog/2009/02/17/upgrade-android-developer-phone-adp-to-rc33-manually/</link>
      <pubDate>Tue, 17 Feb 2009 00:00:00 PST</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2009/02/17/upgrade-android-developer-phone-adp-to-rc33-manually</guid>
      <description>&lt;p&gt;Please note that you will lose all data on your phone when performing these steps.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mount the ADP MicroSD card&lt;/li&gt;
&lt;li&gt;Download &lt;a href=&quot;https://android.clients.google.com/updates/hboot-0.95.0000.zip&quot; title=&quot;hboot&quot;&gt;hboot-0.95.0000.zip&lt;/a&gt; to the mount and rename it to &lt;code&gt;update.zip&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Unmount the card and shutdown the phone (unplug the USB cable if connected)&lt;/li&gt;
&lt;li&gt;Hold &lt;code&gt;Home+Power&lt;/code&gt; to boot&lt;/li&gt;
&lt;li&gt;When prompted press &lt;code&gt;Alt+S&lt;/code&gt; and wait for the update to finish&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;Home+Back&lt;/code&gt; to reboot and wait for second update to finish and boot into the Android recovery system&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;Home+Back&lt;/code&gt; to reboot again&lt;/li&gt;
&lt;li&gt;Mount the MicroSD card&lt;/li&gt;
&lt;li&gt;Delete &lt;code&gt;update.zip&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Download &lt;a href=&quot;https://android.clients.google.com/updates/signed-holiday_devphone-ota-130444-debug.55489994.zip&quot;&gt;signed-holiday_devphone-ota-130444-debug.55489994.zip&lt;/a&gt; to the mount and rename it to &lt;code&gt;update.zip&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Unmount the card and shutdown the phone&lt;/li&gt;
&lt;li&gt;Hold &lt;code&gt;Home+Power&lt;/code&gt; to boot&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;Alt+S&lt;/code&gt; to update and wait for update to finish&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;Home+Back&lt;/code&gt; to reboot and wait for the second update to finish and boot into the Android system recovery utility&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;Alt+W&lt;/code&gt; to wipe all data&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;Home+Back&lt;/code&gt; to reboot and wait for the reboot to finish (this could take a couple of minutes)&lt;/li&gt;
&lt;li&gt;Re-setup the ADP (hint: press menu to setup custom APN settings)&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Introducing the FuncShell</title>
      <link>http://silas.sewell.org/blog/2009/01/30/introducing-the-func-shell/</link>
      <pubDate>Fri, 30 Jan 2009 00:00:00 PST</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2009/01/30/introducing-the-func-shell</guid>
      <description>&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: I am currently refactoring FuncShell; please use the following
code: &lt;a href=&quot;http://github.com/silas/funcshell/raw/f630b9dd552287f5fe4b3f46ca09442499c68f0f/src/shell.py&quot; title=&quot;shell.py&quot;&gt;shell.py&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I created &lt;a href=&quot;http://github.com/silas/funcshell&quot; title=&quot;funcshell&quot;&gt;funcshell&lt;/a&gt; for running &lt;a href=&quot;https://fedorahosted.org/func/&quot; title=&quot;func&quot;&gt;Func&lt;/a&gt; modules in a more
intuitive manner.&lt;/p&gt;

&lt;p&gt;The current implementation only supports the command module, but more will be
released shortly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code:&lt;/strong&gt; &lt;a href=&quot;http://github.com/silas/funcshell&quot; title=&quot;funcshell&quot;&gt;http://github.com/silas/funcshell&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Example Usage&lt;/h3&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[root@pluto ~]# python shell.py
fs&amp;gt; use web*.example.org
fs&amp;gt; get hosts
web01.example.org
web02.example.org
fs&amp;gt; !du -sh /tmp
================================================================================
== web02.example.org                                                          ==
================================================================================

236K    /tmp

================================================================================
== web01.example.org                                                          ==
================================================================================

217M    /tmp

fs&amp;gt; !cat /proc/meminfo | grep MemTotal | awk &amp;#39;{ print $2 }&amp;#39;
================================================================================
== web02.example.org                                                          ==
================================================================================

1027116

================================================================================
== web01.example.org                                                          ==
================================================================================

1027116

fs&amp;gt; exit
[root@pluto ~]#
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Android Dev Phone 1 - AT&amp;T</title>
      <link>http://silas.sewell.org/blog/2008/12/17/android-dev-phone-1-att/</link>
      <pubDate>Wed, 17 Dec 2008 00:00:00 PST</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2008/12/17/android-dev-phone-1-att</guid>
      <description>&lt;p&gt;I received my &lt;a href=&quot;/blog/2008/12/06/adroid-dev-phone-1/&quot; title=&quot;Android Dev Phone 1&quot;&gt;Android Dev Phone 1&lt;/a&gt; today and wanted to report that with
the following &lt;a href=&quot;http://en.wikipedia.org/wiki/Access_Point_Name&quot; title=&quot;APN&quot;&gt;APN&lt;/a&gt; settings it works great (setup instructions come with
the phone).&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;Name: AT&amp;amp;T
APN: wap.cingular 
Proxy: &amp;lt;Not set&amp;gt;
Port: &amp;lt;Not set&amp;gt;
Username: wap.cingulargprs.com 
Password: CINGULAR1 
Server: &amp;lt;Not set&amp;gt;
MMSC: mmsc.cingular.com 
MMS proxy: &amp;lt;Not set&amp;gt;
MMS port: 80 
MCC: 310
MNC: 410
APN type: &amp;lt;Not set&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Source &lt;a href=&quot;http://groups.google.com/group/android-developers/msg/e4a9172898b7d7cc&quot; title=&quot;Jackson Miller&quot;&gt;Jackson Miller&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Adroid Dev Phone 1</title>
      <link>http://silas.sewell.org/blog/2008/12/06/adroid-dev-phone-1/</link>
      <pubDate>Sat, 06 Dec 2008 00:00:00 PST</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2008/12/06/adroid-dev-phone-1</guid>
      <description>&lt;p&gt;I just ordered the Adroid Dev Phone 1, an unlocked Android device available
through the &lt;a href=&quot;http://market.android.com/publish/Home&quot; title=&quot;Developer Console&quot;&gt;Developer Console&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/adroid-dev-phone-1-dev1.jpg&quot; alt=&quot;Front - Open&quot;&gt;
&lt;img src=&quot;/files/adroid-dev-phone-1-dev2.jpg&quot; alt=&quot;Front - Closed&quot;&gt;
&lt;img src=&quot;/files/adroid-dev-phone-1-dev3.jpg&quot; alt=&quot;Back&quot;&gt;
&lt;img src=&quot;/files/adroid-dev-phone-1-dev4.jpg&quot; alt=&quot;Side - Left&quot;&gt;
&lt;img src=&quot;/files/adroid-dev-phone-1-dev5.jpg&quot; alt=&quot;Side - Right&quot;&gt;
&lt;img src=&quot;/files/adroid-dev-phone-1-dev6.jpg&quot; alt=&quot;Profile - Open&quot;&gt;
&lt;img src=&quot;/files/adroid-dev-phone-1-dev7.jpg&quot; alt=&quot;Profile - Closed&quot;&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Price:&lt;/strong&gt; $399.00 USD&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run and debug your Android applications directly on a device. Modify and rebuild the Android operating system, and flash it onto a phone. The Android Dev Phone 1 is carrier independent, and available for purchase by any developer registered with Android Market.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Development Platform Features&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SIM unlocked - Put any SIM in the device&lt;/li&gt;
&lt;li&gt;Hardware unlocked - Rebuild the Android operating system, and load it onto the device&lt;/li&gt;
&lt;li&gt;Test out your apps on real hardware before publishing them to the world&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Hardware Features&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Touch screen&lt;/li&gt;
&lt;li&gt;Trackball&lt;/li&gt;
&lt;li&gt;3.2 Megapixel camera with auto focus&lt;/li&gt;
&lt;li&gt;Wi-Fi&lt;/li&gt;
&lt;li&gt;Bluetooth v2.0

&lt;ul&gt;
&lt;li&gt;Handsfree profile v1.5&lt;/li&gt;
&lt;li&gt;Headset profile v1.0&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;3G WCDMA (1700/2100 MHz)&lt;/li&gt;
&lt;li&gt;Quad-band GSM (850/900/1800/1900 MHz)&lt;/li&gt;
&lt;li&gt;QWERTY slider keyboard&lt;/li&gt;
&lt;li&gt;Includes 1GB MicroSD card (Can be replaced with up to 16GB card)&lt;/li&gt;
&lt;li&gt;Included in the box

&lt;ul&gt;
&lt;li&gt;HTC Android Dev Phone 1&lt;/li&gt;
&lt;li&gt;USB Cable&lt;/li&gt;
&lt;li&gt;AC Adapter (with US plug)&lt;/li&gt;
&lt;li&gt;Stereo Hands-Free Headset&lt;/li&gt;
&lt;li&gt;Battery&lt;/li&gt;
&lt;li&gt;Getting Starting Guide&lt;/li&gt;
&lt;li&gt;1G Micro SD Card (inserted into Device)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Software Features&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real web browsing&lt;/li&gt;
&lt;li&gt;Customizable home screen&lt;/li&gt;
&lt;li&gt;One-touch Google Search&lt;/li&gt;
&lt;li&gt;Android Market&lt;/li&gt;
&lt;li&gt;Full-featured Google applications:

&lt;ul&gt;
&lt;li&gt;Google Maps&lt;/li&gt;
&lt;li&gt;Gmail&lt;/li&gt;
&lt;li&gt;YouTube&lt;/li&gt;
&lt;li&gt;Google Calendar&lt;/li&gt;
&lt;li&gt;Google Talk&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;SMS and MMS&lt;/li&gt;
&lt;li&gt;Music Player&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>IPython + Python: Single Bash Command</title>
      <link>http://silas.sewell.org/blog/2008/12/01/ipython-python-single-bash-command/</link>
      <pubDate>Mon, 01 Dec 2008 00:00:00 PST</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2008/12/01/ipython-python-single-bash-command</guid>
      <description>&lt;p&gt;The following is a simple Bash function you can paste into your bashrc file to
start Python/IPython depending on the context.&lt;/p&gt;

&lt;h3&gt;~/.bashrc&lt;/h3&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;function python {
    IPYTHON=&amp;quot;/usr/bin/ipython&amp;quot;
    PYTHON=&amp;quot;/usr/bin/python&amp;quot;

    if [[ -n $1 ]]; then
        $PYTHON $@
    elif [[ -e $IPYTHON ]]; then
        $IPYTHON
    else
        $PYTHON
    fi
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Push: Func Module to Run Arbitrary Python Code</title>
      <link>http://silas.sewell.org/blog/2008/11/18/push-func-module-to-run-arbitrary-python-code/</link>
      <pubDate>Tue, 18 Nov 2008 00:00:00 PST</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2008/11/18/push-func-module-to-run-arbitrary-python-code</guid>
      <description>&lt;p&gt;&lt;a href=&quot;https://fedorahosted.org/func/&quot; title=&quot;Func&quot;&gt;Func&lt;/a&gt; is a nifty, although not yet polished, Python-based service for
running tasks on many hosts at once. It lets you do things like restart
&lt;a href=&quot;https://fedorahosted.org/func/wiki/ServiceModule&quot; title=&quot;Service Module&quot;&gt;Apache instances&lt;/a&gt;, &lt;a href=&quot;https://fedorahosted.org/func/wiki/YumModule&quot; title=&quot;Yum Module&quot;&gt;run yum updates&lt;/a&gt; or
&lt;a href=&quot;https://fedorahosted.org/func/wiki/VirtModule&quot; title=&quot;Virt Module&quot;&gt;provision virtual machines&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can accomplish theses tasks via the command line interface&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;func web-*.example.net call service restart httpd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;or through the Python API&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;import func.overlord.client as fc

client = fc.Client(&amp;#39;web-*.example.net&amp;#39;)

print client.service.restart(&amp;#39;httpd&amp;#39;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;One of the annoying issues I&amp;#39;m dealing with right now is the distribution of
Func modules, which for various reasons isn&amp;#39;t as simple as packaging the
modules and pushing them to all the hosts (it is, just not in my network).&lt;/p&gt;

&lt;p&gt;My solution is &lt;a href=&quot;/file/push.py&quot;&gt;Push&lt;/a&gt;, a Func module which lets you instantly run Python
code on any or all hosts in your network.&lt;/p&gt;

&lt;p&gt;Example usage:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;import func.overlord.client as fc

client = fc.Client(&amp;#39;web-*.example.net&amp;#39;)

source = &amp;quot;&amp;quot;&amp;quot;
def main():
    return &amp;#39;Hello World&amp;#39;
&amp;quot;&amp;quot;&amp;quot;

print client.push.code(source)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I realize this isn&amp;#39;t the most elegant solution, but its very useful and
extremely simple.&lt;/p&gt;

&lt;p&gt;I also realize that I could use the copyfile module to push modules via Func,
but I haven&amp;#39;t found a way to restart funcd via Func (required to initialize
modules), so until that happens I need a solution which doesn&amp;#39;t require
restarting Func.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/file/push.py&quot;&gt;Get Push Module&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Adobe Flash 10 64-bit SPEC File for Fedora 9</title>
      <link>http://silas.sewell.org/blog/2008/11/18/adobe-flash-10-64-bit-spec-file-for-fedora-9/</link>
      <pubDate>Tue, 18 Nov 2008 00:00:00 PST</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2008/11/18/adobe-flash-10-64-bit-spec-file-for-fedora-9</guid>
      <description>&lt;p&gt;I hacked up a quick SPEC file for the alpha release of
&lt;a href=&quot;http://labs.adobe.com/technologies/flashplayer10/releasenotes_64bit.html&quot;&gt;Adobe Flash 10 64-bit&lt;/a&gt; for Linux.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;Name:           adobe-flash
Version:        10.0.d20.7
Release:        1%{?dist}
Summary:        Adobe Flash player.

Group:          Application/Internet
License:        Proprietary
URL:            http://labs.adobe.com/technologies/flashplayer10/
Source0:        http://download.macromedia.com/pub/labs/flashplayer10/libflashplayer-10.0.d20.7.linux-x86_64.so.tar.gz
BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)

BuildArch:      x86_64
Requires:       firefox &amp;gt;= 3
Requires:       mozilla-filesystem

%description
The Adobe Flash player.

%prep
%setup -T -c -a 0

%install
install -D -m 644 libflashplayer.so $RPM_BUILD_ROOT%{_usr}/lib64/mozilla/plugins/libflashplayer.so

%clean
rm -rf $RPM_BUILD_ROOT

%files
%defattr(-,root,root,-)
%{_usr}/lib64/mozilla/plugins/libflashplayer.so

%changelog
* Tue Nov 18 2008 Silas Sewell &amp;lt;silas@sewell.ch&amp;gt; - 10.0.d20.7
- Created package.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>C GMP Hello World on Leopard (OS X 10.5)</title>
      <link>http://silas.sewell.org/blog/2008/10/19/c-gmp-hello-world-on-leopard-os-x-105/</link>
      <pubDate>Sun, 19 Oct 2008 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2008/10/19/c-gmp-hello-world-on-leopard-os-x-105</guid>
      <description>&lt;p&gt;A simple &lt;a href=&quot;http://gmplib.org/&quot; title=&quot;GMP&quot;&gt;GMP&lt;/a&gt; Hello World example in C.&lt;/p&gt;

&lt;h3&gt;Makefile&lt;/h3&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;all:
    gcc -o gmp_hello_world gmp_hello_world.c -lgmp -m64

clean:
    rm gmp_hello_world
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;gmp&lt;em&gt;hello&lt;/em&gt;world.c&lt;/h3&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;/*
 * GMP Hello World on OS X 10.5
*/
#include &amp;lt;gmp.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;

int main() {
  mpz_t add_total1, add_total2, sub_total1, sub_total2, mul_total1, mul_total2;
  mpz_t num1, num2;

  // Initialize variables
  mpz_init_set_str(num1, &amp;quot;345192567923875922375736284875732&amp;quot;, 10);
  mpz_init_set_str(num2, &amp;quot;937929298382994742939293857584837&amp;quot;, 10);
  mpz_init(add_total1);
  mpz_init(add_total2);
  mpz_init(sub_total1);
  mpz_init(sub_total2);
  mpz_init(mul_total1);
  mpz_init(mul_total2);

  // Do arithmetic
  mpz_add(add_total1, num1, num2);
  mpz_add_ui(add_total2, num1, 10);
  mpz_sub(sub_total1, num1, num2);
  mpz_sub_ui(sub_total2, num1, 10);
  mpz_mul(mul_total1, num1, num2);
  mpz_mul_ui(mul_total2, num1, 10);

  // Display results
  gmp_printf(&amp;quot;Add Total 1: %Zd\n&amp;quot;, add_total1);
  gmp_printf(&amp;quot;Add Total 2: %Zd\n&amp;quot;, add_total2);
  gmp_printf(&amp;quot;Subtract Total 1: %Zd\n&amp;quot;, sub_total1);
  gmp_printf(&amp;quot;Subtract Total 2: %Zd\n&amp;quot;, sub_total2);
  gmp_printf(&amp;quot;Multiply Total 1: %Zd\n&amp;quot;, mul_total1);
  gmp_printf(&amp;quot;Multiply Total 2: %Zd\n&amp;quot;, mul_total2);

  // Free space
  mpz_clear(num1);
  mpz_clear(num2);
  mpz_clear(add_total1);
  mpz_clear(add_total2);
  mpz_clear(sub_total1);
  mpz_clear(sub_total2);
  mpz_clear(mul_total1);
  mpz_clear(mul_total2);

  return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Persistent Queuing in Python</title>
      <link>http://silas.sewell.org/blog/2008/09/26/persistent-queuing-python/</link>
      <pubDate>Fri, 26 Sep 2008 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2008/09/26/persistent-queuing-python</guid>
      <description>&lt;p&gt;&lt;a href=&quot;http://code.google.com/p/peafowl/&quot;&gt;Peafowl&lt;/a&gt; is a Python port of Ruby's &lt;a href=&quot;http://rubyforge.org/projects/starling/&quot;&gt;Starling&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Common Usage Database (cudb)</title>
      <link>http://silas.sewell.org/blog/2008/09/24/common-usage-database-cudb/</link>
      <pubDate>Wed, 24 Sep 2008 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2008/09/24/common-usage-database-cudb</guid>
      <description>&lt;p&gt;A couple of months ago I was searching for an excuse to write an application on
Google App Engine. After mucking around with the &lt;a href=&quot;http://code.google.com/appengine/docs/datastore/&quot; title=&quot;Datastore&quot;&gt;Datastore&lt;/a&gt; and
&lt;a href=&quot;http://code.google.com/appengine/docs/users/&quot; title=&quot;User Authentication&quot;&gt;authentication&lt;/a&gt; API I decided to rewrite Most Common Usage on Google
App Engine.&lt;/p&gt;

&lt;p&gt;The end result was the &lt;a href=&quot;http://www.cudb.org/&quot;&gt;Common Usage Database&lt;/a&gt; and like Most Common
Usage the website is focused on the usage of CLI commands in Linux and
Unix-like operating systems.&lt;/p&gt;

&lt;p&gt;The website uses Google for authentication so you don&amp;#39;t need to signup if you
already have a Google account. I&amp;#39;ve also setup a &lt;a href=&quot;http://groups.google.com/group/cudb&quot;&gt;Google Group&lt;/a&gt; and the
&lt;code&gt;#cudb&lt;/code&gt; channel on Freenode.&lt;/p&gt;

&lt;p&gt;I look forward to creating a repository of useful commands and providing an
easy and open way for developers to use that repository.&lt;/p&gt;

&lt;p&gt;Link: &lt;a href=&quot;http://www.cudb.org/&quot;&gt;http://www.cudb.org/&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Python SDK for PhoneFactor</title>
      <link>http://silas.sewell.org/blog/2008/06/07/python-sdk-phonefactor/</link>
      <pubDate>Sat, 07 Jun 2008 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2008/06/07/python-sdk-phonefactor</guid>
      <description>&lt;p&gt;A first (and very alpha) attempt at creating a Python SDK for &lt;a href=&quot;http://www.phonefactor.com/&quot; title=&quot;PhoneFactor&quot;&gt;PhoneFactor&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Link: &lt;a href=&quot;http://github.com/silas/graveyard/tree/master/python-phonefactor/&quot; title=&quot;Python PhoneFactor&quot;&gt;http://github.com/silas/graveyard/tree/master/python-phonefactor/&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Universal Feed Parser to JSON</title>
      <link>http://silas.sewell.org/blog/2008/05/05/universal-feed-parser-json/</link>
      <pubDate>Mon, 05 May 2008 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2008/05/05/universal-feed-parser-json</guid>
      <description>&lt;p&gt;My attempt at wrangling a Universal Feed Parser object into JSON.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;import feedparser

def json_make_normal(obj):
    if type(obj) in [str, unicode, int, float, bool, dict, set, list, tuple]:
        return obj
    try: return dict(obj)
    except: pass
    try: return list(obj)
    except: pass
    return None

def json_handle(obj):
    obj = json_make_normal(obj)
    if type(obj) in [str, unicode]:
        obj = obj.replace(&amp;#39;\\&amp;#39;, &amp;#39;\\\\&amp;#39;)
        obj = obj.replace(&amp;#39;&amp;quot;&amp;#39;, &amp;#39;\\&amp;quot;&amp;#39;)
        obj = obj.replace(&amp;#39;\b&amp;#39;, &amp;#39;\\\b&amp;#39;)
        obj = obj.replace(&amp;#39;\f&amp;#39;, &amp;#39;\\\f&amp;#39;)
        obj = obj.replace(&amp;#39;\n&amp;#39;, &amp;#39;\\\n&amp;#39;)
        obj = obj.replace(&amp;#39;\r&amp;#39;, &amp;#39;\\\r&amp;#39;)
        obj = obj.replace(&amp;#39;\t&amp;#39;, &amp;#39;\\\t&amp;#39;)
        return &amp;#39;&amp;quot;%s&amp;quot;&amp;#39; % obj
    elif type(obj) in [int, float]:
        return obj
    elif type(obj) is bool:
        if obj: return &amp;#39;true&amp;#39;
        else: return &amp;#39;false&amp;#39;
    elif type(obj) is type(None):
        return &amp;#39;null&amp;#39;
    elif type(obj) is dict:
        temp = &amp;#39;&amp;#39;
        for key in obj.keys():
            temp += &amp;#39;%s:%s, &amp;#39; % (json_handle(key), json_handle(obj[key]))
        return &amp;#39;{\%s}&amp;#39; % temp[:-2]
    elif type(obj) in [set, list, tuple]:
        temp = &amp;#39;&amp;#39;
        for value in obj:
            temp += &amp;#39;%s, &amp;#39; % json_handle(value)
        return &amp;#39;[%s]&amp;#39; % temp[:-2]
    return &amp;#39;null&amp;#39;

data = feedparser.parse(&amp;#39;http://digg.com/rss/index.xml&amp;#39;)

print json_handle(data)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Link: &lt;a href=&quot;/files/feed_parser_to_json.py&quot; title=&quot;feed parser to json&quot;&gt;feed&lt;em&gt;parser&lt;/em&gt;to_json.py&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; According to &lt;a href=&quot;http://code.google.com/u/john.paulett/&quot; title=&quot;John Paulett&quot;&gt;John Paulett&lt;/a&gt; &lt;a href=&quot;http://code.google.com/p/jsonpickle/&quot; title=&quot;jsonpickle&quot;&gt;jsonpickle&lt;/a&gt; now supports Universal Feed Parser objects. Thanks for letting me know!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>OS X’s GNU Screen - Open in the Current Working Directory</title>
      <link>http://silas.sewell.org/blog/2008/04/05/os-xs-gnu-screen-open-current-working-directory/</link>
      <pubDate>Sat, 05 Apr 2008 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2008/04/05/os-xs-gnu-screen-open-current-working-directory</guid>
      <description>&lt;p&gt;How to get GNU Screen working properly in Mac OS X.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;~/.bashrc&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;alias screen=&amp;#39;export SCREENPWD=$(pwd); /usr/bin/screen&amp;#39;
export SHELL=&amp;#39;/bin/bash -rcfile ~/.bash_profile&amp;#39;;

case &amp;quot;$TERM&amp;quot; in 
    &amp;#39;screen&amp;#39;)
         cd $SCREENPWD
         ;; 
esac
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;~/.screenrc&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;startup_message off
shell -$SHELL
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Four Ways to Make Safari Better</title>
      <link>http://silas.sewell.org/blog/2008/04/04/four-ways-make-safari-better/</link>
      <pubDate>Fri, 04 Apr 2008 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2008/04/04/four-ways-make-safari-better</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://themacnewbie.blogspot.com/2008/03/how-to-force-safari-to-open-new-window.html&quot; title=&quot;Force New Window&quot;&gt;Force Safari to open a new window in a tab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.macosxhints.com/article.php?story=20030514035516436&quot; title=&quot;Change Default Search Engine&quot;&gt;Change Safari&amp;#39;s default search engine&lt;/a&gt; (use with &lt;a href=&quot;http://www.keyfu.com&quot; title=&quot;KeyFu&quot;&gt;Keyfu&lt;/a&gt; to get Firefox-like keywords)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;%22http://blog.neulio.com/2007/11/24/google-search-with-cmd-k-in-safari-on-leopard-10/&quot; title=&quot;Change Default Search&quot;&gt;Set a search shortcut in Safari&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://safariadblock.sourceforge.net/&quot; title=&quot;AdBlock&quot;&gt;Install AdBlock for Safari&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Post a Get</title>
      <link>http://silas.sewell.org/blog/2008/03/30/post-a-get/</link>
      <pubDate>Sun, 30 Mar 2008 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2008/03/30/post-a-get</guid>
      <description>&lt;p&gt;I&amp;#39;ve created a PHP script called &lt;a href=&quot;/files/post-a-get-index.php&quot; title=&quot;Post a Get&quot;&gt;Post a Get&lt;/a&gt; which can be copied to
any PHP capable server and used to created a POST request using GET syntax.&lt;/p&gt;

&lt;p&gt;Let&amp;#39;s say you use GoDaddy as your domain registrar and you would like to see if
a domain is available using Firefox keywords, but they don&amp;#39;t offer a GET
search.&lt;/p&gt;

&lt;p&gt;For a traditional keyword, you could construct a GET request like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;https://www.godaddy.com/gdshop/registrar/search.asp&amp;amp;checkAvail=1&amp;amp;fblur=1&amp;amp;tld=.com&amp;amp;domainToCheck=%s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But as of right now Firefox doesn&amp;#39;t offer a way to create POST keywords. What
Post a Fix does is allow you to construct a POST request using GET syntax and
pass it to the &lt;a href=&quot;/files/post-a-get-index.php&quot; title=&quot;Post a Get&quot;&gt;Post a Get code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So if you wanted to submit the above GET as a POST, you would construct the URL
and append the special __action parameter with target URL. So the final URL
would look something like:&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>OS X GNU Screen Proper Bash Prompt</title>
      <link>http://silas.sewell.org/blog/2008/02/23/os-xs-gnu-screen-proper-bash-prompt/</link>
      <pubDate>Sat, 23 Feb 2008 00:00:00 PST</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2008/02/23/os-xs-gnu-screen-proper-bash-prompt</guid>
      <description>&lt;p&gt;How to get GNU Screen working properly in Mac OS X.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;~/.bashrc&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;alias screen=&amp;#39;export SCREENPWD=$(pwd); /usr/bin/screen&amp;#39;
export SHELL=&amp;#39;/bin/bash -rcfile ~/.bash_profile&amp;#39;;

case &amp;quot;$TERM&amp;quot; in
    &amp;#39;screen&amp;#39;)
         cd $SCREENPWD
         ;;
esac
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;~/.screenrc&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;startup_message off
shell -$SHELL
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Gracefully restart Apache in Debian</title>
      <link>http://silas.sewell.org/blog/2008/01/27/gracefully-restart-apache2-debian/</link>
      <pubDate>Sun, 27 Jan 2008 00:00:00 PST</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2008/01/27/gracefully-restart-apache2-debian</guid>
      <description>&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;alias graceful=&amp;quot;sudo /usr/sbin/apache2 -t &amp;amp;&amp;amp; sudo /etc/init.d/apache2 stop &amp;amp;&amp;amp; sleep 2 &amp;amp;&amp;amp; sudo /etc/init.d/apache2 start&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Simple Shell Script to Manage SSH Tunnels</title>
      <link>http://silas.sewell.org/blog/2007/12/15/simple-shell-script-manage-ssh-tunnels/</link>
      <pubDate>Sat, 15 Dec 2007 00:00:00 PST</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2007/12/15/simple-shell-script-manage-ssh-tunnels</guid>
      <description>&lt;p&gt;Manage SSH Tunnel is a simple shell script to start and stop ssh tunnels from the terminal.&lt;/p&gt;

&lt;h3&gt;Setup&lt;/h3&gt;

&lt;p&gt;Note: the setup assumes bash as the default shell&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download &lt;a href=&quot;/files/tunnel.sh&quot;&gt;tunnel.sh&lt;/a&gt; and save it to ~/bin/&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add to &lt;code&gt;~/.bash_profile&lt;/code&gt; or &lt;code&gt;~/.bashrc&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;alias tunnel_home=&amp;#39;/bin/sh ~/bin/tunnel.sh example.net sam 22 8888&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Replace example.net with the hostname of the server, sam with the username
on the server, and 8888 with the local tunnel port&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Type &lt;code&gt;source ~/.bash_profile&lt;/code&gt; or &lt;code&gt;source ~/.bashrc&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;Usage&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;To open the tunnel&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;tunnel_home start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To close the tunnel&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;tunnel_home close
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>Better Terminal Font in OS X (GNOME)</title>
      <link>http://silas.sewell.org/blog/2007/11/18/better-terminal-font-os-x-gnome/</link>
      <pubDate>Sun, 18 Nov 2007 00:00:00 PST</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2007/11/18/better-terminal-font-os-x-gnome</guid>
      <description>&lt;p&gt;With the release of Leopard (OS X 10.5) came a sufficiently usable Terminal
(aka tabs). The only real complaint I had was the font.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/veramonoterminal.png&quot; alt=&quot;Terminal&quot;&gt;&lt;/p&gt;

&lt;p&gt;I ended up tracking down the default font used in the GNOME terminal and
installed it using the steps below:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download &lt;a href=&quot;http://ftp.gnome.org/pub/GNOME/sources/ttf-bitstream-vera/1.10/&quot;&gt;Bitstream Vera Mono 1.10&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Extract the archive&lt;/li&gt;
&lt;li&gt;Double click on &lt;code&gt;VeraMono.ttf&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Install Font&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;From &lt;code&gt;Terminal&lt;/code&gt; click &lt;code&gt;Terminal-&amp;gt;Preferences&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;To the right of &lt;code&gt;Font&lt;/code&gt; click &lt;code&gt;Change...&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;Bitstream Vera Sans&lt;/code&gt; for the &lt;code&gt;Family&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;12&lt;/code&gt; for the &lt;code&gt;Size&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Close the Fonts window&lt;/li&gt;
&lt;li&gt;Enable &lt;code&gt;Antialias text&lt;/code&gt; under Text&lt;/li&gt;
&lt;li&gt;Restart the Terminal&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>iGoogle - Hide Google Search</title>
      <link>http://silas.sewell.org/blog/2007/11/15/igoogle-hide-google-search/</link>
      <pubDate>Thu, 15 Nov 2007 00:00:00 PST</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2007/11/15/igoogle-hide-google-search</guid>
      <description>&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; This gadget will no longer work, Google has deprecated the inline
property which this gadget required.&lt;/p&gt;

&lt;p&gt;Hide Google Search (&lt;a href=&quot;/files/hide_google_search.xml&quot;&gt;source&lt;/a&gt;) is a gadget which hides the search area
of iGoogle.&lt;/p&gt;

&lt;p&gt;I&amp;#39;ve tested the gadget with the latest versions of Firefox, IE and Safari.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/hide-google-search-screenshot.png&quot; alt=&quot;Hide Google Search&quot;&gt;&lt;/p&gt;

&lt;p&gt;The above image is how the iGoogle page will load by default. You can toggle
the hidden area by clicking the line right below the navigation bar.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/hide-google-search-usage.png&quot; alt=&quot;Hide Google Search Expanded&quot;&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>opml2html Updates</title>
      <link>http://silas.sewell.org/blog/2007/08/05/opml-html-updates/</link>
      <pubDate>Sun, 05 Aug 2007 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2007/08/05/opml-html-updates</guid>
      <description>&lt;p&gt;I&amp;#39;ve made some tweaks to &lt;a href=&quot;http://github.com/silas/graveyard/tree/master/python-opml2html/&quot; title=&quot;opml2html&quot;&gt;opml2html&lt;/a&gt; to make it a little cleaner and
more useful.&lt;/p&gt;

&lt;p&gt;The main two additions are a class so opml2html can be called programmatically
and a command line argument so the input file isn&amp;#39;t static.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Open Source Games</title>
      <link>http://silas.sewell.org/blog/2007/08/04/open-source-games/</link>
      <pubDate>Sat, 04 Aug 2007 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2007/08/04/open-source-games</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://xmoto.tuxfamily.org/&quot;&gt;X-Moto&lt;/a&gt; - 2D motocross platform game&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>GWT Webmail Experiment</title>
      <link>http://silas.sewell.org/blog/2007/08/03/gwt-webmail-experiment/</link>
      <pubDate>Fri, 03 Aug 2007 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2007/08/03/gwt-webmail-experiment</guid>
      <description>&lt;p&gt;A Java/GWT webmail experiment.&lt;/p&gt;

&lt;p&gt;Link: &lt;a href=&quot;http://github.com/silas/graveyard/tree/master/java-ssmail/&quot;&gt;ssmail&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Setting up Ricochet in Linux</title>
      <link>http://silas.sewell.org/blog/2007/07/20/setting-up-ricochet-linux/</link>
      <pubDate>Fri, 20 Jul 2007 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2007/07/20/setting-up-ricochet-linux</guid>
      <description>&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; The follow instructions are meant for the Linux &lt;a href=&quot;http://en.wikipedia.org/wiki/Command_line_interpreter&quot;&gt;CLI&lt;/a&gt;, and
should be run with &lt;a href=&quot;http://en.wikipedia.org/wiki/Sudo&quot;&gt;sudo&lt;/a&gt; or as root.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Install wvdial&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;Debian/Ubuntu: apt-get install wvdial
Fedora/RHEL: yum install wvdial
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Edit &lt;code&gt;/etc/wvdial.conf&lt;/code&gt; and replace its content with:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;[Dialer Defaults]
Modem = /dev/ttyACM0
Baud = 460800
Init1 = ATZ
Init2 = ATQ0

[Dialer ricochet]
Username = *
Password = *
Phone = 3333
Inherits = Dialer Defaults
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Replace &lt;code&gt;/dev/ttyACM0&lt;/code&gt; with the device your modem connected to:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;$ dmesg | grep cdc_acm
cdc_acm 2-1:1.0: ttyACM1: USB ACM device
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Take the device name and prepend dev, so you get:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;Modem = /dev/ttyACM1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start wvdial&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;wvdial ricochet &amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>Convert Google Reader subscriptions (OPML) to HTML</title>
      <link>http://silas.sewell.org/blog/2007/07/16/google-reader-opml-html/</link>
      <pubDate>Mon, 16 Jul 2007 00:00:00 PDT</pubDate>
      <author>Silas Sewell (Silas Sewell)</author>
      <guid>http://silas.sewell.org/blog/2007/07/16/google-reader-opml-html</guid>
      <description>&lt;p&gt;I&amp;#39;ve created a simple Python script to convert Google Reader’s OPML to HTML.&lt;/p&gt;

&lt;p&gt;Link: &lt;a href=&quot;http://github.com/silas/graveyard/tree/master/python-opml2html/&quot;&gt;http://github.com/silas/graveyard/tree/master/python-opml2html/&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    

  </channel> 
</rss>
