<?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"
	>

<channel>
	<title>jonEbird</title>
	<atom:link href="http://jonebird.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://jonebird.com</link>
	<description>Nesting place for this bird's projects</description>
	<pubDate>Mon, 17 Nov 2008 00:14:20 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.2</generator>
	<language>en</language>
			<item>
		<title>Pyworks In Summation</title>
		<link>http://jonebird.com/2008/11/16/pyworks-in-summation/</link>
		<comments>http://jonebird.com/2008/11/16/pyworks-in-summation/#comments</comments>
		<pubDate>Mon, 17 Nov 2008 00:10:18 +0000</pubDate>
		<dc:creator>jonEbird</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[blogging]]></category>

		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://jonebird.com/2008/11/16/73/</guid>
		<description><![CDATA[I sit in the Atlanta Airport reminiscing over the events of PyWorks &#8216;08. This was the first year for PyWorks but MTA combined the conference with PHP Architect and I believe everyone was happy with the combination. At a minimum, people had engaging conversations between the groups and a significant number of them cross-attended the [...]]]></description>
			<content:encoded><![CDATA[<p>I sit in the Atlanta Airport reminiscing over the events of PyWorks &#8216;08. This was the first year for PyWorks but <a title="[MTA]" href="http://mtabini.blogspot.com/" id="x_i7">MTA</a> combined the conference with <a title="PHP Architect" href="http://phparch.com/" id="jucl">PHP Architect</a> and I believe everyone was happy with the combination. At a minimum, people had engaging conversations between the groups and a significant number of them cross-attended the sessions. I attended two PHP sessions and one neutral session and then the rest Python. Some people were a bit disappointed in the lack of Python attendees and it is true that we didn&#8217;t make up a large part of the total 148 attendees of the conference. But with the quality of talks staying superbly high, not having a full room wasn&#8217;t a <i>bad</i> thing. </p>
<p>The quality of talks were all superb, indeed. Probably over half of the presenters are either principle developers on high profile projects or they have written a book or own their own consulting company. On day zero, where there were 3hr long tutorial sessions, I spend the morning in <a title="Mark Ramm" href="http://compoundthinking.com/blog/" id="qx6.">Mark Ramm</a>&#8217;s <a title="TurboGears" href="http://turbogears.org/" id="squs">TurboGears</a> but then I switched over to the PHP side in the afternoon to catch <a title="Scott MacVicar" href="http://www.macvicar.net/" id="ih2.">Scott MacVicar</a> and <a title="Helgi Þormar Þorbjörnsson" href="http://www.helgi.ws/" id="ic:3">Helgi Þormar Þorbjörnsson</a>&#8217;s <a title="Caching for Cash" href="http://pyworks.mtacon.com/c/schedule/speaker/helgi_scott" id="tr80">Caching for Cash</a>.</p>
<p>At the start of day one, the first day of the normal sessions, I think everyone was expecting a lot more people. There were, in fact, more people but not as many as I was expecting, but again that&#8217;s perfectly okay. This day was a full one, starting off with the keynote by <a title="Kevin Dangoor" href="http://www.blueskyonmars.com/" id="xuwc">Kevin Dangoor</a> about <a title="Growing your Community" href="http://pyworks.mtacon.com/c/schedule/talk/d1s1/0" id="cv9y">Growing your Community</a>. After a break I then attended <a title="Decorators are Fun" href="http://blog.tplus1.com/index.php/2008/11/13/slides-for-decorator-talk/" id="yteb">Decorators are Fun</a> by <a title="Matt Wilson" href="http://tplus1.com" id="ef8y">Matt Wilson</a> and learned that he is not that far away from me in Cleveland. Next I attended another Mark Ramm talk about WSGI where he was explaining how easy it was to build a web framework. It was given a bit &#8220;tongue in check&#8221; since he is the primary maintainer of <a title="TurboGears" href="http://turbogears.org/" id="squs">TurboGears</a>. Following that, I attended a middle track session about Distributed version control with GIT by <a title="Travis Wsicegood" href="http://domain51.com/" id="fkxa">Travis Swicegood</a>. Travis had just finished writing a book about using GIT called <a title="Pragmatic Version Control Using Git" href="http://pragprog.com/titles/tsgit/pragmatic-version-control-using-git" id="canc">Pragmatic Version Control Using Git</a> and not surprisingly gave a authoritation explanation of using GIT. Following lunch, I attending another PHP track presentation but it could have been in the neutral middle track. The talk was <a title="Map, Filter, Reduce In the Small and in the Cloud" href="http://sebastian-bergmann.de/talks/" id="y.bz">Map, Filter, Reduce In the Small and in the Cloud</a> by <a title="Sebastian Bergmann" href="http://sebastian-bergmann.de/" id="d6:g">Sebastian Bergmann</a> where he explained the popular functional programming techniques popularized by Google for computing large quantities of data. Sebastian gave me another reason to checkout <a title="Hadoop" href="http://hadoop.apache.org/" id="u8-i">Hadoop</a> and in fact I&#8217;m now thinking of another <a title="Python Magazine" href="http://pymag.phparch.com/" id="cpup">Python Magazine</a> article about using hadoop with <a title="Jython" href="http://www.jython.org/" id="p7lx">Jython</a>. For the last session of the day I decided to attend <a title="Michael Foord" href="http://www.voidspace.org.uk/python/index.shtml" id="t9:o">Michael Foord</a>&#8217;s talk about IronPython. I didn&#8217;t think I&#8217;d ever checkout <a title="IronPython" href="http://www.ironpython.com/" id="bd2v">IronPython</a> on my own, so I thought I&#8217;d get a crash course from Michael who also just finished work on his book <a title="IronPython in Action" href="http://www.ironpythoninaction.com/" id="l7c0">IronPython in Action</a>.</p>
<p>Still not done with day one. After all of the normal presentation&#8217;s concluded, we had happy hour while gearing up for the <a title="Pecha Kucha" href="http://en.wikipedia.org/wiki/Pecha_Kucha" id="ogqu">Pecha Kucha</a> competition sessions. <a title="Pecha Kucha" href="http://en.wikipedia.org/wiki/Pecha_Kucha" id="ogqu">Pecha Kucha</a> is where you provide 20 slides and set them to auto switch every 20 seconds making your session a little over six minutes. Apparently people have found that you can get the same quality bits of information in that format as compared to a full hour session. At least that is what the Japanese have concluded. As for PHP/PyWorks, we mostly had fun with the sessions. There were talks about web security, general ranting, <a title="LOLCode" href="http://en.wikipedia.org/wiki/LOLCODE" id="resv">LOLCode</a>, and many others which I&#8217;m having a problem remembering. At the end, the LOLCode talk took the prize of the Xbox 360 gaming system by our judges and if you&#8217;d really like to see what was going on, you may be able to watch streamed video captured by <a title="Travis Swicegood" href="http://qik.com/tswicegood" id="wexw">Travis Swicegood</a>&#8217;s iPhone. Before I went to bed, I rehearsed my presentation one more time.</p>
<p>By the time day two started, it felt like I had been there a full week and yet we still had a full day of presentations again. I started the morning in <a title="Chris Perkins" href="http://www.percious.com" id="lr4a">Chris Perkins</a>&#8217;s talk about the <a title="Sphinx Documentation System" href="http://sphinx.pocoo.org/" id="hzr1">Sphinx Documentation System</a>. We all understand the importance of documentation and it&#8217;s not always fun, but again I thought investing 45min catching up on some of the Python &#8220;best practices&#8221; for documentation would be well worth the time. Afterwards, I stayed in the same room for <a title="Jacob Taylor" href="http://thejacobtaylor.blogspot.com/" id="oxrl">Jacob Taylor</a>&#8217;s talk about Exploring Artificial Intelligence with Python. Jacob didn&#8217;t get around to showing any Python code but he had good attendance for being a founder of <a title="SugarCRM" href="http://www.sugarcrm.com/" id="sfho">SugarCRM</a>. Next, the highlight of the conference, my presentation about <a title="LDAP and Python" href="http://jonebird.com/pyworks/" id="s9tr">LDAP and Python</a>. The number of attendees for my presentation were average for the Python sessions and by this point I felt like I knew everyone which removed any pressure or nervousness. We&#8217;ll see how interested people were by seeing who downloads my <a title="configparser.py" href="http://jonebird.com/pyworks/configparser2ldap.py" id="x583">configparser.py</a> and/or <a title="ldapconfig.py" href="http://jonebird.com/pyworks/ldapconfig.py" id="mu.0">ldapconfig.py</a> scripts. After lunch, I attended <a title="Kevin Dangoor" href="http://www.blueskyonmars.com/" id="r16s">Kevin Dangoor</a>&#8217;s Paver talk where he explained the motivations for <a title="Paver" href="http://www.blueskyonmars.com/projects/paver/" id="sqre">Paver</a> and showed numerous examples of what pain points it solves. Finally, the last session I attended at PyWorks was <a title="Jonathan LaCour" href="http://cleverdevil.org/" id="ihuq">Jonathan LaCour</a>&#8217;s talk about <a title="Elixir" href="http://elixir.ematia.de/" id="x33w">Elixir</a>, the Python module which makes introduction into <a title="SQLAlchemy" href="http://www.sqlalchemy.org/" id="iu_o">SQLAlchemy</a> an easy one. Elixir helps kick start your DB code by simplifying SQLAlchemy by making a lot of sane choices for you as well as providing other conveniences. Jonathan had to work hard to get all of his content into his hour, mostly because he gave a decent overview of SQLAlchemy and then his Elixir module.</p>
<p>As with the previous day, this day concluded with another happy hour while waiting for our closing keynote. The closing keynote was given by <a title="Jay Pipes" href="http://jpipes.com/" id="smfp">Jay Pipes</a> about &#8220;living in the gray areas&#8221; and not sticking to extreme black and white of our technologies. He praised the joint efforts being made by the PHP and Python folks and criticized people who are too biased to learn from the other communities. Jay is working on <a title="Drizzle" href="https://launchpad.net/drizzle" id="q8q9">Drizzle</a>, while working for Sun, where they are challanging all of the preconceived notions being made by the MySQL community. Drizzle is basically a fork of MySQL and their goals are to provide a much more streamlined version of a database. Jay explained that forks are good (as well as &#8220;sporks&#8221;) because it keeps people on their toes and keeps the level of competition up. Finally, Jay&#8217;s last point was that we need to spend more time listening to other people and less time preaching our biased opinions.</p>
<p>I overheard PHP and Python people resonating Jay&#8217;s message after the keynote. I&#8217;m glad to have participated in such a successful conference where I truely believe boundries were crossed. With as much time that I spend with the PHP folks, I was repeatedly asked, &#8220;So, you coming over to the PHP side?&#8221; I think the last time I was asked that was in the hotel pool where again I was playing the role of the &#8220;token Python guy&#8221; amongst the PHP folks. To be honest, those PHP folks know how to have fun, and if my criteria for choosing a programming language was the amount of fun the community had I would be doing PHP development. I definately want attend next year&#8217;s PyWorks and PHP conference and I have an entire year to come up with my presentation proposals.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonebird.com/2008/11/16/pyworks-in-summation/feed/</wfw:commentRss>
		</item>
		<item>
		<title>2D Barcodes</title>
		<link>http://jonebird.com/2008/11/06/2d-barcodes/</link>
		<comments>http://jonebird.com/2008/11/06/2d-barcodes/#comments</comments>
		<pubDate>Thu, 06 Nov 2008 05:06:21 +0000</pubDate>
		<dc:creator>jonEbird</dc:creator>
		
		<category><![CDATA[blogging]]></category>

		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://jonebird.com/?p=37</guid>
		<description><![CDATA[ In anticipation of heading down to PyWorks 2008, I have been thinking about creating a business card for the sake of keeping in contact with people I meet. One of my main goals, while attending and speaking at PyWorks, is to network with people and mark 2008 as the year which I start participating [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://jonebird.com/qrcode.png"> In anticipation of heading down to <a href="http://pyworks.mtacon.com/">PyWorks 2008</a>, I have been thinking about creating a <a href="http://www.flickr.com/photos/dailypoetics/sets/72057594104389710/">business card</a> for the sake of keeping in contact with people I meet. One of my main goals, while attending and <a href="http://pyworks.mtacon.com/c/schedule/talk/d2s3/4">speaking at PyWorks</a>, is to network with people and mark 2008 as the year which I start participating and contributing within the OSS community. While exercising my creativity in designing a nice business card, I have also been reading about Google&#8217;s <a href="http://code.google.com/android/">android</a> mobile platform, and I came across a interesting intersection between the two when I saw a demonstration video.</p>
<p>A Google developer, working on the <a href="http://code.google.com/p/zxing/">zxing</a> project (pronounced &#8220;zebra crossing&#8221;), has printed a 2D barcode encoding of his personal information on the back of his business card. With the builtin camera, on his android phone, he can scan in a barcode and immediate use the encoded data. It is an impressive demonstration of integrating technology with our mobile devices. Check out the video which has inspired me to not only do the same but also write this small informational note about 2D barcodes.</p>
<p><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/3LkNlTNHZzE&#038;hl=en&#038;fs=1"></param><param name="allowFullScreen" value="true"></param><embed src="http://www.youtube.com/v/3LkNlTNHZzE&#038;hl=en&#038;fs=1" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"></embed></object></p>
<p>If you didn&#8217;t catch it, the format of the 2D barcode on his business card is <a href="http://en.wikipedia.org/wiki/QR_Code">QR Code</a>. Among the other 2D barcode formats, QR Code barcodes are most popular in Japan where it was invented by <a href="http://www.denso-wave.com/qrcode/aboutqr-e.html">Denso-Wave</a>. The popularity of QR Codes in Japan has grown to the level of being supported by nearly every mobile device there and that also means finding QR Codes available on a increasing amount of printed media from fliers to magazines and coupons. </p>
<p>There are <a href="http://en.wikipedia.org/wiki/Barcode#2D_barcodes">other competing 2D barcode formats</a> that I could choose from but after doing researching and not seeing any distinctive advantages, I have concluded to follow suit with the google developer and hope that the android phone&#8217;s application and popularity will help propel QR Code&#8217;s popularity over the other 2D barcode formats. </p>
<p>Since 2D barcodes are nothing more than encoding and decoding data, the first thing to decide is what data we would like to encode. Since I actually do not have a business of my own and furthermore use a work issued phone, the data I encode will probably be a URL of my website. There are other interesting encodings, though, which include email address, sms, geographic locations, etc. See zxing&#8217;s wiki about <a href="http://code.google.com/p/zxing/wiki/BarcodeContents">BarcodeContents</a> for a better discussion for suggested format, including their primary suggestion of using the <a href="http://www.nttdocomo.co.jp/english/service/imode/make/content/barcode/function/application/addressbook/index.html">MECARD</a> format which is typically a composite of Name, Address, Phone number and Email address. </p>
<p>Once you know what you would like to encode in your 2D barcode, I&#8217;m guessing you will need software to help with that. With the assumption that you are not going to be encoding/decoding barcodes with a large frequency, my suggestion is that you use online utilities to help you. Interestingly, it turns out that the <a href="http://google-code-updates.blogspot.com/2008/07/qr-codes-now-available-on-google-chart.html">google chart api</a> can now generate QR Code online. That is both convenient for repeated generation of QR Code but also in dynamic generation of barcodes. But alas, <a href="http://jasondelport.com/">Jason Delport</a> has created a google app engine application to record your text and <a href="http://createqrcode.appspot.com/">generate the QR Code</a> for you by generating the google chart api link for you. At that point, you can either use the supplied URL or simply download the png image. Finally, for performing online decoding of the barcode I have found the <a href="http://zxing.org/w/decode.jspx">zxing online decoder</a> to be the best and least intrusive one available. </p>
<p>The main reason 2D barcodes have not really taken off here in the States is because people have not yet came up with a really good idea to propel it into the mainstream. That, my friends, is going to be up to you and me to accomplish. Or, wait, we could just let google usher it in for us? But seriously I think support for mobile devices to read 2D barcodes is great step forward. Afterwards, I can envision graphic designers coming up with <a href="http://www.darkroastedblend.com/2008/04/japanese-creative-barcodes.html">clever barcode</a> prints and ways of intriguing people to scan the code for more details, but then it would be people like us who come up with new categories of data to be encoded in the barcodes for new, innovative ways to use them.</p>
<p>To learn more, try the collection of <a href="http://code.google.com/p/zxing/wiki/InterestingLinks">interesting links</a> provided again by the zxing folks.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonebird.com/2008/11/06/2d-barcodes/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Management Tools for Multi-Vendors</title>
		<link>http://jonebird.com/2008/11/04/management-tools/</link>
		<comments>http://jonebird.com/2008/11/04/management-tools/#comments</comments>
		<pubDate>Tue, 04 Nov 2008 21:44:08 +0000</pubDate>
		<dc:creator>jonEbird</dc:creator>
		
		<category><![CDATA[adminstration]]></category>

		<category><![CDATA[blogging]]></category>

		<guid isPermaLink="false">http://jonebird.com/2008/11/04/50/</guid>
		<description><![CDATA[The challenge to build a tool which manages multiple vendors and platforms by way of piggy backing off their technology is a losing battle. Be it provisioning, patching, monitoring, etc it doesn&#8217;t matter. To choose such a tool, you end up paying big bucks for other people to constantly watch and react to what various [...]]]></description>
			<content:encoded><![CDATA[<p>The challenge to build a tool which manages multiple vendors and platforms by way of piggy backing off their technology is a losing battle. Be it provisioning, patching, monitoring, etc it doesn&#8217;t matter. To choose such a tool, you end up paying big bucks for other people to constantly watch and react to what various vendors are doing. Combine that piece of realization with the fact that a tool will almost never perfectly suit the unique requirements of your business and you&#8217;d be in denial to not realize that it sucks. Beyond the shear money of the endeavour you are also wasting time of your associates which will probably not get recouped. </p>
<p>I will never say anything is impossible. You can build such a tool and it can have the necessary hooks to allow your associates to customize it to suits your needs. My point is, that work is much harder to pull off than the naive observer might realize. Imagine you are abstracting the details of Suse&#8217;s automated installer &#8220;AutoYast&#8221;. But let&#8217;s say the OpenSuse project decides to take a drastic change on how the unattended installer works. Their efforts, no doubt, will be motivated by improving their end user&#8217;s experience by presumably making it quicker, simpler and overall a better product. Depending on how drastic the change, it could represent an entirely different philosophical approach to OS installs. As the tool builder, trying to provide a layer of abstraction, you have just stuck yourself into a large endeavour to re-factor those pieces of your application to handle the radical changes being made. It&#8217;s a given risk, if that is what you&#8217;re providing. My point is, as a customer, just don&#8217;t buy that product.</p>
<p>To purchase such a product, you are basically stating that you believe the particular team of developers are going to continue to accurately and intuitively abstract those details for you. Don&#8217;t forget you&#8217;re still paying a lot of money for this. But this is how management thinks, &#8220;I&#8217;m going to buy this tool and allow my associates to use one tool and spend their time elsewhere.&#8221; It doesn&#8217;t happen. Instead, the associates try to shift their energies on learning a new tool, figuring out how to customize it for their needs and probably end up with one FTE dedicated to maintaining it.</p>
<p>Please, don&#8217;t waste your time and money. Spend your time collaborating with teammates. Decide upon OS and install standards. Each OS installer provides the ability to perform basic configuration of disk, network, software, etc and then allows for final post-install hook. That hook will then lean upon your team&#8217;s efforts. You will end up spending the same amount of work creating your post-install scripts as it takes to merely install and train folks on an &#8220;all in one&#8221; tool. Big difference of &#8220;rolling your own&#8221; is you now own the tool set, it already exactly meets your needs, every one knows and understands how it works, updates are easy, knowledge and skill gained is more widely recognized and all the while you haven&#8217;t spent more money.</p>
<p>Now for the counter-point: You have to have a good team to pull this off. Team members will require enough experience to demonstrate the proper discernment in building out a quality framework. So what if you maintain a Solaris Jumpstart, RedHat kickstart, Suse autoyast, etc all together? Keep your data and configs centrally managed together. Parallel concepts between each one, maintain like directory hierarchies, write straight forward documentation on using and performing builds. Doesn&#8217;t it make sense to be proficient in the OS tool which comes directly from the vendor, at least from a personal development perspective?&nbsp; </p>
<p></p>
]]></content:encoded>
			<wfw:commentRss>http://jonebird.com/2008/11/04/management-tools/feed/</wfw:commentRss>
		</item>
		<item>
		<title>PyWorks Stuff</title>
		<link>http://jonebird.com/2008/10/25/pyworks-stuff/</link>
		<comments>http://jonebird.com/2008/10/25/pyworks-stuff/#comments</comments>
		<pubDate>Sat, 25 Oct 2008 05:00:53 +0000</pubDate>
		<dc:creator>jonEbird</dc:creator>
		
		<category><![CDATA[adminstration]]></category>

		<category><![CDATA[python]]></category>

		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://jonebird.com/?p=29</guid>
		<description><![CDATA[For the 2008 PyWorks convention, I will be presenting about LDAP and Python. The presentation is really about demystifying LDAP and encouraging people to use and extend LDAP for their config file needs. In efforts to make my point, the last half of my presentation will be a time for a demo. This entry is [...]]]></description>
			<content:encoded><![CDATA[<p>For the 2008 PyWorks convention, I will be presenting about LDAP and Python. The presentation is really about demystifying LDAP and encouraging people to use and extend LDAP for their config file needs. In efforts to make my point, the last half of my presentation will be a time for a demo. This entry is your basic landing point where you can download the scripts, presuming you are looking for a copy of the scripts and/or slides after seeing my presentation? (oh! nevermind, your google search landed you here)</p>
<p><a href="http://pyworks.mtacon.com/"><img src="http://jonebird.com/pyworks/pyworks_08_Speaker_button.jpg" alt="PyWorks Speakers Badge" /></a></p>
<p>For the demo, I will be leveraging the <a href="http://fail2ban.sourceforge.net/">fail2ban</a> project. It is a python based application which scans typical application logs for security failures and bans IPs from being able to connect again. It also uses the builtin <a href="http://www.python.org/doc/2.5/lib/module-ConfigParser.html">ConfigParser</a> module for reading it&#8217;s 30+ config files, which is why I have chosen to use it. For the demo, I have created two scripts:</p>
<p>The first one, <a href="http://jonebird.com/pyworks/configparser2ldap.py">configparser2ldap.py</a> is used to process a set of config files and automatically generate LDAP schema as well as LDIF data. </p>
<p>Next, I have my <a href="http://jonebird.com/pyworks/ldapconfig.py">ldapconfig.py</a> module where I extended the ConfigParser module to support making queries to LDAP. I am basically overriding the <code>read()</code> method only and leaving the rest of the module alone. This way the only modifications to the fail2ban application are how it is instantiating the ConfigParser and I won&#8217;t have to become a full time fail2ban developer if I want to centralize the configuration data in LDAP.</p>
<p>And that is really the main point of my presentation: The power of centralizing your configuration data and how it can drastically change how you administer your large scale server farm. </p>
<h3>Downloads</h3>
<p><a href="http://jonebird.com/pyworks/ldap.pdf">LDAP + Python</a> Slides.</br><br />
<a href="http://jonebird.com/pyworks/configparser2ldap.py">configparser2ldap.py</a> script to auto-generate LDAP schema and LDIF from ConfigParser compatible config files.</br><br />
<a href="http://jonebird.com/pyworks/ldapconfig.py">ldapconfig.py</a> python module which inherits the ConfigParser and supports optionally pulling config data from LDAP.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonebird.com/2008/10/25/pyworks-stuff/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Essential Emacs Knowledge</title>
		<link>http://jonebird.com/2008/09/18/essential-emacs-knowledge/</link>
		<comments>http://jonebird.com/2008/09/18/essential-emacs-knowledge/#comments</comments>
		<pubDate>Fri, 19 Sep 2008 02:33:32 +0000</pubDate>
		<dc:creator>jonEbird</dc:creator>
		
		<category><![CDATA[blogging]]></category>

		<category><![CDATA[emacs]]></category>

		<guid isPermaLink="false">http://jonebird.com/2008/09/18/24/</guid>
		<description><![CDATA[I am on a island at work and there is no one else to converse with other than Wilson. The island is called &#8220;Isle de Emacs&#8221; and Wilson is, I guess, psychoanalyze-pinhead. But occasionally I do get a visitor to the island and the conversation is more or less the same stuff. Okay, enough with [...]]]></description>
			<content:encoded><![CDATA[<p>I am on a island at work and there is no one else to converse with other than Wilson. The island is called &#8220;Isle de Emacs&#8221; and Wilson is, I guess, psychoanalyze-pinhead. But occasionally I do get a visitor to the island and the conversation is more or less the same stuff. Okay, enough with the analogy, this short tutorial is about getting you acquainted with using the Emacs editor. The repeated conversation I was referring to was an introduction to Emacs and trying to educate my co-worker on both the essential pieces of knowledge and a bit of Emacs philosophy to help guide their learning process. </p>
<h3>Essential Knowledge</h3>
<p>- In case you don&#8217;t know, emacs is really just a lisp interpreter.<br />&nbsp; Means it&#8217;s nearly infinitely extensible.<br />&nbsp; P.S. Also, in case you don&#8217;t know, Lisp is a programming language. That means practically everything the editor is supporting, from moving the cusor word by word to saving and opening files, is actually being done via code written in Lisp.<br />- Files being opened and edited are referred to as buffers.<br />&nbsp; To say you are &#8220;closing a buffer&#8221; means you are closing that file and will no longer have it open.<br />&nbsp; Similarly, when we say &#8220;switch to buffer&#8221; means that you are changing the current screen from what you are viewing/editing and moving to the next file.<br />- In keyboard shortcut notation, (C-x f) means to hold the<br />
&lt;control&gt; key then depress &lt;x&gt;, then releasing and then<br />
pressing &lt;f&gt;.<br />&nbsp; In general, a space means you should stop pressing any keys and then move onto the next key sequence.<br />- Emacs commands are often a two sequence routine.<br />&nbsp; Open a file (C-x C-f), save (C-x C-s), quit the editor (C-x C-c).<br />&nbsp; Psst. (C-x) is common starting sequence, particularly for the basic operations.<br />- What does the &#8220;M&#8221; character stand for in keyboard sequences?<br />&nbsp; It is called the &#8220;Meta&#8221; key and to execute it, you can use the &lt;Alt&gt; key or you can alternatively hit &lt;Esc&gt; followed by the next key. If you use the &lt;Esc&gt; key, you do not depress both keys at the same time, whereas with the &lt;Alt&gt; you do hit both keys at the same time.<br />&nbsp; So, to get the command prompt (technically executing execute-extended-command), the sequence is (M-x). With the &lt;Esc&gt; method, it&#8217;s hit Escape, then hit &#8220;x&#8221;, whereas with the &lt;Alt&gt; you would start by holding &lt;Alt&gt; and then depress &#8220;x&#8221;.<br />&nbsp; I used to use the &lt;Esc&gt; key method, but forced myself to use the &lt;Alt&gt; method in order to keep my fingers on the home keys for speed.<br />- To set a keyboard shortcut, it is called a &#8220;binding&#8221;.<br />&nbsp; The interactive emacs command to do this is called &#8220;global-set-key&#8221;.<br />- The equivalent to &#8220;man man&#8221; of learning shell skills is (C-h ?)<br />&nbsp; There you will see various types of help. You can search the building commands, you can query what a keyboard sequence will execute and much more.<br />- Emacs can do nearly everything, but it is fairly esoteric in it&#8217;s approach to being your text editor.<br />&nbsp; What this means is that it&#8217;s learning curve is pretty steep. If you try to climb that hill initially, you&#8217;ll probably give up.<br />&nbsp; Try to <i>just</i> learn the essentials and don&#8217;t bother with anything else. Learn one thing at a time. Use the menu, use the mouse, use your arrow keys, the pgdn and pgup keys, etc. Try to use the editor just like you would use notepad, but understand that one of the goals of a advanced emacs user is to not need the menu, scroll bars, mouse, etc.<br />&nbsp; I once attended a RedHat training course where the instructor called himself a &#8220;emacs guy&#8221; but watching him actually use the editor appeared to me like he just started using it last week. But hey, that is totally cool, and really, the correct approach for learning emacs.<br />- Why should I invest in a learning a editor with such a steep learning curve?<br />&nbsp; Because it can do nearly anything and can be customized for everything. Without going into a full dissertation, this means that the effort you are investing into this editor will not be put to waste. And moreover, you will not invest efforts just to find that you&#8217;ve reached the extent of what the particular editor can do.<br />- When you use (M-x) to enter a command, if there is a keyboard shortcut, the mini-buffer will tell you what it is.<br />&nbsp; Psst: Can also use (C-h b) to show a helping page about the keyboard bindings.<br />- You can Tab-complete nearly everywhere.<br />&nbsp; First place you&#8217;ll notice is when opening a file, but you can use within the mini-buffer too. Can be used to complete emacs commands,<br />&nbsp; variable names, etc.<br />- So, you&#8217;ve forgotten that command but you remember it&#8217;s about the keyboard?<br />&nbsp; Search the commands, (C-h a) then just type &#8220;key&#8221; and ENTER to search for commands with &#8220;key&#8221; in the name.<br />- In case you get yourself stuck or just not sure what you just pressed, there are two common ways to quit out.<br />&nbsp; (ESC ESC ESC) - Hiting Escape three times gets you out of what you&#8217;re doing. This actually works for closing out that split screen help window too.<br />&nbsp; The other way to quit out of items is to use (C-g), but there are scenarios where ESC ESC ESC works and C-g doesn&#8217;t.<br />- Customization is done within your ~/.emacs file.<br />&nbsp; You are technically executing emacs lisp here. Since you&#8217;re reading this, I&#8217;ll assume you&#8217;re a newbie and as such, just go and copy somebody else&#8217;s .emacs file. If you&#8217;re still a Emacs user after a year, perhaps you&#8217;ll finally feel adventurous enough to dive in there and generate your own customizations.<br />- Support for different types of files is done via different &#8220;modes&#8221;.<br />&nbsp; Your current &#8220;mode&#8221; is displayed in the status bar, at the bottom of the editor, in parentheses.<br />&nbsp; To change to text mode, for example, execute the command text-mode (M-x text-mode). In general, to enter any mode, it&#8217;s going to be the modename followed by &#8220;-mode&#8221;. Means, for Python, execute python-mode.<br />&nbsp; A cheap way to see how many modes Emacs supports is to do a apropos search on &#8220;mode&#8221;. That is, (C-h a &#8220;mode&#8221;) to show each command with the word &#8220;mode&#8221; in it.<br />- How do I automatically execute something when entering a particular mode?<br />&nbsp; Although not an essential piece of knowledge, to execute something when entering a mode to to &#8220;create a hook&#8221;. By convention, the hooks are stored by the variable matching the mode name and adding &#8220;-hook&#8221; to the end. So the hook for executing something when I enter &#8220;outline&#8221; mode is stored in the variable &#8220;outline-mode-hook&#8221;. I didn&#8217;t use that example by accident either. Here is my hook, used in my .emacs file:<br /><span style="font-family: Courier New;">(add-hook &#8216;outline-mode-hook &#8216;hide-body)</span><br />&nbsp; Even without any Lisp knowledge, that should be fairly intuitive. It will automatically fold the body of each section within my outline document upon opening it. <br />&nbsp; Psst: Try sticking a &#8220;<span style="font-family: Courier New;">-*- outline -*-</span>&#8221; as the first line of your outline file while keeping the file extension .txt. Without that line, emacs will assume it&#8217;s plain text because of the .txt extension, but with that line, you are telling emacs to use outline-mode for this file. It&#8217;s great for keeping notes.<br />&nbsp; I use it for keeping notes on every single work request ticket I receive at work. Such a file could become beastly in size but I don&#8217;t notice since it&#8217;s all rolled up when I re-open it. <br />
<h3>Essential Habits.</h3>
<p>- Keep your buffers open<br />&nbsp; Learn to switch between buffers (C-x b TAB)<br />&nbsp; I, myself, keep my emacs editor open at all times. I never close it. I keep buffers of my week&#8217;s work open for weeks on end. I&#8217;ll pretty much only close buffers when it becomes too cluttered when switching between buffers (C-x b TAB).<br />&nbsp; Finally, I currently have my EDITOR variable set to &#8220;emacsclient&#8221; which means commands such as &#8220;crontab&#8221; connect to that single running emacs editor.<br />- Tab complete everything.<br />&nbsp; Just like you should be doing in the shell, tab-complete commands, filenames, etc within emacs.<br />- Use the desktop-save feature.<br />&nbsp; This tip suppliments the habit of keeping your buffers open. The desktop-save allows you to keep track of all buffers currently open and to reopen them upon restarting emacs. This is useful on laptops where you won&#8217;t be able to keep a copy of emacs always running.<br />- Pay attention to the keyboard shortcuts which are listed in the menu as you navigate to execute them.<br />&nbsp; This goes along with the &#8220;learn one trick at a time&#8221; suggestion. Next time you get tired of executing that command from the menu, instead learn the keyboard shortcut for it. <br />&nbsp; Psst: If you are curious what emacs lisp command is being executed in the menu, you can still use the keyboard help command (C-h k). People normally use that help command to tell them what command is being executed for the keyboard sequence but few realize that it works for menu items as well. <br />
<h3>Essential Tricks</h3>
<p>- (C-x ESC ESC) - Repeat complex sequence<br />- Want to assign a keyboard shortcut to something which you do alot?<br />&nbsp; E.g. By default &#8220;goto-line&#8221; is not set to a shortcut. Let&#8217;s say you want to assign to (C-c g).<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Run (M-x global-set-key). It will prompt you what keyboard sequence to use and what to execute.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Next run, (C-x ESC ESC) which is for repeat complex routine. At this point, the sequence is listed in emacs-lisp form in the mini-buffer.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Run (C-x o) to get to the mini-buffer so you can copy that text (C-a C-space C-e M-w) and return to the normal buffer (C-x o).<br />- If operating in a corporate environment with a jump machine segregating your workstation and the rest of your environment, use TRAMP.<br />&nbsp; Tramp allows you edit remote files over various protocols. I recommend using &#8220;ssh&#8221; and to that point, stick these lines into your .emacs file:
<pre style="font-family: Courier New;">(setq tramp-default-method "ssh")</pre>
<p>- Redefine how your backups are made.<br />&nbsp; Emacs will automatically make backups of your files as you are editing them. By default it sticks a &#8220;~&#8221; character at the end of the file.<br />&nbsp; Well, this is quite annoying for me since it will also keep file permissions. If I&#8217;m creating a script, now I can&#8217;t get a unique tab-completion in the shell by typing (./scr TAB) to expand to &#8220;./script.sh&#8221;. Instead it finds &#8220;script.sh~&#8221; also. Move your backups to ~/.backups directory. Create that directory and then add these lines to your .emacs file:<br /><span style="font-family: Courier New;">(defun my-make-backup-file-name (file-name)</span><br style="font-family: Courier New;"><span style="font-family: Courier New;">&nbsp; &#8220;Create the non-numeric backup file name for `file-name&#8217;.n</span><br style="font-family: Courier New;"><span style="font-family: Courier New;">&nbsp;&nbsp; This customized version of this function is useful to keep all backups</span><br style="font-family: Courier New;"><span style="font-family: Courier New;">&nbsp;&nbsp; in one place, instead of all over the filesystem.&#8221;</span><br style="font-family: Courier New;"><span style="font-family: Courier New;">&nbsp; (require &#8216;dired)</span><br style="font-family: Courier New;"><span style="font-family: Courier New;">&nbsp; (message (concat &#8220;make-backup: &#8221; file-name))</span><br style="font-family: Courier New;"><span style="font-family: Courier New;">&nbsp; (if (file-exists-p &#8220;~/.backups&#8221;)</span><br style="font-family: Courier New;"><span style="font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (concat (expand-file-name &#8220;~/.backups/&#8221;)</span><br style="font-family: Courier New;"><span style="font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (dired-replace-in-string &#8220;/&#8221; &#8220;|&#8221; file-name))</span><br style="font-family: Courier New;"><span style="font-family: Courier New;">&nbsp;&nbsp;&nbsp; (concat file-name &#8220;~&#8221;)))</span><br /><span style="font-family: Courier New;">(setq make-backup-file-name-function &#8216;my-make-backup-file-name)</span><br />- Use emacswiki.org. In fact, the last backup trick was taken from there.<br />&nbsp; Just as I recommended above, don&#8217;t try to become an expert overnight. Learn the basics well and then pick up one trick at a time. I believe this can be a never ending process as you&#8217;re goal should be to become more and more proficient in your editor. So, go out and learn just one new trick and don&#8217;t come back until that new trick is ingrained into your finger&#8217;s memory.<br />
<h3>Essential Memorization List</h3>
<p>- (M-x) - Execute emacs command. <br />- (C-x u) - Undo.<br />- (M-x revert-buffer) - Oops, I just totally messed this file up and need to revert from the saved copy.<br />- (C-x o) - Move cursor to other split window pane.<br />&nbsp; Nice for looking through the help buffer after it just split your screen.<br />- (C-x 1) - Keep current buffer and remove other split pane.<br />&nbsp; I.e. Get that other window out of my way, please.<br />- (C-x 0) - Keep the _other_ buffer and remove this one.<br />&nbsp; Just like the previous, but you&#8217;re keeping the other buffer as the sole window.<br />&nbsp; Nice when you&#8217;re paging through an apropos section and are done. Use this to close the window without switching back first.<br />- (C-x C-f) - Open file<br />- (C-x C-s) - Save file<br />- (C-x C-c) - Exit</p>
<p>The goal of this short guide was to arm you with the necessary knowledge<br />
in order to get you going with one of the most powerful editors around.<br />
I didn&#8217;t necessarilly want to write a whole series of Emacs weblog entries. Instead, I just did a brain dump and I hope it wasn&#8217;t too overwhelming. Instead, I&#8217;d rather hope it helps<br />
guide you to the island. We&#8217;ll play some volleyball, snorkel, hunt peacocks,<br />
etc; you know, island stuff.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonebird.com/2008/09/18/essential-emacs-knowledge/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Fixing my Weblog</title>
		<link>http://jonebird.com/2008/09/18/fixing-my-weblog/</link>
		<comments>http://jonebird.com/2008/09/18/fixing-my-weblog/#comments</comments>
		<pubDate>Fri, 19 Sep 2008 01:40:54 +0000</pubDate>
		<dc:creator>jonEbird</dc:creator>
		
		<category><![CDATA[blogging]]></category>

		<guid isPermaLink="false">http://jonebird.com/?p=21</guid>
		<description><![CDATA[Some time ago I lost my harddrive. At that point, I was making infrequent backups to the laptop. Not very admin-like for someone who&#8217;s profession is a Systems Administrator. It could have been much worse, but still a pain none the less. 
I had to solve various issues with my home setup. First the harddrive [...]]]></description>
			<content:encoded><![CDATA[<p>Some time ago I lost my harddrive. At that point, I was making infrequent backups to the laptop. Not very admin-like for someone who&#8217;s profession is a Systems Administrator. It could have been much worse, but still a pain none the less. </p>
<p>I had to solve various issues with my home setup. First the harddrive vulnerability. For that, I bought two 320GB harddrives and setup a /dev/md0 RAID0 mirror. After that, I installed a fresh copy of Fedora Core 9. I got Wordpress back up but honestly my site was still limping along. I left it that way for too long and have finally cleaned things up tonight, culminating the work by upgrading to Wordpress 2.6.2. </p>
<p>Now let&#8217;s get back to writing more weblog entries.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonebird.com/2008/09/18/fixing-my-weblog/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Reverse Engineering Buddy</title>
		<link>http://jonebird.com/2007/11/13/20/</link>
		<comments>http://jonebird.com/2007/11/13/20/#comments</comments>
		<pubDate>Wed, 14 Nov 2007 03:34:52 +0000</pubDate>
		<dc:creator>jonEbird</dc:creator>
		
		<category><![CDATA[adminstration]]></category>

		<category><![CDATA[linux]]></category>

		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://jonebird.com/2007/11/13/20/</guid>
		<description><![CDATA[An Idea for a helpful Admin Tool
What if you got a page and/or ticket for an obscure server&#8217;s particular service? The unique problem is that your environment is huge, you&#8217;re still relatively new to the company, co-workers are not there to help you and you have never heard of this server. When logging in, you&#8217;re [...]]]></description>
			<content:encoded><![CDATA[<p>An Idea for a helpful Admin Tool</p>
<p>What if you got a page and/or ticket for an obscure server&#8217;s particular service? The unique problem is that your environment is huge, you&#8217;re still relatively new to the company, co-workers are not there to help you and you have never heard of this server. When logging in, you&#8217;re hoping that the person has a nice RC script under /etc/init.d/, that you can find the app via a &#8220;lsof -i:&lt;port&gt;&#8221;, find the application&#8217;s home and locate some log files. But what if the application install was not that nice and did not conform to the norms that you are used to? </p>
<p>To either a small or very large degree, you will be reverse engineering this application. If you&#8217;re <i>really</i> unlucky, the application who supports it also has no idea about it nor knows anything about Unix-like machines. So, what if there was an application which is polling upon logging into the server, told you, &#8220;In case you are looking for the application binX, which typically listens on port XX, it was most likely started last time by issuing the script /path/to/funky/path/binX.sh&#8221;. I&#8217;m guessing it would freak you out and immediately flood your emotions with confusion, gratitude and curiosity. </p>
<p>So, would such an application be difficult to write? 
<ul>
<li>Poll any events for read/write/access under key dirs, such as /etc/init.d/, /etc/*conf ? (use the inotify syscall introduced in Linux kernel 2.6.16)</li>
<li>Track users logging into the system (could correlate later)</li>
<li>Watch for any new ports being listened on, then record the binary name. </li>
<li>Reverse engineer this application to automatically collect interesting data on it.</li>
<li>Intelligently parse an strace (note to self, checkout: http://subterfugue.org/)</li>
<li>Utilize systemtap for Linux and DTrace for Solaris. pseudo code { observe new socket being opened, so show me the last 10 files opened and executed. correlate application with startup script }</li>
</ul>
<p>Now, if your data was collected in a easily usable format, you can collect similar data from other machines and start to make broader correlations. </p>
<p>The whole process is really about automating the process of reverse engineering an application. I do that alot. I believe others would like an application which aided or performed the entire reverse engineering for them. </p>
]]></content:encoded>
			<wfw:commentRss>http://jonebird.com/2007/11/13/20/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Stripping Another Process of it&#8217;s Signal Handler</title>
		<link>http://jonebird.com/2007/06/21/stripping-another-process-of-its-signal-handler/</link>
		<comments>http://jonebird.com/2007/06/21/stripping-another-process-of-its-signal-handler/#comments</comments>
		<pubDate>Fri, 22 Jun 2007 04:38:05 +0000</pubDate>
		<dc:creator>jonEbird</dc:creator>
		
		<category><![CDATA[adminstration]]></category>

		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://jonebird.com/2007/06/21/stripping-another-process-of-its-signal-handler/</guid>
		<description><![CDATA[Have you ever wanted to send a signal, which normally produces a core file, but the process has one of those annoying signal handlers setup to catch the signal you&#8217;re sending? The nerve of that application trying to intelligently handle signals! I actually have a real need to remove the signal handler of a process [...]]]></description>
			<content:encoded><![CDATA[<p>Have you ever wanted to send a signal, which normally produces a core file, but the process has one of those annoying signal handlers setup to catch the signal you&#8217;re sending? The nerve of that application trying to intelligently handle signals! I actually have a real need to remove the signal handler of a process which I&#8217;ll describe shortly. Normally, it is a bad idea to remove another process&#8217;s signal handler and under normal circumstances I do not suggest following the procedure which I am going to describe. </p>
<p>I have been struggling with a production issue at work with a process which has been less than cooperative. You see, I have a java process which gets crazy and starts consuming CPU cycles. When you run a <code>strace</code> against the process the only system call you will see is a <code>sched_yield()</code> call. The java thread is most likely stuck on a spinlock in user space and the process/thread which owns the lock has died or something else, but for my runaway process all it cares about it is checking for it&#8217;s lock and yielding execution back to the kernel to schedule another task. Ofcourse, it just gets the CPU again and continues to pound it.</p>
<p>My company pays alot of money for support and we actually have had a case now open for eight months now. The problem is we are unable to gather sufficient data for their level2 and level3 support teams. They would like a javacore to be generated, which can be done by sending a signal 3 to the java process. In addition to a javacore, they recommend sending a signal 11 (SEGV) to the process to prompt the generation of a normal binary core file. Either one would be invaluable for the support team in ascertaining what is going wrong. Unfortunately, it seems that once the process is stuck in this tight, <code>sched_yield()</code> loop any of the signals we send to it are being ignored. In short, that is my problem.</p>
<p>During my <a href="https://www.redhat.com/training/developer/courses/rhd236.html">Linux Kernel Internals</a> training with RedHat, I had an idea of writing a kernel module to strip the signal handler from the java process so I can finally generate that elusive core file. The kernel module sets up an entry under /proc named <code>stripsignal_pid</code>. If you read the value, it will tell you a quick one-liner about using this interface. To use the module, you write a process ID into that file and that process&#8217;s SIGABRT signal handler will be reset to the SIG_DFL. At this point, if you send a SIGABRT signal to the process the result will be writing out of it&#8217;s core file. </p>
<p>Download the source along with a helper test program here: <a href="/stripsignal.tar.gz">stripsignal.tar.gz</a>.</p>
<p>But if all you are interested in is reviewing the short source code, then feel free to browse the <a href="/stripsignal.html">stripsignal.c</a> source online.</p>
<p>I tell you what, the best thing I learned from the class was just familiarizing myself with the source code and actually learning some new emacs tricks for navigating large source code projects. Next writeup will be about my experiences with the GNU global tagging system. </p>
]]></content:encoded>
			<wfw:commentRss>http://jonebird.com/2007/06/21/stripping-another-process-of-its-signal-handler/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Python Admin vs. Java Developers</title>
		<link>http://jonebird.com/2007/01/15/python-admin-vs-java-developers/</link>
		<comments>http://jonebird.com/2007/01/15/python-admin-vs-java-developers/#comments</comments>
		<pubDate>Mon, 15 Jan 2007 22:31:45 +0000</pubDate>
		<dc:creator>jonEbird</dc:creator>
		
		<category><![CDATA[adminstration]]></category>

		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://jonebird.com/2007/01/15/python-admin-vs-java-developers/</guid>
		<description><![CDATA[What is the best programming language for a system administrator? Queue the language war, please. The typical arguments are &#8220;your language can&#8217;t do this&#8221;, &#8220;this library doesn&#8217;t have a consistent naming convention&#8221;, well &#8220;my language is faster&#8221;, yeah and &#8220;your syntax is hideous to read much less use&#8221;, blah blah blah.  No, I&#8217;m not [...]]]></description>
			<content:encoded><![CDATA[<p>What is the best programming language for a system administrator? Queue the language war, please. The typical arguments are &#8220;your language can&#8217;t do this&#8221;, &#8220;this library doesn&#8217;t have a consistent naming convention&#8221;, well &#8220;my language is faster&#8221;, yeah and &#8220;your syntax is hideous to read much less use&#8221;, blah blah blah.  No, I&#8217;m not a professional developer but I do spend a significant time doing development as a systems administrator. My programs are not huge year long projects, will probably never reach million lines of code and usually never need superb speed. For administrators, the most important aspect of the language of choice is productivity and maintainability. </p>
<p>When choosing your language, I recommend picking one that has a decent user community, is available on numerous platforms, has had significant time to mature in proving itself and has an extensive modules/library support. Meeting these requirements will leave you using a language that <em>should</em> keep you efficiently producing solutions to your administrative tasks. </p>
<p>First let&#8217;s eliminate some languages based on maintainability. Goodbye <a href="http://en.wikipedia.org/wiki/Haskell_%28programming_language%29">Haskell</a>, <a href="http://en.wikipedia.org/wiki/Lisp_%28programming_language%29">lisp</a>, <a href="http://en.wikipedia.org/wiki/Scheme_%28programming_language%29">scheme</a>, <a href="http://http://en.wikipedia.org/wiki/Erlang_%28programming_language%29">Erlang</a> and any other purely functional languages you have used or know of. I&#8217;d venture to say that less than 2% of system administrators are comfortable using any one of those languages. And you can obviously not choose a language which only yourself are going to be able to maintain. Aside from staying away from the obscure, the program should be intuitive to read. People can argue on the virtues of their favorite language and why it lends itself to writing maintainable code, but writing maintainable code is truly a skill. You can write obfusticated code in <em>any</em> language. It takes practice and a conscience effort of keeping your code clean and organized well. Here, practice makes perfect, is the key. </p>
<p>Secondly, and in my opinion the most important aspect of the language of choice is staying efficient. Ideally, each program should be succinct and to the point. I no longer use C/C++ regularly, even though that&#8217;s the language I started with, because you simply have to write much more code which another language can do in half or less of work. Try looking at one of the &#8216;P&#8217;s of the <a href="http://en.wikipedia.org/wiki/LAMP_%28software_bundle%29">LAMP</a> stack and see which fits you better and you can see yourself being productive in. That is, evaluate <a href="http://en.wikipedia.org/wiki/Python_%28programming_language%29">Python</a>, <a href="http://en.wikipedia.org/wiki/Perl">Perl</a>, <a href="http://en.wikipedia.org/wiki/PHP">PHP</a> and <a href="http://en.wikipedia.org/wiki/Ruby_%28programming_language%29">Ruby</a> (okay, not a &#8216;P&#8217; but whatever). Don&#8217;t use a language that doesn&#8217;t make sense to you. Don&#8217;t waste your time. </p>
<p>And finally, time to explain this title and tell a little story where some customer data was delayed during one day&#8217;s production incident. One day, we had a production issue where messages were accidentally dequeued from a IBM Webphere MQSeries queue. A tool which was used to grab just one message dequeued all of the messages. To top it all off, the same tool kept seg faulting while trying to requeue the same messages. The solution left to us was to manually parse out each of the discrete messages into separate files. Once in that state, we had another known tool which could upload the messages separately. There were three developers and myself on the phone and we were all racing to the solution. My language of choice was Python and the rest of the developers used the language that they use professionally, Java. So who reached the solution first? Well I wouldn&#8217;t be writing this if I hadn&#8217;t won, would I? For me, Python makes sense and I can efficiently write code which I like to think other people will be able to understand and update. That is what is most important for your language of choice.</p>
<p>[ As un-entertaining as it is, you can view the <a href="http://jonebird.com/parser.html">Python solution</a>. ]</p>
]]></content:encoded>
			<wfw:commentRss>http://jonebird.com/2007/01/15/python-admin-vs-java-developers/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Scripting Best Practices</title>
		<link>http://jonebird.com/2006/11/06/scripting-best-practices/</link>
		<comments>http://jonebird.com/2006/11/06/scripting-best-practices/#comments</comments>
		<pubDate>Mon, 06 Nov 2006 23:35:26 +0000</pubDate>
		<dc:creator>jonEbird</dc:creator>
		
		<category><![CDATA[adminstration]]></category>

		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://jonebird.com/2006/11/06/scripting-best-practices/</guid>
		<description><![CDATA[Nothing too fancy here. Just a list of the most common things I find desirable while writing shell scripts. 

 Use meaningful variable names 
This point is strictly for the sake of readability. Too often when trying to read somebodies script I&#8217;ll actually do various search &#038; replaces of their variables because they used variables [...]]]></description>
			<content:encoded><![CDATA[<p>Nothing too fancy here. Just a list of the most common things I find desirable while writing shell scripts. </p>
<ol>
<li> Use meaningful variable names </li>
<p>This point is strictly for the sake of readability. Too often when trying to read somebodies script I&#8217;ll actually do various search &#038; replaces of their variables because they used variables like &#8220;w&#8221;, &#8220;w2&#8243;, &#8220;w3&#8243;. It was quick and dirty for the author, but the inheritor of that script would appreciate if you had used more meaningful variable names.</p>
<li> Comment your code. </li>
<p>This goes without saying, really&#8230;</p>
<li> Visually separate any optional settings sections. </li>
<p>Don&#8217;t know about you, but sometimes I get lazy and don&#8217;t feel like using <code>getopts</code>. Instead, I&#8217;ll throw my what would be optional arguments as hard coded variables at the top of my script. I think this is fine, but you&#8217;ll want to visually segregate these optional variables from the rest of the script.<br />
I like to use a &#8212; dashed line of about 50-70 characters and even put the words &#8220;do not modify beyond this point&#8221; to further emphasize what you&#8217;re encouraged to change and what shouldn&#8217;t normally be touched. </p>
<li> Use relative pathing for accessing files to the script. </li>
<p>    Never assume the user&#8217;s cwd is the same as the script and use &#8220;./&#8221; to run or source another file. I like to set a variable <code>REL_DIR=`dirname $0`</code> and use it to reference the directory where the very script is running from.<br />
    E.g. You have a functions script you&#8217;d like to source, then with that <code>REL_DIR</code> variable you would &#8220;<code>. ${REL_DIR}/&lt;some-file&gt;</code>&#8220;.<br />
I&#8217;m actually surprised on how often this happens.</p>
<li> Always print a usage statement for improper usage and/or when -h option used. </li>
<p>      My code excerpt typically looks like:</p>
<pre>
USAGE="Usage: `basename $0` &lt;my options here&gt;"
if [ -z "$SOME_ARG" ]; then
    print $USAGE 1>&amp;2
    exit 1
fi
</pre>
<li> Conscientiously use STDOUT vs. STDERR in different scenarios. </li>
<p>Not a script faux pau really, but it can help during the development process.  Use STDOUT only for informational messages and/or optional debugging info. Then STDERR would only be used for errors. That way, when running the script you can optionally turn off stdout (<code>1&gt;&#038;-</code>) and easily check that nothing was printed to STDERR. When the output is mixed you&#8217;ll have a greater chance of missing the error.<br />
      One example of this technique in action is when using the tar command. Try leaving out the verbose (&#8217;v') option when creating or extracting your archive, then you can easily see when you might have had a permissions issue or something else related.</p>
<li> Keep all required variables defined in the script. </li>
<p>      Define the required variables at the top of the script. Even mention that they are REQUIRED. A good example of this is scripts that use Sybase&#8217;s isql utility. Anytime I run isql, I like to set something like:</p>
<pre>
# required variables for isql
SYBASE=/some/path/to/sybase
LD_LIBRARY_PATH=$SYBASE/lib
</pre>
<p>      What you want to avoid is a situation where the script works because you&#8217;ve got the required variable set in <em>your</em> env, but only because it&#8217;s set in one of your dot files.</p>
<li> Cron&#8217;ed Scripts. </li>
<p>      Two common principles I like to emphasize here:<br />
         1. Keep all required variable/env settings in the script! cron does NOT source your dot files.<br />
         2. Redirect stdout, but leave stderr unmanaged. This is a cheap technique, but whenever I don&#8217;t have time to test for all possible errors I simply setup my .forward file and let cron email me the output produced from the cron script. Though, to be complete, you should really manage your stderr in other fashions. </p>
<li> Keep your exit/return codes categorized. </li>
<p>      Not always important for small scripts, but a good practice.<br />
      For any sort of error checking your script might perform, use a unique error code for each situation that you decide to exit the shell script. That will make invocations of your script more manageable.</p>
<li> Avoid &#8220;Magic&#8221; Numbers </li>
<p>      Anywhere you are comparing a value to some, seemingly, arbitrary number, go ahead and set that value to a meaningful variable name. Then your comparison reads alot better.<br />
Using &#8220;<code>$CURRENT_VALUE -gt $THRESHOLD</code>&#8221; is much better than finding &#8220;<code>$CURRENT_VALUE -gt 83</code>&#8221; buried in some script and not having any clue what the number 83 signifies aside from the surrounding code.</p>
<li> Use unique temporary files. </li>
<p>      Never do this: <code>/path/to/some/command -option &gt; command.out</code>.<br />
You are assuming that you are sitting in a directory where you have permissions to create a temporary file and secondly that no one will ever be running the same script at the same time you are.<br />
      Some shells make creating temporary files easy with commands such as <code>mktemp</code>. I typically employ a convention where I define my temporary file space as &#8220;<code>TEMP=/tmp/.myshellname$$_</code>&#8220;. Then lets say I need a temp file to capture the output from ps. I might redirect it to <code>${TEMP}raw_ps</code>.<br />
      And finally, at the end of the script, or defined in a shell function, you can cleanup each temporary file with one line: <code>rm -f ${TEMP}*</code>. </p>
</ol>
<p>In general, well written code/scripts should read well and be organized well. Every principle discussed above has one purpose: maintainability.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonebird.com/2006/11/06/scripting-best-practices/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
