<?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>Death of a Gremmie</title>
	<atom:link href="http://deathofagremmie.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://deathofagremmie.com</link>
	<description>by Brian Neal</description>
	<lastBuildDate>Sat, 23 Jan 2010 01:16:22 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Testing Your First Django App</title>
		<link>http://deathofagremmie.com/2010/01/22/testing-your-first-django-app/</link>
		<comments>http://deathofagremmie.com/2010/01/22/testing-your-first-django-app/#comments</comments>
		<pubDate>Sat, 23 Jan 2010 01:16:22 +0000</pubDate>
		<dc:creator>gremmie</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[unittest]]></category>

		<guid isPermaLink="false">http://deathofagremmie.com/?p=337</guid>
		<description><![CDATA[Dougal Matthews wrote a great blog post entitled &#8220;Testing Your First Django App&#8220;. This is something that I have been meaning to do for a long time now, but didn&#8217;t know how to get started. Much to my surprise (I guess I shouldn&#8217;t be), Python supports the xUnit style of testing via the standard library [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://dougalmatthews.com/">Dougal Matthews</a> wrote a great blog post entitled &#8220;<a href="http://dougalmatthews.com/articles/2010/jan/20/testing-your-first-django-app/">Testing Your First Django App</a>&#8220;. This is something that I have been meaning to do for a long time now, but didn&#8217;t know how to get started. Much to my surprise (I guess I shouldn&#8217;t be), Python supports the <a href="http://en.wikipedia.org/wiki/XUnit">xUnit</a> style of testing via the standard library package <a href="http://docs.python.org/library/unittest.html">unittest</a>. Since we are now using <a href="http://cxxtest.tigris.org/">CxxTest</a> at work, this is quite familiar to me now. Dougal&#8217;s blog entry shows some nice ways of testing Django web applications without using a server by mocking up requests and examining responses from your view functions. Very cool!</p>
]]></content:encoded>
			<wfw:commentRss>http://deathofagremmie.com/2010/01/22/testing-your-first-django-app/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python and SSH</title>
		<link>http://deathofagremmie.com/2009/12/31/python-and-ssh/</link>
		<comments>http://deathofagremmie.com/2009/12/31/python-and-ssh/#comments</comments>
		<pubDate>Fri, 01 Jan 2010 04:26:15 +0000</pubDate>
		<dc:creator>gremmie</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[cygwin]]></category>
		<category><![CDATA[paramiko]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[sftp]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[webcam]]></category>

		<guid isPermaLink="false">http://deathofagremmie.com/?p=332</guid>
		<description><![CDATA[I was fooling around with my webcam, and I got to wondering if I could write a small Python script to upload a snapshot to my webserver periodically. Since I was planning on uploading a new snapshot every ten minutes or so, I&#8217;d rather use SFTP to avoid sending my login and password unencrypted so [...]]]></description>
			<content:encoded><![CDATA[<p>I was fooling around with my webcam, and I got to wondering if I could write a small Python script to upload a snapshot to my webserver periodically. Since I was planning on uploading a new snapshot every ten minutes or so, I&#8217;d rather use <a href="http://en.wikipedia.org/wiki/SSH_file_transfer_protocol">SFTP</a> to avoid sending my login and password unencrypted so frequently. I had already <a href="http://deathofagremmie.com/tag/ftplib/">used FTP in Python</a> before in a backup script, but I didn&#8217;t know if the Python standard library had a solution for SSH. After a bit of Googling, I discovered the 3<sup>rd</sup> party Python module <a href="http://www.lag.net/paramiko/">Paramiko</a> (the name is a combination of the Esperanto words for    &#8220;paranoid&#8221; and &#8220;friend&#8221; &#8212; I love that), which allows you to do all kinds of SSH2 operations, including SFTP. Paramiko is extremely <a href="http://www.lag.net/paramiko/docs/">well documented</a> (thank-you!) and I had no problems at all using it to accomplish my task. I also found this <a href="http://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely-different/">great introductory article</a> by Python core developer <a href="http://jessenoller.com/">Jesse Noller</a> that was helpful in getting up to speed on it quickly.</p>
<p>Since I was using my webcam from Windows XP, I decided to write my script under the new 1.7.1 version of <a href="http://cygwin.com">Cygwin</a> that came out recently. You&#8217;ll need to get both the Paramiko package and the python-crypto package.</p>
<p>Happy New Year everyone!</p>
]]></content:encoded>
			<wfw:commentRss>http://deathofagremmie.com/2009/12/31/python-and-ssh/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SG101 2.0 Status Report</title>
		<link>http://deathofagremmie.com/2009/12/20/sg101-2-0-status-report/</link>
		<comments>http://deathofagremmie.com/2009/12/20/sg101-2-0-status-report/#comments</comments>
		<pubDate>Mon, 21 Dec 2009 03:30:34 +0000</pubDate>
		<dc:creator>gremmie</dc:creator>
				<category><![CDATA[SG101 2.0]]></category>
		<category><![CDATA[forums]]></category>
		<category><![CDATA[status]]></category>

		<guid isPermaLink="false">http://deathofagremmie.com/?p=328</guid>
		<description><![CDATA[This is the obligatory &#8220;why haven&#8217;t you been blogging about your project in a while&#8221; post. Yes, I suppose it is time to give a quick update.
Things slowed down dramatically on SG101 2.0 this summer. There was the 2009 SG101 convention vacation and other fun summer things to distract me. I had put up a [...]]]></description>
			<content:encoded><![CDATA[<p>This is the obligatory &#8220;why haven&#8217;t you been blogging about your project in a while&#8221; post. Yes, I suppose it is time to give a quick update.</p>
<p>Things slowed down dramatically on SG101 2.0 this summer. There was the 2009 SG101 convention vacation and other fun summer things to distract me. I had put up a beta site for feedback but was still missing a forums application. I got the itch to start back up again sometime in the Fall. I decided to start on a forums application myself and to see how it went. If it was too complicated I would look for a third-party solution.</p>
<p>This is one case where I did look at several third-party applications for ideas and to check on their status. There doesn&#8217;t seem to be a single recognized forums application in Django-land. There are a number of them, and they range from very simple to moderately complex. Many of them seem unsupported and have obvious problems. So in the end, I decided that since the forums are probably the most important part of my site, it would be best if I wrote it myself so that I could understand it completely. This includes both strengths and weaknesses. I did borrow many ideas from existing applications, and some of my initial momentum came from <a href="http://www.djangobb.org/">djangobb</a>. However, I quickly stopped looking at other apps because <a href="http://djangoproject.com/">Django</a> really makes it easy to write complex web applications once you get an idea and try a few things.</p>
<p>My forum app contains most of the functionality of the venerable <a href="http://www.phpbb.com/">phpBB</a>-based board I have now. I added a few things like the ability for users to flag posts as spam or abuse (I sure wish I had that now). I am considering making the first few posts of a user require approval to counter spam. But I&#8217;m not sure it is worth the effort with the &#8220;flag post&#8221; feature in-place. I might just wait and see how well that works.</p>
<p>I also decided to save a user&#8217;s post read and unread status in the database, instead of using cookies. Too many of my existing users complain that when their cookies expire they lose track of which threads are new. It will cost some database space, no doubt, but it is an often requested feature to fix this issue. I implemented a rolling 7-day window of thread and post read status, and in initial tests it seems to work just fine. It did add significant complexity to the design however, and I&#8217;m not looking forward to debugging that logic when a problem occurs.</p>
<p>After finishing the forums, I began working on my lengthy to-do list using my <a href="http://trac.edgewall.org/">Trac</a> issue tracker. I also spent a great deal of time refactoring some of my original code that I wrote over a year ago. I&#8217;ve become so much more proficient with <a href="http://python.org/">Python</a> and <a href="http://jquery.com/">jQuery</a> it is inevitable. My task list has become quite small and I am thinking about wiping the existing beta site and putting up a new one over holiday break and launching an official beta test.</p>
<p>The one area that I am lacking in right now is a good design and layout. A few users have volunteered to help with that, and one in particular is showing me some really nice work. If I can just manage to implement his design we may be on to something. I may also try to reach out to someone who is familiar with Django.</p>
<p>There are a couple of interesting problems I either solved or worked around during this period that I should blog about. I&#8217;ll just have to find the time to do that. In particular, I wanted to share how I created an admin dashboard for user-created content that needs admin approval before being published.</p>
<p>I&#8217;ve also volunteered to give a &#8220;brown-bag&#8221; lunchtime talk at my employer on Python. I&#8217;ll have to prepare some slides over the holiday break for this.</p>
]]></content:encoded>
			<wfw:commentRss>http://deathofagremmie.com/2009/12/20/sg101-2-0-status-report/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Python Subprocess Popen and Windows</title>
		<link>http://deathofagremmie.com/2009/12/13/python-subprocess-popen-and-windows/</link>
		<comments>http://deathofagremmie.com/2009/12/13/python-subprocess-popen-and-windows/#comments</comments>
		<pubDate>Sun, 13 Dec 2009 22:28:57 +0000</pubDate>
		<dc:creator>gremmie</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[subprocess]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://deathofagremmie.com/?p=322</guid>
		<description><![CDATA[I was writing a Python script to automate some Subversion-related tasks at work last week on Windows. The Python code was calling the Subversion command-line client applications using the Python subprocess module. I don&#8217;t know why exactly, but I had passed in the parameter shell=True to the subprocess.Popen function. I probably did this because I [...]]]></description>
			<content:encoded><![CDATA[<p>I was writing a Python script to automate some Subversion-related tasks at work last week on Windows. The Python code was calling the Subversion command-line client applications using the Python <a href="http://docs.python.org/library/subprocess.html">subprocess module</a>. I don&#8217;t know why exactly, but I had passed in the parameter shell=True to the subprocess.Popen function. I probably did this because I saw a lot of examples on the web, and you know, monkey-see, monkey-do. In hindsight, these examples were probably for Unix. It turned out that this caused a lot of problems. The Subversion clients started complaining when handed filenames that contained &#8220;special&#8221; characters like ampersands. And when they got to the files that had <strong>both</strong> ampersands and spaces, all kinds of crazy errors were produced. I was pulling my hair out, trying to escape the special characters and/or use quotes around the filename, but I could not come up with a combination that would work for all the different filenames the script encountered. Finally, as I stared at the code, I somehow got the idea to try switching that shell=True to shell=False.  Suddenly, everything worked perfectly. I undid all the escaping and quoting and everything worked as expected.</p>
<p>So I&#8217;m not sure what shell=True does on Windows, and it certainly isn&#8217;t documented. I do not recommend using it unless you know what is happening  in the implementation. Interestingly, shell=False is the default. I should have left it that way. <img src='http://deathofagremmie.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://deathofagremmie.com/2009/12/13/python-subprocess-popen-and-windows/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using the Python Shell in Vi Mode</title>
		<link>http://deathofagremmie.com/2009/11/30/using-the-python-shell-in-vi-mode/</link>
		<comments>http://deathofagremmie.com/2009/11/30/using-the-python-shell-in-vi-mode/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 01:18:53 +0000</pubDate>
		<dc:creator>gremmie</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[readline]]></category>
		<category><![CDATA[vi]]></category>

		<guid isPermaLink="false">http://deathofagremmie.com/?p=319</guid>
		<description><![CDATA[The Python shell is an invaluable tool for trying things out and experimenting with the language. Wouldn&#8217;t it be great if you could use the Python shell in Vi mode? Much to my surprise, it turns out you can.
Python leverages the GNU Readline Library in its shell code. The Readline library is used in a [...]]]></description>
			<content:encoded><![CDATA[<p>The Python shell is an invaluable tool for trying things out and experimenting with the language. Wouldn&#8217;t it be great if you could use the Python shell in Vi mode? Much to my surprise, it turns out you can.</p>
<p>Python leverages the <a href="http://tiswww.case.edu/php/chet/readline/rltop.html">GNU Readline Library</a> in its shell code. The Readline library is used in a number of open source projects, notably the <a href="http://www.gnu.org/software/bash/bash.html">BASH shell</a>. The Readline library looks for a configuration file at startup in a number of places. On Unix-like operating systems, the configuration file can be found at <code>~/.inputrc</code> and falls back to <code>/etc/inputrc</code>.</p>
<p>One line is all you need in your <code>~/.inputrc</code> file:</p>
<pre>set editing-mode vi</pre>
<p>Unfortunately I don&#8217;t know how to make this work under Windows.</p>
]]></content:encoded>
			<wfw:commentRss>http://deathofagremmie.com/2009/11/30/using-the-python-shell-in-vi-mode/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Vim: Different Settings For Different File Types</title>
		<link>http://deathofagremmie.com/2009/11/18/vim-different-settings-for-different-file-types/</link>
		<comments>http://deathofagremmie.com/2009/11/18/vim-different-settings-for-different-file-types/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 18:56:22 +0000</pubDate>
		<dc:creator>gremmie</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://deathofagremmie.com/?p=315</guid>
		<description><![CDATA[Old habits die hard. I have been using 3 space indents for C and C++ code for as long as I have been a programmer. A little over a year ago I dove head-first into Python, and eventually discovered PEP 8. PEP 8 is basically the style guide for the Python community. I read it [...]]]></description>
			<content:encoded><![CDATA[<p>Old habits die hard. I have been using 3 space indents for C and C++ code for as long as I have been a programmer. A little over a year ago I dove head-first into Python, and eventually discovered <a title="PEP 8" href="http://www.python.org/dev/peps/pep-0008/">PEP 8</a>. PEP 8 is basically the style guide for the Python community. I read it with great interest and took just about everything to heart, except for the recommended 4-space indents. I just could not shake my old habit.</p>
<p>Eventually as I got more and more excited about Python I decided to wholly embrace the customs of the community. But how could I easily tell my favorite editor <a title="Vim" href="http://www.vim.org/">Vim</a> to use 4-space indents for just Python code? I still do a lot of C++ at work, and I still like 3-space indents in other file types.</p>
<p>My first attempt was to use a Vim modeline embedded right in my source files. At the bottom of my Python files I placed this line:</p>
<pre># vim: set sw=4 ts=4:</pre>
<p>When Vim first opens a file, it scans the first and last few lines in the file, looking for modelines, and will use the settings just for that file.</p>
<p>This obviously worked, but soon I found it ugly and distracting to have that at the bottom of each file. And sometimes I would forget to put it there, and not realize it until a bunch of code had been written.</p>
<p>It turns out there is a far easier way, but it took some digging to discover. Vim has a very elaborate system of determing file types. If you peek into your Vim installation directory, you&#8217;ll see a ftplugin directory. This directory is full of little files that get executed once the type of a file has been determined. Some people on the Web suggest that you should modify these files directly. Thus I could modify the ftplugin/python.vim file, and place my tabstop and shiftwidth settings in there. But you would be modifying a Vim file, and your changes would get lost the next time you upgrade Vim.</p>
<p>There is a much better solution. After Vim executes the python.vim file in the ftplugins directory, it looks for a file called ~/.vim/after/ftplugin/python.vim (on Unix; on Windows I&#8217;ve had luck with C:\Progam Files\Vim\vimfiles\after\ftplugin\python.vim). If this file exists, it will be executed after the &#8220;official&#8221; python.vim file.</p>
<p>Inside your personal python.vim file, the documentation says to use the &#8220;setlocal&#8221; instead of &#8220;set&#8221; command. Thus, my file looks like:</p>
<pre style="text-align: left;">setlocal tabstop=4
setlocal shiftwidth=4</pre>
<p style="text-align: left;">Although to be honest, I&#8217;ve used the regular set for some time (by accident) without seeing any strange effects.</p>
<p style="text-align: left;">Happy Vimming!</p>
]]></content:encoded>
			<wfw:commentRss>http://deathofagremmie.com/2009/11/18/vim-different-settings-for-different-file-types/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>I </title>
		<link>http://deathofagremmie.com/2009/09/24/i-heart-vim/</link>
		<comments>http://deathofagremmie.com/2009/09/24/i-heart-vim/#comments</comments>
		<pubDate>Fri, 25 Sep 2009 00:15:23 +0000</pubDate>
		<dc:creator>gremmie</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://deathofagremmie.com/?p=310</guid>
		<description><![CDATA[I love the text editor Vim. I started using Vi because I really didn&#8217;t know any better around 1988 when I was first teaching myself C on my trusty Amiga 500. Not long after that I discovered Vim which sported many improvements over the venerable Vi. Sometime around 1993-1994 I started hacking Vim. I added [...]]]></description>
			<content:encoded><![CDATA[<p>I love the text editor <a href="http://vim.org">Vim</a>. I started using Vi because I really didn&#8217;t know any better around 1988 when I was first teaching myself C on my trusty Amiga 500. Not long after that I discovered Vim which sported many improvements over the venerable Vi. Sometime around 1993-1994 I started hacking Vim. I added a complete <a href="http://en.wikipedia.org/wiki/ARexx">ARexx</a> port to Vim so that you could script it. Alas, a new version of Vim came out right after I finished, and author <a href="http://www.moolenaar.net/">Bram Moolenaar</a> had changed the code so much I felt it was impossible to merge my changes into the new version. This was when I was a young pup programmer, and I was unfamiliar with revision control and difference/merging tools. I had fun doing it anyway, so I just chalked it up to experience.</p>
<p>I have used Vim on every programming task at every job I&#8217;ve had. I&#8217;m constantly learning new things about it, and the commands and keystrokes are now part of my DNA. I don&#8217;t even think how to execute commands anymore and I am often hard pressed to recall them to others learning Vim. I have to sit at a keyboard with Vim running in order to understand what my fingers are doing.</p>
<p>A while back, I discovered the auto-complete feature, where you type Ctrl-n in insert mode and Vim will attempt to complete the word you are typing based on all the words in all buffers and how frequently they occur. This is incredibly handy when programming to quickly pound out those function and variable names. I used &#8220;imap &lt;S-Tab&gt; &lt;C-n&gt;&#8221; in my .vimrc file to map this to shift-tab, which I felt was more convenient.</p>
<p>I also picked up a really handy way to <a href="http://vim.wikia.com/wiki/Cycle_through_buffers_including_hidden_buffers">cycle through all your buffers</a>.  I used the tab and shift-tab mapping mentioned in that Vim tip. Combine that with Vim&#8217;s tab feature I can very easily find the file I am looking for.</p>
<p>And finally I had another big &#8220;wow, Vim can do that?&#8221; moment just last week. Since version 7, Vim has sported an &#8220;omni-complete&#8221; framework. Basically it is an architecture for people to hang code completion routines into Vim. In fact, right out of the box, Vim 7 has support for Javascript, CSS, and yes, even Python! Python completion is only available if you are using a version of Vim that has been compiled with Python support (e.g. on Ubuntu). Imagine my shock when I was editing a CSS file and I typed &#8220;display:&#8221; and then hit Ctrl-X Ctrl-O for the first time and a drop down list of all the possible values (inline, block, none, etc) appeared! No more hunting for that w3schools website. And the Python support is just as handy. Type &#8220;os.path.&#8221; followed by Ctrl-X Ctrl-O and you can see all the entities and function in the os.path module. I had no idea!</p>
<p>So all of this reminds me it is time to once again donate to the Vim project. Thanks Bram for all your amazing work you do on this invaluable tool.</p>
<p>P.S. I have no interest in the great editor holy war. Use a tool that you find intuitive and useful and learn it, back to front. I&#8217;m sure there is nothing wrong with other popular editors. But for me, Vim is it. I can&#8217;t imagine how many hours of productivity it has given me over the years.</p>
]]></content:encoded>
			<wfw:commentRss>http://deathofagremmie.com/2009/09/24/i-heart-vim/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Server Monitoring with Munin</title>
		<link>http://deathofagremmie.com/2009/09/19/server-monitoring-with-munin/</link>
		<comments>http://deathofagremmie.com/2009/09/19/server-monitoring-with-munin/#comments</comments>
		<pubDate>Sun, 20 Sep 2009 03:53:14 +0000</pubDate>
		<dc:creator>gremmie</dc:creator>
				<category><![CDATA[Server]]></category>
		<category><![CDATA[monitoring]]></category>
		<category><![CDATA[munin]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://deathofagremmie.com/?p=306</guid>
		<description><![CDATA[I finally got around to investigating server monitoring tools, and came across Munin. This tool allows you to monitor various nodes in your network, and it generates pretty graphs for a wide variety of system parameters. You install munin-node software on the machines you wish to monitor. The node software gathers statistics which are collected [...]]]></description>
			<content:encoded><![CDATA[<p>I finally got around to investigating server monitoring tools, and came across <a href="http://munin.projects.linpro.no/">Munin</a>. This tool allows you to monitor various nodes in your network, and it generates pretty graphs for a wide variety of system parameters. You install munin-node software on the machines you wish to monitor. The node software gathers statistics which are collected periodically by a munin master agent, which produces the nice graphs that you can view with a web browser.</p>
<p>Installing it was easy with Ubuntu, as packages already exist for it. It was a simple &#8220;sudo apt-get install munin munin-node.&#8221; The Ubuntu package set me up for running both the master and node software on the same machine. I then had to edit the /etc/munin/munin.conf to change a few paths around, notably where to put the generated HTML files. One hitch that stumped me for a few minutes was a permissions problem on the path to the location of the HTML files. The Ubuntu package creates a new munin user, so make sure all directories on the path to the HTML files have an &#8220;x&#8221; bit for world. Once that was sorted I started seeing data after 5 minutes for a variety of things including CPU load, MySQL statistics, and filesystem usage. Awesome! I decided to put Apache Basic Authorization password protection on the directory where the report files live, as it is sensitive data that I wouldn&#8217;t want just anyone to see.</p>
<p>Below is an example graph, one of about 50 (!) that are available right out of the box. Plugins exist and can be created for a wide variety of other parameters as well. In addition, Munin can notify you by email if parameters get out of range. See the Munin home page for more examples and information.</p>
<div id="attachment_307" class="wp-caption aligncenter" style="width: 514px"><img class="size-full wp-image-307" title="munin-mysql" src="http://deathofagremmie.com/wp-content/uploads/2009/09/munin-mysql.png" alt="Munin MySQL Graph" width="504" height="348" /><p class="wp-caption-text">Munin MySQL Graph</p></div>
<p>Munin looks like a very useful tool to keep an eye on your server. Thanks to the Munin team for this great piece of software!</p>
]]></content:encoded>
			<wfw:commentRss>http://deathofagremmie.com/2009/09/19/server-monitoring-with-munin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django Tip: get_object_or_404() and select_related()</title>
		<link>http://deathofagremmie.com/2009/09/15/get_object_or_404_select_related/</link>
		<comments>http://deathofagremmie.com/2009/09/15/get_object_or_404_select_related/#comments</comments>
		<pubDate>Wed, 16 Sep 2009 00:29:13 +0000</pubDate>
		<dc:creator>gremmie</dc:creator>
				<category><![CDATA[SG101 2.0]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://deathofagremmie.com/?p=301</guid>
		<description><![CDATA[I was looking at the SQL my views were generating, and I came across a couple of places where I was using get_object_or_404(), and then later following some foreign keys in the returned object. Something like this:


forum = get_object_or_404(Forum, slug=slug)
if not forum.category.can_access(request.user):
     return HttpResponseForbidden()


The problem is that two SQL queries occur here, one during the [...]]]></description>
			<content:encoded><![CDATA[<p>I was looking at the SQL my views were generating, and I came across a couple of places where I was using get_object_or_404(), and then later following some foreign keys in the returned object. Something like this:</p>
<pre>
<pre class="brush: python">
forum = get_object_or_404(Forum, slug=slug)
if not forum.category.can_access(request.user):
     return HttpResponseForbidden()
</pre>
</pre>
<p>The problem is that two SQL queries occur here, one during the get_object_or_404(), and then another in the following if statement, when we access category, a foreign key on the forum object. It would sure be nice to somehow use a select_related() there to avoid the extra SQL query. I did some googling, and found a quick tip on one of the <a href="http://michaeltrier.com/2008/3/31/this-week-in-django-16-2008-03-30">This Week in Django podcast pages</a>. And yes, <a href="http://docs.djangoproject.com/en/dev/topics/http/shortcuts/#get-object-or-404">the documentation</a> confirmed that get_object_or_404() can now take as a first argument either a model, a manager, or a queryset!</p>
<p>So now you can keep using the handy get_object_or_404() idiom, and reduce the number of queries with a slight bit of refactoring:</p>
<pre>
<pre class="brush: python">
forum = get_object_or_404(Forum.objects.select_related(), slug=slug)
if not forum.category.can_access(request.user):
     return HttpResponseForbidden()
</pre>
</pre>
<p>Very cool!</p>
]]></content:encoded>
			<wfw:commentRss>http://deathofagremmie.com/2009/09/15/get_object_or_404_select_related/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Denyhosts: SSH Brute Force Protection</title>
		<link>http://deathofagremmie.com/2009/09/04/denyhosts-ssh-brute-force-protection/</link>
		<comments>http://deathofagremmie.com/2009/09/04/denyhosts-ssh-brute-force-protection/#comments</comments>
		<pubDate>Sat, 05 Sep 2009 01:09:17 +0000</pubDate>
		<dc:creator>gremmie</dc:creator>
				<category><![CDATA[Server]]></category>
		<category><![CDATA[denyhosts]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[ssh]]></category>

		<guid isPermaLink="false">http://deathofagremmie.com/?p=293</guid>
		<description><![CDATA[I&#8217;m always very uneasy when I look through my web server and system logs. It seems dozens of people (or more!) a month try to log into my server, attempt an SQL injection attack on one or more of my hosted websites, and probe for weaknesses. It really makes me lose some faith in humanity.
I [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m always very uneasy when I look through my web server and system logs. It seems dozens of people (or more!) a month try to log into my server, attempt an SQL injection attack on one or more of my hosted websites, and probe for weaknesses. It really makes me lose some faith in humanity.</p>
<p>I was tipped of to the <a href="http://denyhosts.sourceforge.net/">Denyhosts script</a> via <a href="http://twitter.com/dozba/status/3719492333">a tweet from @dozba</a>. This is nothing more than a Python script that analyzes your ssh log file, looking for suspicious activity. It monitors the number of failed SSH login attempts over time, and once a configurable threshold is reached, it adds the IP address of the remote host to your hosts.deny file, thus blocking the brute-force break-in attempt. The script is very configurable. It can have different thresholds for login attempts to existent or non-existent user accounts, it can purge blocked entries, and it will email you when it blocks a host.</p>
<p>Installation and configuration on Ubuntu is a breeze, as it is available as a package. Use your favorite package manager and install it. Ubuntu automatically configures it to run in daemon mode, so you won&#8217;t need to mess with cron. Configure it by editing the file /etc/denyhosts.conf. Restart the daemon, and then you are done. In a nutshell:</p>
<pre>$ sudo apt-get install denyhosts
$ sudo vi /etc/denyhosts.conf
$ sudo /etc/init.d/denyhosts restart</pre>
<p>Two days after I installed it, I had already blocked 5 break-in attempts. Thanks to the author Phil Schwartz and the Ubuntu package maintainers for this very useful utility!</p>
]]></content:encoded>
			<wfw:commentRss>http://deathofagremmie.com/2009/09/04/denyhosts-ssh-brute-force-protection/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
