<?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>Coderholic &#187; scripts</title>
	<atom:link href="http://www.coderholic.com/category/scripts/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.coderholic.com</link>
	<description>Addicted to Development</description>
	<lastBuildDate>Tue, 31 Aug 2010 09:19:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>PHPUnit Command Line Code Coverage</title>
		<link>http://www.coderholic.com/phpunit-command-line-code-coverage/</link>
		<comments>http://www.coderholic.com/phpunit-command-line-code-coverage/#comments</comments>
		<pubDate>Wed, 14 Apr 2010 21:40:33 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[scripts]]></category>
		<category><![CDATA[ci]]></category>
		<category><![CDATA[code coverage]]></category>
		<category><![CDATA[hudson]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[phpunit]]></category>

		<guid isPermaLink="false">http://www.coderholic.com/?p=663</guid>
		<description><![CDATA[I&#8217;m a big fan of unit testing, and for PHP projects I use PHPUnit. Combined with XDebug PHPUnit provides some great code coverage reporting options, including detailed HTML reports and a variety of different XML report options that work nicely with various different continuous integration servers and other tools. A feature I&#8217;ve often wanted, that [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a big fan of unit testing, and for PHP projects I use <a href="http://www.phpunit.de/">PHPUnit</a>. Combined with <a href="http://xdebug.org/">XDebug</a> PHPUnit provides some great code coverage reporting options, including detailed HTML reports and a variety of different XML report options that work nicely with various different continuous integration servers and other tools. </p>
<p>A feature I&#8217;ve often wanted, that is currently missing from PHPUnit, is a simple command line display of code coverage statistics when you&#8217;re running tests. If you&#8217;re trying to improve the code coverage of a specific test it isn&#8217;t practical to generate a full HTML report of the test every time you run it, and then check it in a browser. It would be much easier if the code coverage could be reported next to the success or failure message on the command line. </p>
<p>After a little bit of investigation into the different PHPUnit reports, and some git, awk, and sed hackery I came up with the following PHPUnit wrapper that does exactly what I was after. Once you&#8217;ve run a test, or collection of tests, it&#8217;ll display a list of files affected by the test and the code coverage for each file. The code for this script is below:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
<span style="color: #007800;">METRIC_FILE</span>=<span style="color: #ff0000;">&quot;/tmp/test-metrics.xml&quot;</span>
<span style="color: #666666; font-style: italic;"># Call PHPUnit will all provided command line arguments, and also generate a metrics file</span>
phpunit <span style="color: #660033;">--log-metrics</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$METRIC_FILE</span>&quot;</span> $<span style="color: #000000; font-weight: bold;">@</span>
<span style="color: #666666; font-style: italic;"># If phpunit exits with an error then exit here with the same error code</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$?</span> <span style="color: #660033;">-ne</span> <span style="color: #000000;">0</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #000000; font-weight: bold;">then</span>
   <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #007800;">$?</span>
<span style="color: #000000; font-weight: bold;">fi</span>
<span style="color: #666666; font-style: italic;"># Do some manipulation of the metrics file and output each file and the coverage for that file</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;*** SIMPLE COVERAGE REPORT ***&quot;</span>
<span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$METRIC_FILE</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #ff0000;">&quot;&lt;file&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">awk</span> <span style="color: #ff0000;">'{print $2 $10}'</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span>
<span style="color: #ff0000;">&quot;s|<span style="color: #007800;">$PWD</span>||g&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">awk</span> <span style="color: #660033;">-F</span><span style="color: #000000; font-weight: bold;">\&quot;</span> <span style="color: #ff0000;">'{printf &quot;%-50s %.2f%\n&quot;, $2, $4}'</span>
<span style="color: #666666; font-style: italic;"># Cleanup</span>
<span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$METRIC_FILE</span>&quot;</span></pre></div></div>

<p>I&#8217;ve place the script in /usr/bin/phpuc on my machine, and then I can invoke it like so:</p>
<pre>
$ phpcs tests/ExampleTest.xml

PHPUnit 3.3.16 by Sebastian Bergmann.

.........

Time: 0 seconds

OK (9 tests, 9 assertions)

Writing metrics report XML file, this may take a moment.
*** SIMPLE COVERAGE REPORT ***
Example.php                     89.37%
IncludedFile.php                 12.9%
</pre>
<p>Hopefully this will be something that&#8217;ll be built-in to PHPUnit in the future!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/phpunit-command-line-code-coverage/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PyWebShot &#8211; Generate website thumbnails using Python</title>
		<link>http://www.coderholic.com/pywebshot-generate-website-thumbnails-using-python/</link>
		<comments>http://www.coderholic.com/pywebshot-generate-website-thumbnails-using-python/#comments</comments>
		<pubDate>Sun, 11 Apr 2010 17:24:27 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[scripts]]></category>
		<category><![CDATA[python gtkmozembed screenshot pywebshot webkit2png]]></category>

		<guid isPermaLink="false">http://www.coderholic.com/?p=643</guid>
		<description><![CDATA[There have been lots of links to automatic website thumbnail generators on sites like reddit and hacker news today, including webkit2png and CutyCapt. Well it just so happens that a few weeks ago I wrote my own website thumbnail generator, and today I got around to putting it on GitHub. The code is based on [...]]]></description>
			<content:encoded><![CDATA[<p>There have been lots of links to automatic website thumbnail generators on sites like reddit and hacker news today, including <a href="http://www.paulhammond.org/webkit2png/">webkit2png</a> and <a href="http://cutycapt.sourceforge.net/">CutyCapt</a>. Well it just so happens that a few weeks ago I wrote my own website thumbnail generator, and today I got around to putting it on <a href="http://github.com/coderholic/PyWebShot">GitHub</a>.</p>
<p>The code is based on Matt Biddulph&#8217;s <a href="http://burtonini.com/computing/screenshot-tng.py">screenshot-tng</a> script, but heavily modified to be more user friendly and provide more options. It uses embedded mozilla for rendering, and therefore requires the <a href="http://www.mozilla.org/unix/gtk-embedding.html">python-gtkmozembed</a> package.</p>
<p>You can specify a resolution to take the screenshot at, and also a resolution for the thumbnail. When generating the thumbnail the aspect ratio will be preserved. You can also specify a delay, so that the screenshot is only taken so many seconds after loading the page. Here&#8217;s an example of running PyWebShot with 3 URLs, and the resulting images:</p>
<pre>
$ ./pywebshot.py -t 500x250 http://www.coderholic.com http://geomium.com/update/598/ http://jobs.plasis.co.uk
Loading http://www.coderholic.com... saved as www.coderholic.com.png
Loading http://geomium.com/update/598/... saved as geomium.com.update.598..png
Loading http://jobs.plasis.co.uk... saved as jobs.plasis.co.uk.png
</pre>
<p><img src="http://www.coderholic.com/wp-content/uploads/coderholic.com_.png"/></p>
<p><img src="http://www.coderholic.com/wp-content/uploads/geomium.com_.update.598..png"/></p>
<p><img src="http://www.coderholic.com/wp-content/uploads/jobs.plasis.co_.uk_.png"/></p>
<p>It you have a huge list of URLs you&#8217;d like to generate screenshots for you can put them all into a file and generate images for them all with the following command:</p>
<pre>
$ cat urls.txt | xargs ./pywebshot.py
</pre>
<p>For more details and the source code see the <a href="http://github.com/coderholic/PyWebShot">PyWebShot project page</a> on GitHub.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/pywebshot-generate-website-thumbnails-using-python/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Clojure: 12 New Programming Languages Update 1</title>
		<link>http://www.coderholic.com/clojure-12-new-programming-languages-update-1/</link>
		<comments>http://www.coderholic.com/clojure-12-new-programming-languages-update-1/#comments</comments>
		<pubDate>Sat, 20 Mar 2010 10:25:08 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[scripts]]></category>
		<category><![CDATA[12in12]]></category>
		<category><![CDATA[clojure]]></category>

		<guid isPermaLink="false">http://www.coderholic.com/?p=588</guid>
		<description><![CDATA[At the start of the year I announced that I was setting myself the challenge of learning 12 new programming languages during 2010. That works out at a language a month, so seeing as it&#8217;s almost the end of March you might expect me to be wrapping up my third language. Unfortunately that isn&#8217;t the [...]]]></description>
			<content:encoded><![CDATA[<p>At the start of the year I announced that I was setting myself the challenge of learning <a href="http://www.coderholic.com/12-new-programming-languages-in-12-months/">12 new programming languages during 2010</a>. That works out at a language a month, so seeing as it&#8217;s almost the end of March you might expect me to be wrapping up my third language. Unfortunately that isn&#8217;t the case. I&#8217;m just about to move on to my second. I&#8217;m still optimistic I can achieve the target of 12 new languages this year though, so expect future updates to be more regular.</p>
<p><strong>Getting Starting with Clojure</strong></p>
<p>Getting up and running with Clojure was made easy to to the wealth of documentation. There&#8217;s a great <a href="http://en.wikibooks.org/wiki/Clojure_Programming/Getting_Started">getting started guide</a>, and a guide specifically for <a href="http://riddell.us/ClojureOnUbuntu.html">Clojure on Ubuntu</a>. In terms of programming environment there&#8217;s a round up of <a href="http://www.bestinclass.dk/index.php/2010/03/clojure-ides-the-grand-tour-getting-started/">Clojure IDEs</a>. I stuck to Vim, but I didn&#8217;t take it as far as <a href="http://writequit.org/blog/?p=386">this guide</a>, which describes turning Vim into a fairly comprehensive Clojure IDE. </p>
<p>Clojure has a <a href="http://clojure.org/repl_and_main">REPL</a>, which I always find makes learning a new language easier. When you want to find something out just type it in a see what the result is! The default REPL doesn&#8217;t support arrow navigation or pressing up to run previous commands though, so it can be a little frustrating. There are guides on <a href="http://en.wikibooks.org/wiki/Clojure_Programming/Getting_Started#Enhancing_Clojure_REPL_with_JLine">enhacing the REPL</a> with this functionality.</p>
<p>One of the first things I did was put together the following shell script which either runs the specified Clojure script, or gives you a REPL if no script was specified.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/sh</span>
<span style="color: #007800;">CLOJURE_JAR</span>=<span style="color: #ff0000;">&quot;/opt/clojure-1.1.0/clojure.jar&quot;</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;$1&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span> 
        java <span style="color: #660033;">-jar</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${CLOJURE_JAR}</span>&quot;</span> 
<span style="color: #000000; font-weight: bold;">else</span>
        java <span style="color: #660033;">-jar</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${CLOJURE_JAR}</span>&quot;</span> <span style="color: #ff0000;">&quot;$@&quot;</span>
<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<p><strong>Writing Code</strong></p>
<p>I decided to write a port scanner in Clojure, which would introduce me to command line argument handling, the network API, and parallelization. </p>
<p>One of the great things about Clojure is that despite being such a new language there is so much example code available on the web. I was able to find a <a href="http://travis-whitton.blogspot.com/2009/07/network-sweeping-with-clojure.html">Clojure network scanner</a> by Travis Whitton which detailed all of the network related code I&#8217;d need to my port scanner. Travis uses <a href="http://clojure.org/agents">Clojure&#8217;s agents</a> for parallelization, which is something else I borrowed from his script. I was amazed at how easy it was to parallelize the lookups. So much simpler than threading. If there is only one thing I take away from Clojure it&#8217;ll be its interesting approaches to parallelization.</p>
<p>So without further ado here is my Clojure port scanner:</p>

<div class="wp_syntax"><div class="code"><pre class="scheme" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span>import '<span style="color: #66cc66;">&#40;</span>java.io IOException<span style="color: #66cc66;">&#41;</span>
        '<span style="color: #66cc66;">&#40;</span>java.net Socket<span style="color: #66cc66;">&#41;</span>
        '<span style="color: #66cc66;">&#40;</span>java.net InetSocketAddress<span style="color: #66cc66;">&#41;</span>
        '<span style="color: #66cc66;">&#40;</span>java.net SocketTimeoutException<span style="color: #66cc66;">&#41;</span>
        '<span style="color: #66cc66;">&#40;</span>java.net UnknownHostException<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">==</span> <span style="color: #66cc66;">&#40;</span>count <span style="color: #66cc66;">*</span>command<span style="color: #66cc66;">-</span>line<span style="color: #66cc66;">-</span>args<span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span>def hostname <span style="color: #66cc66;">&#40;</span>first <span style="color: #66cc66;">*</span>command<span style="color: #66cc66;">-</span>line<span style="color: #66cc66;">-</span>args<span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span>
    <span style="color: #66cc66;">&#40;</span>println <span style="color: #ff0000;">&quot;Usage: scanner &amp;lt;hostname&amp;gt;&quot;</span><span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#40;</span>System<span style="color: #66cc66;">/</span>exit <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span>defn port<span style="color: #66cc66;">-</span>open? <span style="color: #66cc66;">&#91;</span>hostname port timeout<span style="color: #66cc66;">&#93;</span>
  <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#91;</span>sock<span style="color: #66cc66;">-</span>addr <span style="color: #66cc66;">&#40;</span>InetSocketAddress. hostname port<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#93;</span>
    <span style="color: #66cc66;">&#40;</span>try
     <span style="color: #66cc66;">&#40;</span>with<span style="color: #66cc66;">-</span>open <span style="color: #66cc66;">&#91;</span>sock <span style="color: #66cc66;">&#40;</span>Socket.<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#93;</span>
       <span style="color: #66cc66;">&#40;</span>. sock connect sock<span style="color: #66cc66;">-</span>addr timeout<span style="color: #66cc66;">&#41;</span>
       port<span style="color: #66cc66;">&#41;</span>
     <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">catch</span> IOException <span style="color: #b1b100;">e</span> false<span style="color: #66cc66;">&#41;</span>
     <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">catch</span> SocketTimeoutException <span style="color: #b1b100;">e</span> false<span style="color: #66cc66;">&#41;</span>
     <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">catch</span> UnknownHostException <span style="color: #b1b100;">e</span> false<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
     	<span style="color: #66cc66;">&lt;</span>li<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&#40;</span>defn host<span style="color: #66cc66;">-</span>port<span style="color: #66cc66;">-</span>open? <span style="color: #66cc66;">&#91;</span>port<span style="color: #66cc66;">&#93;</span>
  <span style="color: #66cc66;">&#40;</span>port<span style="color: #66cc66;">-</span>open? hostname port <span style="color: #cc66cc;">5000</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span>def port<span style="color: #66cc66;">-</span><span style="color: #b1b100;">list</span> <span style="color: #66cc66;">&#40;</span>range <span style="color: #cc66cc;">1</span> <span style="color: #cc66cc;">1024</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span>def agents <span style="color: #66cc66;">&#40;</span>for <span style="color: #66cc66;">&#91;</span>port port<span style="color: #66cc66;">-</span><span style="color: #b1b100;">list</span><span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>agent port<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span>println <span style="color: #66cc66;">&#40;</span>str <span style="color: #ff0000;">&quot;Scanning &quot;</span> hostname <span style="color: #ff0000;">&quot;...&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span>doseq <span style="color: #66cc66;">&#91;</span>agent agents<span style="color: #66cc66;">&#93;</span>
  <span style="color: #66cc66;">&#40;</span>send<span style="color: #66cc66;">-</span>off agent host<span style="color: #66cc66;">-</span>port<span style="color: #66cc66;">-</span>open?<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span>apply await agents<span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span>doseq <span style="color: #66cc66;">&#91;</span>port <span style="color: #66cc66;">&#40;</span>filter deref agents<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#93;</span>
       <span style="color: #66cc66;">&#40;</span>println <span style="color: #66cc66;">&#40;</span>str @port <span style="color: #ff0000;">&quot; is open&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span>shutdown<span style="color: #66cc66;">-</span>agents<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>I&#8217;m sure it is far from an idiomatic solution, so any suggestions for improvement are welcome. Running the scanner with my bash script gives the following output:</p>
<pre>
$ ./clj.sh scanner
Usage: scanner &lt;hostname&gt;

$ ./clj.sh scanner github.com
Scanning github.com...
22 is open
80 is open
443 is open
</pre>
<p><strong>What&#8217;s next?</strong></p>
<p>I&#8217;ve barely scratched the surface of Clojure, but I&#8217;ve certainly become more aware of some of the concepts and idioms used by the language, which is what I was hoping for. I&#8217;ll be looking for more projects in the future where I can make use of it. For now though I need to move on to another language as part of my challenge. As I&#8217;m running behind I plan to go with one that I don&#8217;t think will be too unfamiliar, either Go or Fantom. I&#8217;ll keep you posted!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/clojure-12-new-programming-languages-update-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Munin Popularity Plugins</title>
		<link>http://www.coderholic.com/munin-popularity-plugins/</link>
		<comments>http://www.coderholic.com/munin-popularity-plugins/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 19:45:24 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[scripts]]></category>

		<guid isPermaLink="false">http://www.coderholic.com/?p=405</guid>
		<description><![CDATA[After writing about Munin last week and mentioning some of its uses outside of system performance tracking I decided to write a collection of plugins for tracking website popularity. The full code is available on GitHub. The plugins include: Alexa traffic rank Number of pages in the Google index Technorati authority Feedburner RSS subscribers Twitter [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-408" title="google-index" src="http://www.coderholic.com/wp-content/uploads/google-index.png" alt="google-index" width="504" height="304" /></p>
<p>After writing about <a href="http://www.coderholic.com/server-monitoring-with-munin/">Munin</a> last week and mentioning some of its uses outside of system performance tracking I decided to write a collection of plugins for tracking website popularity. The full code is available on <a href="http://github.com/coderholic/munin-popularity-plugins">GitHub</a>.</p>
<p>The plugins include:</p>
<ul>
<li>Alexa traffic rank</li>
<li>Number of pages in the Google index</li>
<li>Technorati authority</li>
<li>Feedburner RSS subscribers</li>
<li>Twitter followers</li>
</ul>
<p>Munin will automatically handle the generation of daily, weekly, monthly and yearly graphs. All of the plugins support graphing of multiple sites/accounts, so you can show several sites on the same graph, as is the case with the Google index graph above, or you can decide to show a single site/account per graph. Some example graphs are shown below:</p>
<p><img class="alignnone size-full wp-image-410" title="twitter" src="http://www.coderholic.com/wp-content/uploads/twitter.png" alt="twitter" width="503" height="280" /></p>
<p><img class="alignnone size-full wp-image-409" title="technorati" src="http://www.coderholic.com/wp-content/uploads/technorati.png" alt="technorati" width="505" height="281" /></p>
<p><img class="alignnone size-full wp-image-407" title="feedburner" src="http://www.coderholic.com/wp-content/uploads/feedburner.png" alt="feedburner" width="503" height="280" /></p>
<p><img class="alignnone size-full wp-image-406" title="alexa" src="http://www.coderholic.com/wp-content/uploads/alexa.png" alt="alexa" width="504" height="304" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/munin-popularity-plugins/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Server Monitoring with Munin</title>
		<link>http://www.coderholic.com/server-monitoring-with-munin/</link>
		<comments>http://www.coderholic.com/server-monitoring-with-munin/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 21:53:56 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[apache]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[scripts]]></category>
		<category><![CDATA[munin server opensource monitoring sysadmin]]></category>

		<guid isPermaLink="false">http://www.coderholic.com/?p=378</guid>
		<description><![CDATA[Munin is an excellent open source tool for monitoring and graphing server performance metrics. It can be configured to send out alert emails when something goes wrong with your server, and the graphs make it easy to view trends over time: You could see that your site gets much less traffic on a Sunday, for [...]]]></description>
			<content:encoded><![CDATA[<p>Munin is an excellent open source tool for monitoring and graphing server performance metrics. It can be configured to send out alert emails when something goes wrong with your server, and the graphs make it easy to view trends over time: You could see that your site gets much less traffic on a Sunday, for example, or that the number of database queries performed per day has doubled in the last 2 months.</p>
<p><img style="border: 1px solid gray;" src="/wp-content/uploads/munin-graphs1.png" alt="" /></p>
<p>On a Debian-based system installing Munin is as simple as running the following command, and then going to http://your-server/munin/ in your browser:</p>
<pre>sudo aptitude install munin</pre>
<p>Munin comes with lots of monitoring plugins by default, including those for MySQL, PostgresSQL, Apache, Tomcat, Squid, and for things such a CPU and memory usage, load average, network traffic, and many more. You can also find lots of user submitted plugins on sites like <a href="http://muninexchange.projects.linpro.no/">Munin Exchange</a>.</p>
<p>Munin doesn&#8217;t have to be used solely for monitoring server performance though. Being so easy to extend Munin is  also a great tool for tracking non-server performance related trends over time. In just a few lines of code you could write plugins to track the following stats about your website:</p>
<ul>
<li>Number of User signups</li>
<li>Google PageRank</li>
<li>Pages in Google&#8217;s index</li>
<li>Number of backlinks</li>
<li>Number of twitter mentions</li>
<li>Alexa traffic rank</li>
</ul>
<p>The <em>number of pages in Google&#8217;s index</em> is actually a plugin I&#8217;ve written. Simple put the following code in your /etc/munin/plugins directory to see it in action:</p>
<pre name="code" class="python">
#!/bin/sh
# Munin Plugin to display the number of pages in the
# google index for all of the given websites
# Ben Dowling - www.coderholic.com

# Change this to whatever sites you're interested in
websites="www.yahoo.com www.google.com www.twitter.com"

if [ "$1" = "autoconf" ]; then
        echo yes
        exit 0
fi

if [ "$1" = "config" ]; then

        echo 'graph_title Number of Pages in Google Index'
        echo 'graph_args --base 1000 -l 0 '
        echo 'graph_vlabel number of pages'
        echo 'graph_category google'
        echo 'graph_info This graph shows the number of pages in the Google index for a given website.'

        i=0
        for site in $websites
        do
                name="site_${i}"
                echo "${name}.label ${site}"
                echo "${name}.draw LINE2"
                echo "${name}.info The number of pages in the google index."
                i=$((i+1))
        done
        exit 0
fi

i=0
for site in $websites
do
        name="site_${i}"
		value=$(wget -q --user-agent=Firefox -O - "http://www.google.com/search?q=site:${site}" | grep -E "of about <b>[0-9,]+</b>" -o | grep -E "[0-9,]+" -o | sed "s/,//g")
        echo "${name}.value ${value}"

        i=$((i+1))
done
</pre>
<p>For more details about Munin see their <a href="http://munin.projects.linpro.no/">homepage</a>, which also includes detailed documentation on writing your own plugins. </p>
<p>Let me know if you can think of any more Munin plugins that could be interesting, or if you&#8217;ve used any yourself!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/server-monitoring-with-munin/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>MySQL table size reporting script</title>
		<link>http://www.coderholic.com/mysql-table-size-reporting-script/</link>
		<comments>http://www.coderholic.com/mysql-table-size-reporting-script/#comments</comments>
		<pubDate>Tue, 29 Sep 2009 07:40:04 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[scripts]]></category>

		<guid isPermaLink="false">http://www.coderholic.com/?p=330</guid>
		<description><![CDATA[I&#8217;ve written a small shell script to report how much disk space each table in a given MySQL database is using. For example, below is the output of the script when run against this site&#8217;s database: bmd /~: ./dbSize.sh coderholic root ******** wp_comments Data: 6.60MB Indexes: .15MB Total: 6.75MB wp_links Data: 0MB Indexes: 0MB Total: [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve written a small shell script to report how much disk space each table in a given MySQL database is using. For example, below is the output of the script when run against this site&#8217;s database:</p>
<pre>
bmd /~: ./dbSize.sh coderholic root ********
wp_comments Data: 6.60MB Indexes: .15MB Total: 6.75MB
wp_links Data: 0MB Indexes: 0MB Total: 0MB
wp_options Data: 1.57MB Indexes: .01MB Total: 1.58MB
wp_postmeta Data: .01MB Indexes: .01MB Total: .02MB
wp_posts Data: .57MB Indexes: .02MB Total: .60MB
wp_term_relationships Data: 0MB Indexes: .01MB Total: .02MB
wp_term_taxonomy Data: 0MB Indexes: 0MB Total: 0MB
wp_terms Data: 0MB Indexes: 0MB Total: 0MB
wp_tla_data Data: 0MB Indexes: 0MB Total: 0MB
wp_tla_rss_map Data: 0MB Indexes: 0MB Total: 0MB
wp_usermeta Data: 0MB Indexes: 0MB Total: 0MB
wp_users Data: 0MB Indexes: 0MB Total: 0MB
*** 12 Tables | Data: 8.78MB Indexes: .25MB Total: 9.03MB ***
</pre>
<p>With a few small modifications I&#8217;m sure it&#8217;d be possible to get the script working PostgreSQL or other RDBMSes. The full code is below:</p>
<pre name="code" class="python">
#!/bin/bash
# Calculate the storage space used up by all tables in a given MySQL database
# Ben Dowling - www.coderholic.com
database=$1
username=$2
password=$3

if [ ${#database} -eq 0 ]
then
	echo "Usage: $0 &lt;database&gt; [username [password]]"
	exit
fi

if [ "$password" ]
then
   password="-p$password"
fi

mysql="mysql -u $username $password $database"

$mysql -se "USE $database";

tables=$($mysql -se "SHOW TABLES")

totalData=0
totalIndex=0
totalTables=0

for table in $tables
do
   output=$($mysql -se "SHOW TABLE STATUS LIKE \"$table\"\G")
   data=$(echo "$output" | grep Data_length | awk -F': ' '{print $2}')
   dataMegs=$(echo "scale=2;$data/1048576" | bc)
   index=$(echo "$output" | grep Index_length | awk -F': ' '{print $2}')
   indexMegs=$(echo "scale=2;$index/1048576" | bc)
   total=$(($index+$data))
   totalMegs=$(echo "scale=2;$total/1048576" | bc)

   echo "$table Data: ${dataMegs}MB Indexes: ${indexMegs}MB Total: ${totalMegs}MB"

   totalData=$(($totalData+$data))
   totalIndex=$(($totalIndex+$index))
   totalTables=$(($totalTables+1))
done

dataMegs=$(echo "scale=2;$totalData/1048576" | bc)
indexMegs=$(echo "scale=2;$totalIndex/1048576" | bc)
total=$(($totalIndex+$totalData))
totalMegs=$(echo "scale=2;$total/1048576" | bc)

echo "*** $totalTables Tables | Data: ${dataMegs}MB Indexes: ${indexMegs}MB Total: ${totalMegs}MB ***"
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/mysql-table-size-reporting-script/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>linewatch &#8211; an alternative to linux&#8217;s watch</title>
		<link>http://www.coderholic.com/linewatch-an-alternative-to-linuxs-watch/</link>
		<comments>http://www.coderholic.com/linewatch-an-alternative-to-linuxs-watch/#comments</comments>
		<pubDate>Sat, 18 Jul 2009 20:11:23 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[scripts]]></category>

		<guid isPermaLink="false">http://www.coderholic.com/?p=290</guid>
		<description><![CDATA[I often use the linux watch command to monitor the status of certain commands. When I&#8217;m copying lots of files say, I&#8217;d watch the files in the target directory to see what files have already been copied across with the following command: watch ls -l The watch program clears the screen and displays the output [...]]]></description>
			<content:encoded><![CDATA[<p>I often use the linux <a href="http://linux.die.net/man/1/watch">watch</a> command to monitor the status of certain commands. When I&#8217;m copying lots of files say, I&#8217;d watch the files in the target directory to see what files have already been copied across with the following command:</p>
<pre>
watch ls -l
</pre>
<p>The watch program clears the screen and displays the output of &#8220;ls -l&#8221; every 2 seconds. </p>
<p>Sometimes I&#8217;ll want to monitor a command that only outputs a single line. If I wanted to see the total number of files in a directory rather than the files themselves I could use the command &#8220;ls -l | wc -l&#8221;. The fact that watch clears the whole screen can be a little annoying here though, because the command is only outputting a single line. That is why I came up with the following small bash script, linewatch. </p>
<p>Linewatch repeatedly calls any arguments passed to it every 2 seconds (in the same way watch does), but only clears a single line rather than the whole screen. Here is the code:</p>
<pre name="code" class="python">
#!/bin/bash
clearline="\b\033[2K\r"
command=$@

while true
do
    eval "$command"
    sleep 2
    echo -n -e "$clearline"
done
</pre>
<p>And here is an example of how to call it:</p>
<pre>
$ ./linewatch "ls -l | wc -l"
24
</pre>
<p>The number of files in the current directory (24 in the example) will keep update every 2 seconds. Just hit Ctrl-C when you want to quit,</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/linewatch-an-alternative-to-linuxs-watch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SVN Change Monitoring Script</title>
		<link>http://www.coderholic.com/svn-change-monitoring-script/</link>
		<comments>http://www.coderholic.com/svn-change-monitoring-script/#comments</comments>
		<pubDate>Thu, 02 Jul 2009 19:56:00 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[scripts]]></category>

		<guid isPermaLink="false">http://www.coderholic.com/?p=280</guid>
		<description><![CDATA[I came up with the following shell script recently to monitor code changes in a subversion repository. On the first run it will emails out the 10 most recent changes. After that the script mails out all changes since the last time it was run. You can set it up to run as a daily [...]]]></description>
			<content:encoded><![CDATA[<p>I came up with the following shell script recently to monitor code changes in a subversion repository. On the first run it will emails out the 10 most recent changes. After that the script mails out all changes since the last time it was run. You can set it up to run as a daily cron job which mails you all changes made to you favourite open source project!</p>
<p>It wouldn&#8217;t take much to get it working with other version control systems such as Git or Bazaar, or to do some nice formatting of the output instead of outputting the raw svn log as-is. Let me know if you find it useful!</p>
<pre name="code" class="python">
#!/bin/bash
# Shell script to email the latest changes in an SVN
# repsitory to a specified email address.
# Ben Dowling - wwww.coderholic.com

svnUrl="http://anonsvn.wireshark.org/wireshark/trunk/"
lastRevisionFile="./.last-revision"
mailto="ben@coderholic.com"

function getCurrentRevision {
  # Get the current SVN revision, eg. "r4670"
  currentRevision=$(svn log "$svnUrl" -r HEAD 2&gt;/dev/null | head -n2 | grep -v -- "-------" | awk '{ print $1 }')
  # Strip off the 'r'
  currentRevision="${currentRevision:1}"
  echo "$currentRevision"
}

currentRevision=$(getCurrentRevision)

# If we've run this program before then we've stored the SVN revision at the time
if [ -f "$lastRevisionFile" ]
then
  lastRevision=$(cat "$lastRevisionFile")
  #  Check what the current revision is, and exit if there
  # haven't been any changes since we last checked
  if [ $currentRevision -lt $lastRevision ]
  then
      echo "No changes since last check"
      exit
  fi
else
  # We haven't run this program before, so set the last revision to the current revision - 10
  lastRevision=$(echo "$currentRevision - 10" | bc)
fi

# Mail the SVN changes
svn log "$svnUrl" -r "HEAD:${lastRevision}" | mail -s "SVN changes for $svnUrl" $mailto

# Store the current revision + 1 as the last revision
revision=$(echo "$currentRevision + 1" | bc)
echo "$revision" &gt; "$lastRevisionFile"
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/svn-change-monitoring-script/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP Error Log Mail Script</title>
		<link>http://www.coderholic.com/php-error-log-mailscript/</link>
		<comments>http://www.coderholic.com/php-error-log-mailscript/#comments</comments>
		<pubDate>Tue, 26 May 2009 19:26:40 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[scripts]]></category>

		<guid isPermaLink="false">http://www.coderholic.com/?p=249</guid>
		<description><![CDATA[With the configuration option &#8220;log_errors&#8221; PHP will log all errors to the Apache error log file, allowing you to see all of the errors that have occurred while people have been using your site. Given the snippet of code below: &#60;?php // Ensure logging is enabled. Ideally this will be set in php.ini ini_set('log_errors', 'On'); [...]]]></description>
			<content:encoded><![CDATA[<p>With the configuration option &#8220;log_errors&#8221; PHP will log all errors to the Apache error log file, allowing you to see all of the errors that have occurred while people have been using your site. Given the snippet of code below:</p>
<pre name="code" class="php">
&lt;?php
	// Ensure logging is enabled. Ideally this will be set in php.ini
	ini_set('log_errors', 'On');
	// Call a non-existant function to generate an error
	doesNotExist();
?&gt;
</pre>
<p>You&#8217;ll see something like the following entry in the error log, which includes a description of the problem and the file and line number of where the problem occurred:</p>
<p><code><br />
[Tue May 26 19:54:53 2009] [error] [client 127.0.0.1] PHP Fatal error:  Call to undefined function doesNotExist() in /var/www/index.php on line 6<br />
</code></p>
<p>I&#8217;ve written a small bash script to mail me all of the PHP errors that it finds in the log. The results are sorted and piped through the &#8220;uniq&#8221; command to remove any duplicate errors. I&#8217;ve set it up to run as a cron task once a day, so if there are ever any problems it isn&#8217;t long before I know about them. The code is below:</p>
<pre name="code" class="python">
#!/bin/bash
# Mail out PHP errors that are in the apache error log.
# Note PHP's log_errors must be turned on
# Ben Dowling - www.coderholic.com

errorLog=/var/log/apache2/error.log # Error log location
email=you-email-address@example.com # Send report here

# Pull out the lines that mention PHP, and use AWK to get the column we're interested in
errors=$(cat $errorLog | grep PHP | awk -F'] ' '{print $4}')
# Remove referer information, sort, and remove duplicate entries
errors=$(echo "$errors" | awk -F', referer' '{print $1}' | sort | uniq)
# Check that we actually have some errors
if [ -n "$errors" ]
then
	echo "$errors" | mail "$email" -s "PHP Errors"
fi
</pre>
<p>If you need to it should be quite easy to modify the script for a slightly different use, such as printing out all the fatal PHP errors that are in the log. </p>
<p>Hope you find it useful!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/php-error-log-mailscript/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>AVI to DVD Shell Script</title>
		<link>http://www.coderholic.com/avi-to-dvd-shell-script/</link>
		<comments>http://www.coderholic.com/avi-to-dvd-shell-script/#comments</comments>
		<pubDate>Mon, 19 Jan 2009 19:09:46 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[scripts]]></category>

		<guid isPermaLink="false">http://www.coderholic.com/?p=107</guid>
		<description><![CDATA[Inspired by a movable tripe blog post I came up with the following shell script to convert an AVI file to an ISO image that can be burned to disc and played back on a standard DVD player. The script requires mencoder, ffmpeg, dvdauthor and mkisofs, and will let you know you if any of [...]]]></description>
			<content:encoded><![CDATA[<p>Inspired by a <a href="http://movabletripe.com/archive/merging-avis-into-a-single-dvd-on-linux/">movable tripe blog post</a> I came up with the following shell script to convert an AVI file to an ISO image that can be burned to disc and played back on a standard DVD player.</p>
<p>The script requires mencoder, ffmpeg, dvdauthor and mkisofs, and will let you know you if any of these are missing. Use it like follows:</p>
<blockquote><p>./dvd.sh input.avi</p></blockquote>
<p>Once the script has finished a &#8220;dvd.iso&#8221; file will be created, which can then be burned to DVD using your favourite disc burning tool.</p>
<pre class="php" name="code">
#!/bin/bash
# AVI to DVD Script
# Ben Dowling - www.coderholic.com

# Change to "ntsc" if you'd like to create NTSC disks
format="pal"

# Check we have enough command line arguments
if [ $# != 1 ]
then
	echo "Usage: $0 &lt;input file&gt;"
	exit
fi

# Check for dependencies
missing=0
dependencies=( "mencoder" "ffmpeg" "dvdauthor" "mkisofs" )
for command in ${dependencies[@]}
do
	if ! command -v $command &#038;>/dev/null
	then
		echo "$command not found"
		missing=1
	fi
done

if [ $missing = 1 ]
then
	echo "Please install the missing applications and try again"
	exit
fi

function emphasise() {
	echo ""
	echo "********** $1 **********"
	echo ""
}

# Check the file exists
input_file=$1
if [ ! -e $input_file ]
then
	echo "Input file not found"
	exit
fi

emphasise "Converting AVI to MPG"

ffmpeg -i finalmovie.avi -y -target ${format}-dvd -sameq -aspect 16:9 finalmovie.mpg

if [ $? != 0 ]
then
	emphasise "Conversion failed"
	exit
fi

emphasise "Creating DVD contents"

dvdauthor --title -o dvd -f finalmovie.mpg
first=$?
dvdauthor -o dvd -T
second=$?

if [ $first != 0 || $second != 0 ]
then
	emphasise "DVD Creation failed"
	exit
fi

emphasise "Creating ISO image"

mkisofs -dvd-video -o dvd.iso dvd/

if [ $? != 0 ]
then
	emphasise "ISO Creation failed"
	exit
fi

# Everything passed. Cleanup
rm -f finalmovie.mpg
rm -rf dvd/

emphasise "Success: dvd.iso image created"
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.coderholic.com/avi-to-dvd-shell-script/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
