<?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>Erics Tech Blog &#187; System Administration</title>
	<atom:link href="http://eric.lubow.org/category/system-administration/feed/" rel="self" type="application/rss+xml" />
	<link>http://eric.lubow.org</link>
	<description>Thoughts, musings, and other idealistic (sometimes useful) systems and development hoopla.</description>
	<lastBuildDate>Fri, 18 Nov 2011 14:56:45 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.4</generator>
		<item>
		<title>Distributed Flume Setup With an S3 Sink</title>
		<link>http://eric.lubow.org/2011/system-administration/distributed-flume-setup-with-an-s3-sink/</link>
		<comments>http://eric.lubow.org/2011/system-administration/distributed-flume-setup-with-an-s3-sink/#comments</comments>
		<pubDate>Fri, 04 Feb 2011 07:15:03 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[System Administration]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[cloudera]]></category>
		<category><![CDATA[flume]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[s3]]></category>

		<guid isPermaLink="false">http://eric.lubow.org/?p=820</guid>
		<description><![CDATA[I have recently spent a few days getting up to speed with Flume, Cloudera&#8216;s distributed log offering. If you haven&#8217;t seen this and deal with lots of logs, you are definitely missing out on a fantastic project. I&#8217;m not going to spend time talking about it because you can read more about it in the [...]]]></description>
			<content:encoded><![CDATA[<p>I have recently spent a few days getting up to speed with <a href="https://github.com/cloudera/flume">Flume</a>, <a href="http://www.cloudera.com/">Cloudera</a>&#8216;s distributed log offering.  If you haven&#8217;t seen this and deal with lots of logs, you are definitely missing out on a fantastic project.  I&#8217;m not going to spend time talking about it because you can read more about it in the <a href="http://archive.cloudera.com/cdh/3/flume/UserGuide.html">users guide</a> or in the <a href="http://www.quora.com/Flume">Quora Flume Topic</a> in ways that are better than I can describe it.  But I will tell you about is my experience setting up Flume in a distributed environment to sync logs to an Amazon S3 sink.</p>
<p>As CTO of <a href="http://www.simplereach.com">SimpleReach</a>, a company that does most of it&#8217;s work in the cloud, I&#8217;m constantly strategizing on how we can take advantage of the cloud for auto-scaling.  Depending on the time of day or how much content distribution we are dealing with, we will spawn new instances to accommodate the load.  We will still need the logs from those machines for later analysis (batch jobs like making use of Elastic Map Reduce).<br />
<span id="more-820"></span><br />
I am going to attempt to do this as step by step as possible but much of the terminology I use is described in the users guide and there is an expectation that you have at least skimmed it prior to starting this HOWTO.  I am using EMR (Elastic Map Reduce) on EC2 and not the provided Hadoop by Cloudera.  Additionally, the Cloudera version that I am working with is <strong>cdh3b3</strong>.</p>
<p><strong>Context</strong><br />
I have 3 kinds of servers all running CentOS in the <a href="http://www.amazon.com/">Amazon</a> cloud:</p>
<ol>
<li><strong>a1</strong>: This is the agent which is producing all the logs</li>
<li><strong>c1</strong>: This is the collector which is aggregating all the logs (from a1, a2, a3, etc)</li>
<li><strong>u1</strong>: This is the flume master node which is sending out all the commands</li>
</ol>
<p>There are actually <em>n</em> agents, but for this example, we&#8217;ll keep it simple.  Also, for a complete copy of the config files, please check out the full gist available <a href="https://gist.github.com/810104">here</a>.</p>
<p><strong>Initial Setup</strong><br />
On both a1 and c1, you&#8217;ll have to install flume-node (flume-node contains the files necessary to run the agent or the collector).</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># curl http://archive.cloudera.com/redhat/cdh/cloudera-cdh3.repo &gt; /etc/yum.repos.d/cloudera-cdh3.repo<br />
# yum update yum<br />
# yum install flume flume-node</div></div>
<p>On u1, you&#8217;ll need to install the flume-master RPM:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># curl http://archive.cloudera.com/redhat/cdh/cloudera-cdh3.repo &gt; /etc/yum.repos.d/cloudera-cdh3.repo<br />
# yum update yum<br />
# yum install flume flume-master</div></div>
<p>On each host, you need to copy the conf template file to the site specific config file.  That is to say:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">cp flume-site.xml.template flume-site.xml</div></div>
<p>First let&#8217;s jump onto the agent and set that up.  Tune the $master_IP and $collector_IP variables appropriately, but change your <em>/etc/flume/conf/flume-site.xml</em> to look like:</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:450px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>flume.master.servers<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>$master_IP<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>This is the address for the config servers status server (http)<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>flume.collector.event.host<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>$collector_IP<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>This is the host name of the default &quot;remote&quot; collector.<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>flume.collector.port<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>35853<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>This default tcp port that the collector listens to in order to receive events it is collecting.<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>flume.agent.logdir<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>/mnt/flume-${user.name}/agent<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> This is the directory that write-ahead logging data<br />
&nbsp; &nbsp; &nbsp; or disk-failover data is collected from applications gets<br />
&nbsp; &nbsp; &nbsp; written to. The agent watches this directory.<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>Now on to the collector.  Same file, different config.  Replace all the variables with you $master IP address (you should be using Amazon&#8217;s internal IPs otherwise you will be paying the regional charge).  The $account and $secret variables are both your Amazon EC2/S3 account key and secret Access key respectively.  The $bucket is the S3 bucket that will contain the log files.  Also worthy of pointing out is the <em>flume.collector.roll.millis</em> and <em>flume.collector.dfs.compress.gzip</em>.  The millis is how frequently the log file gets truncated and the next file begins to be written to.  It would be nice if this could be done by file size and not only by time, but it works for now. The other config option is <em>flume.collector.dfs.compress.gzip</em>.  This ensures that the logfiles are compressed prior to being dumped onto S3 (saves LOTS of space).</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:450px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>flume.master.servers<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>$master<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>This is the address for the config servers status server (http)<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
<br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>flume.collector.event.host<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>localhost<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>This is the host name of the default &quot;remote&quot; collector.<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>flume.collector.port<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>35853<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>This default tcp port that the collector listens to in order to receive events it is collecting.<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>fs.default.name<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>s3n://$account:$secret@$bucket<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>fs.s3n.impl<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.apache.hadoop.fs.s3native.NativeS3FileSystem<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>fs.s3.awsAccessKeyId<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>$account<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>fs.s3.awsSecretAccessKey<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>$secret<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>fs.s3n.awsAccessKeyId<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>$account<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>fs.s3n.awsSecretAccessKey<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>$secret<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>flume.agent.logdir<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>/mnt/flume-${user.name}/agent<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> This is the directory that write-ahead logging data<br />
&nbsp; &nbsp; &nbsp; or disk-failover data is collected from applications gets<br />
&nbsp; &nbsp; &nbsp; written to. The agent watches this directory.<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp;<br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>flume.collector.dfs.dir<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>file:///mnt/flume-${user.name}/collected<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>This is a dfs directory that is the the final resting<br />
&nbsp; &nbsp; place for logs to be stored in. &nbsp;This defaults to a local dir in<br />
&nbsp; &nbsp; /tmp but can be hadoop URI path that such as hdfs://namenode/path/<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> &nbsp;<br />
<br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>flume.collector.dfs.compress.gzip<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Writes compressed output in gzip format to dfs. value is<br />
&nbsp; &nbsp; &nbsp;boolean type, i.e. true/false<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>flume.collector.roll.millis<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>60000<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>The time (in milliseconds)<br />
&nbsp; &nbsp; between when hdfs files are closed and a new file is opened<br />
&nbsp; &nbsp; (rolled).<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> <br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>While we are still on the collector, in order to properly write to S3, you&#8217;ll need to make 4 file adjustments and all of them will go into the <strong>/usr/lib/flume/lib/</strong> directory.</p>
<ol>
<li>commons-codec-1.4.jar</li>
<li>jets3t-0.6.1.jar</li>
<li>commons-httpclient-3.0.1.jar</li>
<li>emr-hadoop-core-0.20.jar</li>
</ol>
<p>The one thing that should be noted here is that the <strong>emr-hadoop-core-0.20.jar</strong> file replaces the <strong>hadoop-core.jar</strong> symlink.  The emr-hadoop-core-0.20.jar file is the hadoop-core.jar file from an EC2 Hadoop cluster instance.  <strong>Note:</strong> This will break the ability to seamlessly upgrade via the RPM (which is how you installed it if you&#8217;ve been following my HOWTO).  Keep these files around just in case.  I have added a tarball of the files <a href="http://eric.lubow.org/wp-content/uploads/2011/02/flume-jar.tar.gz">here</a>, but they are all still available with a quick Google search.</p>
<p>And now on to the master.  There was actually no configuration that I did on the master file system to get things up and running. But if flume is writing to a /tmp directory on an ephemeral file system, then it should be fixed.</p>
<p><strong>Web Based Setup</strong></p>
<p>I chose to do the individual machine setup via the master web interface.  You can get to this pointing your web browser at http://u1:35871/ (replace u1 with public DNS IP of your flume master).  Ensure that the port is accessible from the outside through your security settings.  At this point, it was easiest for me to ensure all hosts running flume could talk to all ports on all other hosts running flume.  You can certainly lock this down to the individual ports for security once everything is up and running. </p>
<p>At this point, you should go to a1 and c1 run <strong>/etc/init.d/flume-node start</strong>.  If everything goes well, then the master (whose IP is specified in their configs) should be notified of their existence.  Now you can configure them from the web.  Click on the config link and then fill in the text lines as follows (use what is in bold):</p>
<ul>
<li>Agent Node: <strong>$agent_ec2_internal_ip</strong></li>
<li>Source: <strong>tailDir(&#8220;/mnt/logs/&#8221;,&#8221;.*.log&#8221;)</strong></li>
<li>Sink: <strong>agentBESink(&#8220;$collector_ec2_internal_ip&#8221;,35853)</strong></li>
</ul>
<p>Note: I chose to use <em>tailDir</em> since I will control rotating the logs on my own.  I am also using <em>agentBESink</em> because I am ok with losing log lines if the case arises.</p>
<p>Now click <strong>Submit Query</strong> and go back to the config page to setup the collector:</p>
<ul>
<li>Agent Node: <strong>$collector_ec2_internal_ip</strong></li>
<li>Source: <strong>collectorSource(35853)</strong></li>
<li>Sink: <strong>collectorSink(&#8220;s3n://$account:$secret@$bucket/logs/%Y/%m/%d/%H00&#8243;,&#8221;server&#8221;)</strong></li>
</ul>
<p>This is going to tell the collector that we are sinking to s3native with the $account key and the $secret key into the $bucket with an initial folder of &#8216;logs&#8217;.  It will then log to sub-folders with YYYY/MM/DD/HH00 (or 2011/02/03/1300/server-<timestamp>.log).  There will be 60 gziped files in each folder since the timing is setup to be 1 file per minute.  Now click <strong>Submit Query</strong> and go to the &#8216;master&#8217; page and you should see 2 commands listed as &#8220;SUCCEEDED&#8221; in the command history.  If they have not succeeded, ensure a few things have been done (there are probably more, but this is a handy start:</p>
<ol>
<li>Always use double quotes (&#8220;) since single quotes (&#8216;) aren&#8217;t interpreted correctly. UPDATE: Single quotes are interpreted correctly, they are just not accepted intentionally (Thanks jmhsieh)
	</li>
<li>In your regex, use something like &#8220;.*\\.log&#8221; since the &#8216;.&#8217; is part of the regex.</li>
<li>In your regex, ensure that your blackslashes are properly escaped: &#8220;foo\\bar&#8221; is the correct version of trying to match &#8220;foo\bar&#8221;.</li>
<li>Ensure any &#8216;/&#8217; are inserted as &#8216;%2F&#8217; in the Amazon account and secret codes.</li>
</ol>
<p>Additionally, there are also tables of <strong>Node Status</strong> and <strong>Node Configuration</strong>.  These should match up with what you think you configured.</p>
<p>At this point everything should work.  Admittedly I had a lot of trouble getting to this point.  But with the help of the Cloudera folks and the users on irc.freenode.net in #flume, I was able to get things going.  The logs sadly aren&#8217;t too helpful here in most cases (but look anyway cause they might provide you with more info than they provided for me).  If I missed anything in this post or there is something else I am unaware of, then let me know.</p>
<p><strong>References</strong></p>
<ul>
<li><a href="http://wiki.apache.org/hadoop/AmazonS3">http://wiki.apache.org/hadoop/AmazonS3</a></li>
<li><a href="http://archive.cloudera.com/cdh/3/flume/UserGuide.html">Flume Users Guide</a></li>
<li>irc.freenode.net #flume</li>
<li><a href="https://issues.cloudera.org/browse/FLUME-66">https://issues.cloudera.org/browse/FLUME-66</a></li>
<li>Config files <a href="https://gist.github.com/810104">gist</a></li>
</ul>
<p></timestamp></p>


<p>Related posts:<ol><li><a href='http://eric.lubow.org/2011/hadoop/pig-queries-parsing-json-on-amazons-elastic-map-reduce-using-s3-data/' rel='bookmark' title='Pig Queries Parsing JSON on Amazons Elastic Map Reduce Using S3 Data'>Pig Queries Parsing JSON on Amazons Elastic Map Reduce Using S3 Data</a></li>
<li><a href='http://eric.lubow.org/2007/perl/filefind/' rel='bookmark' title='File::Find'>File::Find</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://eric.lubow.org/2011/system-administration/distributed-flume-setup-with-an-s3-sink/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Sharing a Screen Session</title>
		<link>http://eric.lubow.org/2010/system-administration/sharing-a-screen-session/</link>
		<comments>http://eric.lubow.org/2010/system-administration/sharing-a-screen-session/#comments</comments>
		<pubDate>Fri, 23 Jul 2010 12:47:23 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[System Administration]]></category>
		<category><![CDATA[system]]></category>

		<guid isPermaLink="false">http://eric.lubow.org/?p=762</guid>
		<description><![CDATA[Anyone who has spent any time in a shell and has been cut off while working should know about screen. If not, then I recommend reading up on it (here or here). But I&#8217;m not here to tell you about screen as a general tool, I want to show you how to use it for [...]]]></description>
			<content:encoded><![CDATA[<p>Anyone who has spent any time in a shell and has been cut off while working should know about screen.  If not, then I recommend reading up on it (<a href="http://www.rackaid.com/resources/linux-screen-tutorial-and-how-to/">here</a> or <a href="http://www.linuxforums.org/articles/the-screen-program_55.html">here</a>).  But I&#8217;m not here to tell you about screen as a general tool, I want to show you how to use it for screen sharing.  I found a couple of forum posts and other scattered information, so here&#8217;s a little centralizing of information.<br />
<span id="more-762"></span><br />
First a definition, sharing a screen session means both users can at the very least view the same screen (console) at the same time.  And depending on the security settings, they can both type as well (which can be very annoying depending on who your sharing the screen session with).  I&#8217;m going to assume you know the basics so we&#8217;ll go on from there.</p>
<p>Let&#8217;s assume that I <strong>elubow</strong> want to share my console with <strong>jdoe</strong>.  After screen is installed, these next 2 steps are critical otherwise the sessions will not be accessible to other users regardless of which commands you issue inside of the screen session:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">chmod</span> +s <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">screen</span> &nbsp;<span style="color: #666666; font-style: italic;"># Make screen suid root</span><br />
$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #000000;">755</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>run<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">screen</span> <span style="color: #666666; font-style: italic;"># Make the screen dir more open</span></div></div>
<p>The easiest way to do this next part is to actually name your screen session.  So let&#8217;s call our session <strong>test</strong>.</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span><span style="color: #c20cb9; font-weight: bold;">screen</span> <span style="color: #660033;">-S</span> <span style="color: #7a0874; font-weight: bold;">test</span></div></div>
<p>This will create the session and put you in it.  Now we need to add the access control.  Note: You can automate the <em>multiuser</em> piece by adding it to you <strong>.screenrc</strong>.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CTRL-A<br />
:multiuser on<br />
<br />
CTRL-A<br />
:acladd jdoe</div></div>
<p>All <em>jdoe</em> has to do now is connect to the same machine and type the following command:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span><span style="color: #c20cb9; font-weight: bold;">screen</span> <span style="color: #660033;">-x</span> elubow<span style="color: #000000; font-weight: bold;">/</span><span style="color: #7a0874; font-weight: bold;">test</span> &nbsp; <span style="color: #666666; font-style: italic;"># $user/$session_name</span></div></div>
<p>There are other security combinations as the above gives <strong>jdoe</strong> full access.  Here are a few common ones:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">:aclchg user +rx &nbsp;# Give 'user' read-only access<br />
:aclchg user -x &quot;#,at,aclchg,acladd,acldel,quit&quot; &nbsp;# Don't allow 'user' any of the previous commands<br />
:aclchg user +rwx &nbsp;# Give 'user' read-write access (open permission on the session)</div></div>


<p>Related posts:<ol><li><a href='http://eric.lubow.org/2010/system-administration/cluster-ssh-with-csshx/' rel='bookmark' title='Cluster SSH with cSSHx'>Cluster SSH with cSSHx</a></li>
<li><a href='http://eric.lubow.org/2007/linux-security/10-tips-to-start-securing-your-linux-system/' rel='bookmark' title='10 Tips To Start Securing Your Linux System'>10 Tips To Start Securing Your Linux System</a></li>
<li><a href='http://eric.lubow.org/2007/linux-security/ssh-organization-tips/' rel='bookmark' title='SSH Organization Tips'>SSH Organization Tips</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://eric.lubow.org/2010/system-administration/sharing-a-screen-session/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Creating Configuration Files With Ruby Templates</title>
		<link>http://eric.lubow.org/2010/system-administration/creating-configuration-files-with-ruby-templates/</link>
		<comments>http://eric.lubow.org/2010/system-administration/creating-configuration-files-with-ruby-templates/#comments</comments>
		<pubDate>Wed, 30 Jun 2010 11:45:58 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[System Administration]]></category>
		<category><![CDATA[system]]></category>
		<category><![CDATA[tricks]]></category>

		<guid isPermaLink="false">http://eric.lubow.org/?p=749</guid>
		<description><![CDATA[I recently had a very repetitive configuration file that needed creating. There were approximately 50 config blocks of 10 lines each with only the host name changing with each block. So I decided to take a shortcut and do it in Ruby using ERB templates. This is so easy and literally save me hours worth [...]]]></description>
			<content:encoded><![CDATA[<p>I recently had a very repetitive configuration file that needed creating.  There were approximately 50 config blocks of 10 lines each with only the host name changing with each block.  So I decided to take a shortcut and do it in Ruby using ERB templates. This is so easy and literally save me hours worth of work.<br />
<span id="more-749"></span><br />
I started out by creating a template for the <a href="http://www.rsyslog.com/">rsyslog</a> block I wanted to replicate.  In the full version of the script, there is an additional section for the access.log file which you&#8217;ll see below.  If you know Rails, then this template style should look very familiar.</p>
<div class="codecolorer-container ruby default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">rsyslog_block = <span style="color:#006600; font-weight:bold;">%</span><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#008000; font-style:italic;">#</span><br />
<span style="color:#008000; font-style:italic;"># &lt; %= virtual_host %&gt;</span><br />
<span style="color:#008000; font-style:italic;">#</span><br />
<span style="color:#ff6633; font-weight:bold;">$InputFileName</span> <span style="color:#006600; font-weight:bold;">/</span>var<span style="color:#006600; font-weight:bold;">/</span>log<span style="color:#006600; font-weight:bold;">/</span>httpd<span style="color:#006600; font-weight:bold;">/&lt;</span> <span style="color:#006600; font-weight:bold;">%</span>= virtual_host <span style="color:#006600; font-weight:bold;">%&gt;-</span>error.<span style="color:#9900CC;">log</span><br />
<span style="color:#ff6633; font-weight:bold;">$InputFileTag</span> <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#006600; font-weight:bold;">%</span>= virtual_host <span style="color:#006600; font-weight:bold;">%&gt;</span>_error<br />
<span style="color:#ff6633; font-weight:bold;">$InputFileStateFile</span> stat<span style="color:#006600; font-weight:bold;">-&lt;</span> <span style="color:#006600; font-weight:bold;">%</span>= virtual_host <span style="color:#006600; font-weight:bold;">%&gt;-</span>error.<span style="color:#9900CC;">log</span><br />
<span style="color:#ff6633; font-weight:bold;">$InputFileSeverity</span> info<br />
<span style="color:#ff6633; font-weight:bold;">$InputFileFacility</span> local5<br />
<span style="color:#ff6633; font-weight:bold;">$InputRunFileMonitor</span><br />
<br />
<span style="color:#006600; font-weight:bold;">&#125;</span></div></div>
<p>The below block of code creates a configuration block (above) for each of virtual hosts in the array and then prints it to the screen.</p>
<div class="codecolorer-container ruby default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#006600; font-weight:bold;">%</span>w<span style="color:#006600; font-weight:bold;">&#123;</span><br />
&nbsp; &nbsp; vhost.<span style="color:#9900CC;">com</span><br />
&nbsp; &nbsp; bar.<span style="color:#9900CC;">myhost</span>.<span style="color:#9900CC;">com</span><br />
<span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">each</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>virtual_host<span style="color:#006600; font-weight:bold;">|</span> &nbsp;<span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#CC00FF; font-weight:bold;">ERB</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span> rsyslog_block <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">result</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC0066; font-weight:bold;">binding</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span></div></div>
<p>This is going to produce the following block which you can then pipe to a file:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">...Removed for brevity...<br />
#<br />
# bar.myhost.com<br />
#<br />
$InputFileName /var/log/httpd/bar.myhost.com-error.log<br />
$InputFileTag bar.myhost.com_error<br />
$InputFileStateFile stat-bar.myhost.com-error.log<br />
$InputFileSeverity info<br />
$InputFileFacility local5<br />
$InputRunFileMonitor</div></div>
<p>Here is the script in its entirety:<br />
<script src="http://gist.github.com/456080.js"></script></p>


<p>Related posts:<ol><li><a href='http://eric.lubow.org/2009/ruby/parsing-ini-files-with-ruby/' rel='bookmark' title='Parsing Ini Files With Ruby'>Parsing Ini Files With Ruby</a></li>
<li><a href='http://eric.lubow.org/2010/ruby/multiple-input-locations-from-bash-into-ruby/' rel='bookmark' title='Multiple Input Locations From Bash Into Ruby'>Multiple Input Locations From Bash Into Ruby</a></li>
<li><a href='http://eric.lubow.org/2010/ruby/interesting-object-methods-in-ruby/' rel='bookmark' title='Interesting Object Methods in Ruby'>Interesting Object Methods in Ruby</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://eric.lubow.org/2010/system-administration/creating-configuration-files-with-ruby-templates/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Nagios notify-by-campfire Plugin</title>
		<link>http://eric.lubow.org/2010/system-administration/nagios-notify-by-campfire-plugin/</link>
		<comments>http://eric.lubow.org/2010/system-administration/nagios-notify-by-campfire-plugin/#comments</comments>
		<pubDate>Thu, 06 May 2010 09:45:01 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[System Administration]]></category>
		<category><![CDATA[campfire]]></category>
		<category><![CDATA[nagios]]></category>
		<category><![CDATA[system]]></category>

		<guid isPermaLink="false">http://eric.lubow.org/?p=712</guid>
		<description><![CDATA[Since one of the core communication methods for my company amongst engineers is 37Signals Campfire and Nagios is one of our main monitoring tools for all of our applications and services, I thought it would be a good idea to combine the two. So with a few simple additions to the Nagios configuration and a [...]]]></description>
			<content:encoded><![CDATA[<p>Since one of the core communication methods for my company amongst engineers is <a href="http://37signals.com/">37Signals</a> <a href="http://campfirenow.com/">Campfire</a> and <a href="http://www.nagios.org/">Nagios</a> is one of our main monitoring tools for all of our applications and services, I thought it would be a good idea to combine the two.  So with a few simple additions to the Nagios configuration and a Ruby Campfire script, you can get this up and running.<br />
<span id="more-712"></span><br />
On the Campfire side, I will leave the exercise of adding a Campfire user up to you.  You may need to go through your Campfire administrator for that.</p>
<p>On the Nagios side, the first thing that needs to happen is that you need to add the following commands to your <strong>command.cfg</strong> file in your Nagios configuration.  Make sure that you specify the proper location of your <strong>notify-by-campfire.rb</strong> file.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># 'notify-host-by-campfire' command definition<br />
define command{<br />
&nbsp; &nbsp; command_name &nbsp; &nbsp;notify-host-by-campfire<br />
&nbsp; &nbsp; command_line &nbsp; &nbsp;/usr/bin/printf &quot;%b&quot; &quot;***** Nagios *****\n\nNotification Type: $NOTIFICATIONTYPE$\nHost: $HOSTNAME$\nState: $HOSTSTATE$\nAddress: $HOSTADDRESS$\nInfo: $HOSTOUTPUT$\n\nDate/Time: $LONGDATETIME$\n&quot; | /usr/local/bin/ruby /usr/local/bin/notify-by-campfire.rb -s &quot;** $NOTIFICATIONTYPE$ Host Alert: $HOSTNAME$ is $HOSTSTATE$ **&quot; <br />
&nbsp; &nbsp; } &nbsp; <br />
<br />
# 'notify-service-by-campfire' command definition<br />
define command{<br />
&nbsp; &nbsp; command_name &nbsp; &nbsp;notify-service-by-campfire<br />
&nbsp; &nbsp; command_line &nbsp; &nbsp;/usr/bin/printf &quot;%b&quot; &quot;***** Nagios *****\n\nNotification Type: $NOTIFICATIONTYPE$\n\nService: $SERVICEDESC$\nHost: $HOSTALIAS$\nAddress: $HOSTADDRESS$\nState: $SERVICESTATE$\n\nDate/Time: $LONGDATETIME$\n\nAdditional Info:\n\n$SERVICEOUTPUT$&quot; | /usr/local/bin/ruby /usr/local/bin/notify-by-campfire.rb -s &quot;** $NOTIFICATIONTYPE$ Service Alert: $HOSTALIAS$/$SERVICEDESC$ is $SERVICESTATE$ **&quot;<br />
&nbsp; &nbsp; }</div></div>
<p>Add this contact template definition for the Campfire contact to your <strong>contacts.cfg</strong>.  Don&#8217;t forget to add it to a <em>contactgroup</em>.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">define contact{<br />
&nbsp; &nbsp; &nbsp; &nbsp; name &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;campfire-contact<br />
&nbsp; &nbsp; &nbsp; &nbsp; service_notification_period &nbsp; &nbsp; 24x7<br />
&nbsp; &nbsp; &nbsp; &nbsp; host_notification_period &nbsp; &nbsp; &nbsp; &nbsp;24x7<br />
&nbsp; &nbsp; &nbsp; &nbsp; service_notification_options &nbsp; &nbsp;w,u,c,r,f,s<br />
&nbsp; &nbsp; &nbsp; &nbsp; host_notification_options &nbsp; &nbsp; &nbsp; d,u,r,f,s<br />
&nbsp; &nbsp; &nbsp; &nbsp; service_notification_commands &nbsp; notify-service-by-campfire<br />
&nbsp; &nbsp; &nbsp; &nbsp; host_notification_commands &nbsp; &nbsp; &nbsp;notify-host-by-campfire<br />
&nbsp; &nbsp; &nbsp; &nbsp; register &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0<br />
&nbsp; &nbsp; &nbsp; &nbsp; }</div></div>
<p>The Ruby code for <strong>notify-by-campfire.rb</strong> is here. Just install it wherever you&#8217;d like and as I said above, make sure its specified properly in your <strong>commands.cfg</strong>.<br />
<script src="http://gist.github.com/387799.js"></script></p>
<p><strong>Note:</strong> I am aware that I could have made this script much shorter, but my goal is to make this extensible should I want to provide more information or change the format.  Feel free to modify for your own usage.</p>
<p><strong>Update (2010-05-17):</strong> To make it a little easier to read in the context of a smaller Campfire window, I have amended the <em>notify-host-by-campfire</em> and <em>notify-service-by-campfire</em> entries to be shorter:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># 'notify-host-by-campfire' command definition<br />
define command{<br />
&nbsp; &nbsp; command_name &nbsp; &nbsp;notify-host-by-campfire<br />
&nbsp; &nbsp; command_line &nbsp; &nbsp;/usr/bin/printf &quot;%b&quot; &quot;Date/Time: $LONGDATETIME$\n\nHost: $HOSTNAME$\nType/State: $NOTIFICATIONTYPE$/$HOSTSTATE$\n\nInfo: $HOSTOUTPUT$\n\nDate/Time: $LONGDATETIME$\n&quot; | /usr/local/bin/ruby /usr/local/bin/notify-by-campfire.rb -s &quot;** $NOTIFICATIONTYPE$ Host Alert: $HOSTNAME$ ($HOSTADDRESS$) is $HOSTSTATE$ **&quot;<br />
&nbsp; &nbsp; }<br />
<br />
# 'notify-service-by-campfire' command definition<br />
define command{<br />
&nbsp; &nbsp; command_name &nbsp; &nbsp;notify-service-by-campfire<br />
&nbsp; &nbsp; command_line &nbsp; &nbsp;/usr/bin/printf &quot;%b&quot; &quot;Date/Time: $LONGDATETIME$\nType/State: $NOTIFICATIONTYPE$/$SERVICESTATE$\n\n$SERVICEOUTPUT$&quot; | /usr/local/bin/ruby /usr/local/bin/notify-by-campfire.rb -s &quot;** $NOTIFICATIONTYPE$ Service Alert: $HOSTALIAS$/$SERVICEDESC$ ($HOSTADDRESS$) is $SERVICESTATE$ **&quot;<br />
&nbsp; &nbsp; }</div></div>


<p>Related posts:<ol><li><a href='http://eric.lubow.org/2010/perl/perl-modules/monitoring-services-with-nagios-plugin/' rel='bookmark' title='Monitoring Services with Nagios::Plugin'>Monitoring Services with Nagios::Plugin</a></li>
<li><a href='http://eric.lubow.org/2007/perl/syshostname/' rel='bookmark' title='Sys::Hostname'>Sys::Hostname</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://eric.lubow.org/2010/system-administration/nagios-notify-by-campfire-plugin/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Creating Dummy Packages On Debian</title>
		<link>http://eric.lubow.org/2010/system-administration/creating-dummy-packages-on-debian/</link>
		<comments>http://eric.lubow.org/2010/system-administration/creating-dummy-packages-on-debian/#comments</comments>
		<pubDate>Tue, 04 May 2010 11:00:37 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[System Administration]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[system]]></category>

		<guid isPermaLink="false">http://eric.lubow.org/?p=708</guid>
		<description><![CDATA[One of my favorite things about Debian is its awesome package management system. Apt is one of the reasons I have used Debian for servers for so many years and eased my initial transition to Ubuntu (which as most people know was initially a Debian fork). Apt is a great tool as long as you [...]]]></description>
			<content:encoded><![CDATA[<p>One of my favorite things about Debian is its awesome package management system.  Apt is one of the reasons I have used Debian for servers for so many years and eased my initial transition to Ubuntu (which as most people know was initially a Debian fork).  Apt is a great tool as long as you aren&#8217;t building packages from source (and not making debs out of them).  I have packaged a whole bunch of debs, but sometimes it just isn&#8217;t necessary.  So if you haven&#8217;t used <a href="http://packages.debian.org/lenny/equivs">equivs</a>, then you need to check it out.<br />
<span id="more-708"></span><br />
Essentially it allows you to create dummy debs to provide packages that you installed from source (circumvent dependency checking).  It can get dirty when time comes to do dist-upgrades, but it has its usefulness.  For example, I wanted to install <a href="http://packages.debian.org/lenny/altermime">altermime</a> and I had installed the latest Postfix from source and altermime requires an MTA to be installed otherwise it would install exim (amongst other packages).  So I built a dummy packages doing the following:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># apt-get install equivs<br />
# equivs-control postfix</div></div>
<p>That will create a file named postfix in the current directory.  Make the file look similar to this:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Section: misc<br />
Priority: optional<br />
Standards-Version: 2.3.3<br />
<br />
Package: postfix-dummy<br />
Version: 2.7.0<br />
Section: mail<br />
Maintainer: Eric Lubow<br />
Provides: mail-transport-agent<br />
Architecture: all<br />
Description: Dummy Postfix package</div></div>
<p>Then go ahead and build your dummy package:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># equivs-build postfix <br />
dh_testdir<br />
dh_testroot<br />
dh_clean -k<br />
dh_testdir<br />
dh_testroot<br />
dh_install<br />
dh_installdocs<br />
dh_installchangelogs<br />
dh_compress<br />
dh_fixperms<br />
dh_installdeb<br />
dh_gencontrol<br />
dh_md5sums<br />
dh_builddeb<br />
dpkg-deb: building package `postfix-dummy' in `../postfix-dummy_2.7.0_all.deb'.<br />
<br />
The package has been created.<br />
Attention, the package has been created in the current directory,<br />
not in &quot;..&quot; as indicated by the message above!</div></div>
<p>Then I just installed the postfix-dummy package with:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># dpkg -i postfix-dummy_2.7.0_all.deb</div></div>
<p>And everything worked beautifully.  I installed altermime with no problem and we were off to the races.</p>


<p>Related posts:<ol><li><a href='http://eric.lubow.org/2009/spam/deploying-amavisd-logwatch/' rel='bookmark' title='Deploying Amavisd-logwatch'>Deploying Amavisd-logwatch</a></li>
<li><a href='http://eric.lubow.org/2010/system-administration/creating-configuration-files-with-ruby-templates/' rel='bookmark' title='Creating Configuration Files With Ruby Templates'>Creating Configuration Files With Ruby Templates</a></li>
<li><a href='http://eric.lubow.org/2010/mail/a-few-words-about-setting-up-postfix-multi-instance/' rel='bookmark' title='A Few Words About Setting Up Postfix Multi Instance'>A Few Words About Setting Up Postfix Multi Instance</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://eric.lubow.org/2010/system-administration/creating-dummy-packages-on-debian/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Monitoring Services with Nagios::Plugin</title>
		<link>http://eric.lubow.org/2010/perl/perl-modules/monitoring-services-with-nagios-plugin/</link>
		<comments>http://eric.lubow.org/2010/perl/perl-modules/monitoring-services-with-nagios-plugin/#comments</comments>
		<pubDate>Wed, 07 Apr 2010 11:15:03 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[Perl Modules]]></category>
		<category><![CDATA[System Administration]]></category>
		<category><![CDATA[nagios]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[system]]></category>

		<guid isPermaLink="false">http://eric.lubow.org/?p=664</guid>
		<description><![CDATA[There are a lot of people who say, &#8220;if it isn&#8217;t monitored, then it isn&#8217;t a service.&#8221; The problem is that I don&#8217;t think enough people outside of the systems world believe that or even understand why its said. I think the primary offenders here are developers. It isn&#8217;t because they don&#8217;t know better, but [...]]]></description>
			<content:encoded><![CDATA[<p>There are a lot of people who say, &#8220;if it isn&#8217;t monitored, then it isn&#8217;t a service.&#8221;  The problem is that I don&#8217;t think enough people outside of the systems world believe that or even understand why its said.  I think the primary offenders here are developers.  It isn&#8217;t because they don&#8217;t know better, but typically developers just want to get the application up and running and then move on to developing the next thing. I also think there is some fault on the side of the administrators and the managers not insisting that part of the completed version of a project includes monitoring.  But I don&#8217;t want to harp on this as much as I would like to show just how easy it is to compensate here by taking advantage of <a href="http://search.cpan.org/~tonvoon/Nagios-Plugin-0.33/lib/Nagios/Plugin.pm">Nagios::Plugin</a>.<br />
<span id="more-664"></span><br />
Nagios::Plugin is a Perl module that can be used to shortcut how easy it is to add a custom check for your application to your <a href="http://www.nagios.org/">Nagios</a> monitoring infrastructure.  It is so easy to write a Nagios plugin that even with comments and performance data, I have written one to check the alive-ness in under 50 lines.</p>
<div class="codecolorer-container perl default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:450px;"><div class="perl codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">use</span> Nagios<span style="color: #339933;">::</span><span style="color: #006600;">Plugin</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">use</span> Time<span style="color: #339933;">::</span><span style="color: #006600;">HiRes</span> <a href="http://perldoc.perl.org/functions/qw.html"><span style="color: #000066;">qw</span></a><span style="color: #009900;">&#40;</span> gettimeofday tv_interval <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$np</span> <span style="color: #339933;">=</span> Nagios<span style="color: #339933;">::</span><span style="color: #006600;">Plugin</span><span style="color: #339933;">-&gt;</span><span style="color: #000000; font-weight: bold;">new</span><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; shortname <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">'template'</span><span style="color: #339933;">,</span><br />
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp;<span style="color: #666666; font-style: italic;"># We need a URL to test</span><br />
&nbsp;<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$url</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;http://www.myapp.com/&quot;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp;<span style="color: #666666; font-style: italic;"># Create the UserAgent</span><br />
&nbsp;<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$ua</span> <span style="color: #339933;">=</span> LWP<span style="color: #339933;">::</span><span style="color: #006600;">UserAgent</span><span style="color: #339933;">-&gt;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; agent &nbsp; &nbsp; &nbsp; <span style="color: #339933;">=&gt;</span> &nbsp;<span style="color: #ff0000;">'Nagios Application Check'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; from &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #339933;">=&gt;</span> &nbsp;<span style="color: #ff0000;">'webmaster@myapp.com'</span><span style="color: #339933;">,</span><br />
&nbsp;<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp;<span style="color: #666666; font-style: italic;"># Change the timeout to 10 seconds instead of 3 min (180 seconds)</span><br />
&nbsp;<span style="color: #0000ff;">$ua</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">timeout</span><span style="color: #009900;">&#40;</span> <span style="color: #cc66cc;">10</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp;<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$t0</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span>gettimeofday<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$resp</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$ua</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$total</span> <span style="color: #339933;">=</span> tv_interval<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$t0</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span>gettimeofday<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp;<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$content</span><span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #0000ff;">$resp</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">is_success</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">$np</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">nagios_exit</span><span style="color: #009900;">&#40;</span> CRITICAL<span style="color: #339933;">,</span> <span style="color: #0000ff;">$resp</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">status_line</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #009900;">&#125;</span><br />
<br />
&nbsp;<span style="color: #666666; font-style: italic;"># Time it</span><br />
&nbsp;<span style="color: #0000ff;">$np</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">add_perfdata</span><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; label <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">&quot;time&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; value <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">&quot;${total}&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; uom <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">&quot;s&quot;</span><span style="color: #339933;">,</span><br />
&nbsp;<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp;<span style="color: #0000ff;">$np</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">nagios_exit</span><span style="color: #009900;">&#40;</span>OK<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;Test Suggestions Found&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<a href="http://perldoc.perl.org/functions/exit.html"><span style="color: #000066;">exit</span></a> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span></div></div>
<p>By reading the Pod documentation, you&#8217;ll also find that you can get a lot more specific.  You can add command line switches, lots of performance data, and my favorite, some pretty extensive success, warning or critical messages that can be displayed on the dashboard.  </p>


<p>Related posts:<ol><li><a href='http://eric.lubow.org/2010/system-administration/nagios-notify-by-campfire-plugin/' rel='bookmark' title='Nagios notify-by-campfire Plugin'>Nagios notify-by-campfire Plugin</a></li>
<li><a href='http://eric.lubow.org/2010/mac/textmate-minimap-plugin/' rel='bookmark' title='Textmate Minimap Plugin'>Textmate Minimap Plugin</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://eric.lubow.org/2010/perl/perl-modules/monitoring-services-with-nagios-plugin/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Cluster SSH with cSSHx</title>
		<link>http://eric.lubow.org/2010/system-administration/cluster-ssh-with-csshx/</link>
		<comments>http://eric.lubow.org/2010/system-administration/cluster-ssh-with-csshx/#comments</comments>
		<pubDate>Mon, 29 Mar 2010 09:00:21 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[System Administration]]></category>
		<category><![CDATA[cluster]]></category>
		<category><![CDATA[management]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[system]]></category>

		<guid isPermaLink="false">http://eric.lubow.org/?p=635</guid>
		<description><![CDATA[I am in the middle of building out a group of about 25 machines in a data center for my company. I hadn&#8217;t really dove into it on a micro level until a few days ago. I was moving around on individual machines that others were working on. When I had gotten to one of [...]]]></description>
			<content:encoded><![CDATA[<p>I am in the middle of building out a group of about 25 machines in a data center for my company.  I hadn&#8217;t really dove into it on a micro level until a few days ago.  I was moving around on individual machines that others were working on.  When I had gotten to one of the &#8220;untouched&#8221; machines, I found that vim wasn&#8217;t installed.  There was about 15 machines that were &#8220;untouched&#8221; and therefore were missing vim (along with other stuff).  And seriously who wants to install a bunch of the same software on every machine after they&#8217;ve already been kickstarted?<br />
<span id="more-635"></span><br />
So I could try to script it, but you really only get one shot when you script it.  Then you have to deal with expect (or log in as root) and that&#8217;s a little bit of a pain too.  So I decided to see what cluster SSH solutions are out there (since I haven&#8217;t needed them in a while).  The kicker was that it had to work for Mac OS X.  Typically anything that works on Linux has a variation on the Mac so I didn&#8217;t think that would be a problem.</p>
<p>First thing I found was a Perl application bundle that uses Tk to be a cluster SSH solution.  Its available <a href="http://github.com/duncs/clusterssh">here</a>.  I had a little trouble getting some of the required CPAN modules installed and because I like instant gratification (plus I needed to get some stuff done), I had to pass.</p>
<p>The next thing I found was <a href="http://code.google.com/p/csshx/">cSSHx</a> and it&#8217;s just awesome.  All you do is untar it, put it in your path and launch it as follows:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;"># </span>csshx <span style="color: #660033;">--login</span> elubow 192.168.1.1 192.168.1.2 192.168.1.3 192.168.1.4 192.168.1.5</div></div>
<p>One of the nice things is that it equally sizes all the Terminal windows that it opens so that they share equal screen real estate.  It provides a master typing bar to allow you to see what you&#8217;re typing in all sessions.  And if you need to something to one particular machine, just click on that machine&#8217;s Terminal window and only that session will receive input (since it is just a Terminal session after all).  Here is a screen shot of all of the 25 hosts open at once on my screen.<br />
<div id="attachment_637" class="wp-caption aligncenter" style="width: 310px"><a href="http://eric.lubow.org/wp-content/uploads/2010/03/cssh_screenshot.jpg"><img src="http://eric.lubow.org/wp-content/uploads/2010/03/cssh_screenshot-300x187.jpg" alt="Screenshot of cSSHx" title="Screenshot of cSSHx" width="300" height="187" class="size-medium wp-image-637" /></a><p class="wp-caption-text">Screenshot of cSSHx with 20 sessions</p></div></p>
<p>This is an awesome piece of software.  There are only 2 additional features that I think could make it better.  I would like to be able to open up a range if the IPs are sequential.  For instance 192.168.1.1/30 opens 192.168.1.1 and 192.168.1.2 (but on a much larger scale).  This is easier than creating a list each time I want to go to just a subset of machines.  I think it would also be great to be able to specify the password on the command line.  I know security folks would go nuts over this, but in the long run, sometimes its just easier to put the password in the command line.</p>
<p>I want to leave you with 1 more thing.  Although this is a nice tool, it can be even better with aliases.  Add a bunch of groups to your <strong>.bashrc</strong> or you <strong>.bash_profile</strong>.  Something along the lines of:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">csshmail</span>=<span style="color: #ff0000;">'csshx --login elubow 192.168.1.3 192.168.1.4 192.168.1.5'</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">csshdb</span>=<span style="color: #ff0000;">'csshx --login elubow 192.168.1.35 192.168.1.34 192.168.1.37'</span></div></div>


<p>Related posts:<ol><li><a href='http://eric.lubow.org/2010/system-administration/sharing-a-screen-session/' rel='bookmark' title='Sharing a Screen Session'>Sharing a Screen Session</a></li>
<li><a href='http://eric.lubow.org/2007/linux-security/ssh-organization-tips/' rel='bookmark' title='SSH Organization Tips'>SSH Organization Tips</a></li>
<li><a href='http://eric.lubow.org/2009/system-administration/ssh-over-the-web-with-web-shell/' rel='bookmark' title='SSH Over The Web With Web Shell'>SSH Over The Web With Web Shell</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://eric.lubow.org/2010/system-administration/cluster-ssh-with-csshx/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Git Branch Name in Your Bash Prompt</title>
		<link>http://eric.lubow.org/2009/system-administration/git-branch-name-in-your-bash-prompt/</link>
		<comments>http://eric.lubow.org/2009/system-administration/git-branch-name-in-your-bash-prompt/#comments</comments>
		<pubDate>Fri, 11 Dec 2009 11:50:32 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[System Administration]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[tricks]]></category>

		<guid isPermaLink="false">http://eric.lubow.org/?p=461</guid>
		<description><![CDATA[I work with a few repositories at any given time. And during that time, I typically have multiple branches created for each repository. I figured that it would make my life easier if I knew which branch and/or repository I was working in. Luckily, very little hackery is required here since the git distribution already [...]]]></description>
			<content:encoded><![CDATA[<p>I work with a few repositories at any given time. And during that time, I typically have multiple branches created for each repository.  I figured that it would make my life easier if I knew which branch and/or repository I was working in.  Luckily, very little hackery is required here since the git distribution already comes with such a tool.  (Note: If you didn&#8217;t build Git from source, then you may not have this file.)<br />
<span id="more-461"></span><br />
First thing I did was copy the git auto-completion file into my home directory:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">elubow<span style="color: #000000; font-weight: bold;">@</span>beacon repo$ <span style="color: #c20cb9; font-weight: bold;">cp</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>src<span style="color: #000000; font-weight: bold;">/</span>git<span style="color: #000000; font-weight: bold;">/</span>contrib<span style="color: #000000; font-weight: bold;">/</span>git-completion.bash ~<span style="color: #000000; font-weight: bold;">/</span>.git-completion.sh</div></div>
<p>Then I edited my .bashrc file to load up my new <strong>PS1</strong> variable (PS1 is variable name for the Bash prompt) with git information only if we are currently in a repository.  Don&#8217;t forget to set a default <strong>PS1</strong> in case your .bashrc can&#8217;t find your <strong>.git-completion.sh</strong> file.  Another item of note is that you should have the if state below load after your load your <strong>PATH</strong> variable.  This removes the potential for <strong>git</strong> having to be located after every commend.</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># Set the base PS1</span><br />
<span style="color: #007800;">PS1</span>=<span style="color: #ff0000;">&quot;\u:\h \W$ &quot;</span><br />
<br />
<span style="color: #666666; font-style: italic;"># Source the git bash completion file</span><br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-f</span> ~<span style="color: #000000; font-weight: bold;">/</span>.git-completion.sh <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">source</span> ~<span style="color: #000000; font-weight: bold;">/</span>.git-completion.sh<br />
&nbsp; &nbsp; <span style="color: #007800;">GIT_PS1_SHOWDIRTYSTATE</span>=<span style="color: #c20cb9; font-weight: bold;">true</span><br />
&nbsp; &nbsp; <span style="color: #007800;">PS1</span>=<span style="color: #ff0000;">'\u@\h$(__git_ps1 &quot; (%s)&quot;) \W$ '</span><br />
<span style="color: #000000; font-weight: bold;">fi</span><br />
<br />
<span style="color: #7a0874; font-weight: bold;">export</span> PS1</div></div>
<p>You&#8217;ll notice I also set a variable called <strong>GIT_PS1_SHOWDIRTYSTATE</strong>.  What this variable does is it adds a <strong>*</strong> to the branch name if the branch has been changed.</p>
<p>There are other options here if you are looking for something more in depth.  <a href="http://volnitsky.com/project/git-prompt/">Git Prompt</a> provides you with a much more in depth version on the command line fo your dirty files and is much more visually oriented.</p>
<p>Additionally, you now get to make use of the other auto-complete features that this script was actually intended for.</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">elubow<span style="color: #000000; font-weight: bold;">@</span>beacon <span style="color: #7a0874; font-weight: bold;">&#40;</span>master<span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> repo$ <span style="color: #c20cb9; font-weight: bold;">git</span> sta<br />
stage &nbsp; &nbsp;stash &nbsp; &nbsp;status</div></div>
<p>Note the difference between my prompt at the beginning of the post and the end.  When I am not in a repository, nothing shows in my <strong>PS1</strong> variable.</p>
<p>It&#8217;s just that simple to do this and definitely saves some time. Enjoy.</p>


<p>Related posts:<ol><li><a href='http://eric.lubow.org/2009/misc/converting-from-subversion-to-git/' rel='bookmark' title='Converting From Subversion To Git'>Converting From Subversion To Git</a></li>
<li><a href='http://eric.lubow.org/2009/misc/printing-new-lines-in-bash/' rel='bookmark' title='Printing New Lines in Bash'>Printing New Lines in Bash</a></li>
<li><a href='http://eric.lubow.org/2009/tips/git-command-aliases/' rel='bookmark' title='Git Command Aliases'>Git Command Aliases</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://eric.lubow.org/2009/system-administration/git-branch-name-in-your-bash-prompt/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Creating a Slave DNS Server on Bind9</title>
		<link>http://eric.lubow.org/2009/system-administration/creating-a-slave-dns-server-on-bind9/</link>
		<comments>http://eric.lubow.org/2009/system-administration/creating-a-slave-dns-server-on-bind9/#comments</comments>
		<pubDate>Sun, 29 Nov 2009 16:10:13 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[System Administration]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[bind]]></category>
		<category><![CDATA[dns]]></category>

		<guid isPermaLink="false">http://eric.lubow.org/?p=174</guid>
		<description><![CDATA[I couldn&#8217;t find a quick and dirty list of commands for setting up a slave DNS server so I figured I would just throw it together. Starting with a fully working primary name server, we are going to set up a slave name server. We are going to make the following assumptions: primary &#8211; 1.2.3.4 [...]]]></description>
			<content:encoded><![CDATA[<p>I couldn&#8217;t find a quick and dirty list of commands for setting up a slave DNS server so I figured I would just throw it together.</p>
<p>Starting with a fully working primary name server, we are going to set up a slave name server.  We are going to make the following assumptions:<br />
primary &#8211; 1.2.3.4<br />
slave &#8211; 4.5.6.7<br />
* We want to have the domain example.com have a slave name server</p>
<p>On the primary (or master) name server, add the following lines to the options section.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">options {<br />
&nbsp; &nbsp; allow-transfer { 4.5.6.7; };<br />
&nbsp; &nbsp; notify yes;<br />
};</div></div>
<p>Ensure that you update the serial number in the SOA on the master.  Then run:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># rndc reload</div></div>
<p>On the slave name server, add the following entry to the named.conf file (or whichever file houses your zone entries).  Ensure that the path leading up to the zone file exists and that bind has write access to that directory.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp;zone &quot;example.com&quot; &nbsp;{ type slave; file &quot;/etc/bind9/zones/example.com.slave&quot;; masters { 1.2.3.4; }; };</div></div>
<p>Then once you made the changes to the slave, you will need to reload the configuration.  Do this the same way you did on the master:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># rndc reload</div></div>
<p>If you watch your DNS log, you should see the transfer happen as soon as you restart both <em>named</em> servers.</p>


<p>Related posts:<ol><li><a href='http://eric.lubow.org/2007/virtualization/cloning-a-virtual-machine-in-vmware-vi3-without-virtual-server/' rel='bookmark' title='Cloning a Virtual Machine in VMWare VI3 without Virtual Server'>Cloning a Virtual Machine in VMWare VI3 without Virtual Server</a></li>
<li><a href='http://eric.lubow.org/2010/system-administration/creating-dummy-packages-on-debian/' rel='bookmark' title='Creating Dummy Packages On Debian'>Creating Dummy Packages On Debian</a></li>
<li><a href='http://eric.lubow.org/2010/databases/mysql/database-readwrite-splitting-in-frameworksorms/' rel='bookmark' title='Database Read/Write Splitting in Frameworks/ORMs'>Database Read/Write Splitting in Frameworks/ORMs</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://eric.lubow.org/2009/system-administration/creating-a-slave-dns-server-on-bind9/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SSH Over The Web With Web Shell</title>
		<link>http://eric.lubow.org/2009/system-administration/ssh-over-the-web-with-web-shell/</link>
		<comments>http://eric.lubow.org/2009/system-administration/ssh-over-the-web-with-web-shell/#comments</comments>
		<pubDate>Fri, 27 Nov 2009 11:45:46 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[System Administration]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://eric.lubow.org/?p=431</guid>
		<description><![CDATA[After reading a Tweet from Matt Cutts about being able to SSH from the iPhone (and the web in general), I had to give it a try. I am always looking for better ways to be able to check on systems when necessary. I have iPhone apps for SSHing around if I need as well, [...]]]></description>
			<content:encoded><![CDATA[<p>After reading a <a href="http://twitter.com/mattcutts/status/5952475317">Tweet</a> from <a href="http://www.mattcutts.com/">Matt Cutts</a> about being able to SSH from the iPhone (and the web in general), I had to give it a try.  I am always looking for better ways to be able to check on systems when necessary.  I have iPhone apps for SSHing around if I need as well, but like with any &#8220;new&#8221; tool, I have to try it out to see if it serves a purpose or makes my admin life easier in any way.</p>
<p>First go check out the Google Code repository for <a href="http://code.google.com/p/web-shell/">Web Shell</a>.  Webshell is written in Python and is based on Ajaxterm.  All that&#8217;s required is SSL And Python 2.3 or greater.  It works on any browser that has Javascript and can make use of AJAX.</p>
<p>The way Web Shell works is you start it up on a server and then can use a web browser to access only that machine over SSH.  The works best if you have a gateway server to a network and use a single point of entry to access the rest of the servers.  Web Shell runs on HTTPS on port 8022.  Reading the README will lead you through the same set of instructions I used below.  Once installed, we connect by using a web browser: <strong>https://server.com:8022/</strong><br />
<span id="more-431"></span></p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">elubow@server:/home/web/webshell.lubow.org-8022$ ./make_certificate.sh <br />
Generating a 1024 bit RSA private key<br />
...............................................................++++++<br />
...........................................++++++<br />
writing new private key to 'webshell.pem'<br />
-----<br />
elubow@server:/home/web/webshell.lubow.org-8022$ ./webshell.py <br />
The python SSL extensions seem to be not installed.<br />
You can run WebShell without SSL encryption with the --ssl-disable command line switch.</div></div>
<p>You&#8217;ll notice that while it is possible to run the terminal without SSL, it is just not in our best interest.  So let&#8217;s go ahead and install it.  I use <a href="http://debian.org/">Debian</a> on my servers.  So in my case, it&#8217;s as simple as:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">server:~# apt-get install python-pyopenssl python-openssl<br />
Get:1 http://ftp.de.debian.org lenny/main python-openssl 0.7-2 [88.9kB]<br />
Get:2 http://ftp.de.debian.org lenny/main python-pyopenssl 0.7-2 [9.0kB]<br />
Unpacking python-openssl (from .../python-openssl_0.7-2_i386.deb) ...<br />
Setting up python-openssl (0.7-2) ...<br />
Setting up python-pyopenssl (0.7-2) ...<br />
Processing triggers for python-support ...</div></div>
<p>Then we run the server:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">elubow@server:/home/web/ssh.lubow.org-8022$ ./webshell.py <br />
WebShell (https) at 0.0.0.0, port 8022</div></div>
<p>I&#8217;ve included a screenshot from my iPhone below.  The background is interchangeable with any other transparent background image.  If you&#8217;re in need of a quick SSH or someone else&#8217;s smart phone has service and yours doesn&#8217;t with your fancy SSH programs, then this is definitely a cool and viable alternative.</p>
<table align="center" cellpadding="10px">
<tr>
<td><div id="attachment_435" class="wp-caption aligncenter" style="width: 160px"><a href="http://eric.lubow.org/wp-content/uploads/2009/11/IMG_0137.PNG"><img src="http://eric.lubow.org/wp-content/uploads/2009/11/IMG_0137-150x150.PNG" alt="Web Shell SSH on iPhone" title="Web Shell SSH" width="150" height="150" class="size-thumbnail wp-image-435" /></a><p class="wp-caption-text">Web Shell SSH on iPhone</p></div></td>
<td><div id="attachment_437" class="wp-caption aligncenter" style="width: 160px"><a href="http://eric.lubow.org/wp-content/uploads/2009/11/IMG_0138.PNG"><img src="http://eric.lubow.org/wp-content/uploads/2009/11/IMG_0138-150x150.PNG" alt="Web Shell SSH with keyboard out" title="Web Shell SSH with keyboard out" width="150" height="150" class="size-thumbnail wp-image-437" /></a><p class="wp-caption-text">Web Shell SSH with keyboard out</p></div></td>
</tr>
</table>


<p>Related posts:<ol><li><a href='http://eric.lubow.org/2010/book-reviews/mysql-for-python/' rel='bookmark' title='MySQL for Python'>MySQL for Python</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://eric.lubow.org/2009/system-administration/ssh-over-the-web-with-web-shell/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

