<?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>The Daily Build &#187; tool</title>
	<atom:link href="http://blog.bstpierre.org/tag/tool/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.bstpierre.org</link>
	<description>Software Development, version 3.0</description>
	<lastBuildDate>Wed, 26 May 2010 16:08:50 +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>zsh history expansion</title>
		<link>http://blog.bstpierre.org/zsh-history-expansion</link>
		<comments>http://blog.bstpierre.org/zsh-history-expansion#comments</comments>
		<pubDate>Mon, 15 Feb 2010 13:59:52 +0000</pubDate>
		<dc:creator>Brian St. Pierre</dc:creator>
				<category><![CDATA[zsh]]></category>
		<category><![CDATA[tool]]></category>

		<guid isPermaLink="false">http://blog.bstpierre.org/?p=269</guid>
		<description><![CDATA[Exploring zsh features made me want to figure out some of the history-editing wizardry. (Bash has similar history tricks, I just never bothered to dive too deeply into them.)
If you want to experiment with history expansion a bit, you can echo the result instead of executing it:
hostname:~/dir% ls /some/long/path/to/file_0.1-2_i386.changes
hostname:~/dir% echo !?ls?:s/-2/-3/
echo ls /some/long/path/to/file_0.1-3_i386.changes
In this case, [...]


Related posts:<ol><li><a href='http://blog.bstpierre.org/open-an-ssh-tunnel-in-four-seconds-or-less' rel='bookmark' title='Permanent Link: Open an SSH Tunnel in Four Seconds or Less'>Open an SSH Tunnel in Four Seconds or Less</a> <small>As I mentioned in a previous...</small></li><li><a href='http://blog.bstpierre.org/zsh-zle-words' rel='bookmark' title='Permanent Link: Make the zsh zle handle &#8220;words&#8221; correctly'>Make the zsh zle handle &#8220;words&#8221; correctly</a> <small> Snippet from my .zshrc: #...</small></li><li><a href='http://blog.bstpierre.org/zsh-prompt' rel='bookmark' title='Permanent Link: Set Your zsh Prompt'>Set Your zsh Prompt</a> <small>Since the beginning of time, all...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>Exploring zsh features made me want to figure out some of the history-editing wizardry. (Bash has similar history tricks, I just never bothered to dive too deeply into them.)</p>
<p>If you want to experiment with history expansion a bit, you can echo the result instead of executing it:</p>
<pre>hostname:~/dir% ls /some/long/path/to/file_0.1-2_i386.changes
hostname:~/dir% echo !?ls?:s/-2/-3/
echo ls /some/long/path/to/file_0.1-3_i386.changes</pre>
<p>In this case, what I wanted to do is repeat a long command that referenced a file with a version number in it &#8212; but I wanted to use a different version number (-3 instead of the previously given version -2).</p>
<p>History expansion uses &#8220;!&#8221; (&#8220;bang&#8221;, or exclamation point). If you want to select the previous command to expand based on a string match, &#8220;!?str&#8221; will find the previous command that contains &#8220;str&#8221;. If you want to substitute some part of that previous command, put another question mark on the end, add a colon, and use the the &#8220;s&#8221; modifier. In the example above, &#8220;!?ls?&#8221; means expand the previous command containing &#8220;ls&#8221;. The &#8220;:s/-2/-3/&#8221; means modify that expanded command to replace the occurrence of &#8220;-2&#8243; with &#8220;-3&#8243;.</p>
<p>(Of course, to actually get all of that figured out and working, I had to iterate the sequence of commands above about a dozen times.)</p>
<p>Leave a comment with your favorite zsh history trick. Thanks!</p>


<p>Related posts:<ol><li><a href='http://blog.bstpierre.org/open-an-ssh-tunnel-in-four-seconds-or-less' rel='bookmark' title='Permanent Link: Open an SSH Tunnel in Four Seconds or Less'>Open an SSH Tunnel in Four Seconds or Less</a> <small>As I mentioned in a previous...</small></li><li><a href='http://blog.bstpierre.org/zsh-zle-words' rel='bookmark' title='Permanent Link: Make the zsh zle handle &#8220;words&#8221; correctly'>Make the zsh zle handle &#8220;words&#8221; correctly</a> <small> Snippet from my .zshrc: #...</small></li><li><a href='http://blog.bstpierre.org/zsh-prompt' rel='bookmark' title='Permanent Link: Set Your zsh Prompt'>Set Your zsh Prompt</a> <small>Since the beginning of time, all...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bstpierre.org/zsh-history-expansion/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>9 &#8220;Must-Have&#8221; Tools for Software Teams</title>
		<link>http://blog.bstpierre.org/must-have-tools-software-teams</link>
		<comments>http://blog.bstpierre.org/must-have-tools-software-teams#comments</comments>
		<pubDate>Mon, 18 Jan 2010 16:06:38 +0000</pubDate>
		<dc:creator>Brian St. Pierre</dc:creator>
				<category><![CDATA[tools]]></category>
		<category><![CDATA[software-engineering]]></category>
		<category><![CDATA[tool]]></category>

		<guid isPermaLink="false">http://blog.bstpierre.org/?p=254</guid>
		<description><![CDATA[The items below are useful systems based on my experience working with a bunch of different software teams at a handful of companies over the past decade-plus. I haven&#8217;t bothered to list things like compilers, interpreters, libraries, etc. If you don&#8217;t have those, you aren&#8217;t making software&#8230;

Source control. This almost belongs in the &#8220;if you [...]


Related posts:<ol><li><a href='http://blog.bstpierre.org/ssh-remote-port-forwarding-tunnels' rel='bookmark' title='Permanent Link: How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels'>How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels</a> <small>Ssh tunneling can be a bit...</small></li><li><a href='http://blog.bstpierre.org/insist-on-tests' rel='bookmark' title='Permanent Link: Insist on Automatic Tests'>Insist on Automatic Tests</a> <small> At some point your team...</small></li><li><a href='http://blog.bstpierre.org/pid-file-race' rel='bookmark' title='Permanent Link: An Interesting pid File Race'>An Interesting pid File Race</a> <small> ISC&#8217;s dhcpd uses this code...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>The items below are useful systems based on my experience working with a bunch of different software teams at a handful of companies over the past decade-plus. I haven&#8217;t bothered to list things like compilers, interpreters, libraries, etc. If you don&#8217;t have those, you aren&#8217;t making software&#8230;</p>
<ol>
<li><strong>Source control.</strong> This almost belongs in the &#8220;if you don&#8217;t have it, you aren&#8217;t making software&#8221; category. There are so many free and simple to use tools that it is ridiculous to not use source control. Pick one of: subversion, git, or any of the dozens of other free tools and use it. I guess I&#8217;d say &#8220;if you don&#8217;t have it, you are making a mess&#8221;.</li>
<li><strong>Bug/issue tracker</strong>. Trac is a decent tool for keeping tabs on development tasks and bugs. Bugzilla is ok too. If you have a budget, there is an apparently infinite set of commercial systems available of varying quality. Almost anything is better than a list of scribbles on your whiteboard.</li>
<li><strong>Backup server.</strong> You <em>can</em> do software without it, but the odds are against you lasting long.</li>
<li><strong>Build system.</strong> Automated nightly/continuous builds are awesome. Whether you DIY, install something free like hudson, or purchase a commercial system, this is a key piece of making sure that the software maintains at least a minimum level of quality (i.e. it is always buildable). After having worked on a couple of teams that didn&#8217;t have such a system, and the build was always broken, I would never work without it again.</li>
<li><strong>IM / Jabber</strong>. Especially with a conference server where the rooms are archived and available via the web. Searchable is nice, but making them available where they can be grepped isn&#8217;t bad either. I didn&#8217;t become convinced of the value here until last summer.It sounds like an extra distraction and sometimes it can be, but you can turn it off when you&#8217;re heads-down coding. And it has the potential to <em>reduce</em> the number of interruptions from people walking into your office with questions that could have been answered in an IM. It&#8217;s lighter weight than email and rooms are broadcast by nature so you don&#8217;t have to spam a huge list of people to find the answer you&#8217;re looking for.</li>
<li><strong>Email lists</strong>. Must have web-browsable archives; the list without this has much less value. Search would be a nice bonus, though I haven&#8217;t seen it done well. This lets teams communicate a bit more formally than IM and provides a record of certain discussions and decisions.</li>
<li><strong>FTP server.</strong> Bonus points for a TFTP server. Maybe it&#8217;s because of the nature of embedded software, but every team I&#8217;ve been on has always had to fling around large files and images. Email is horribly inefficient for this. Also, most of the products I&#8217;ve worked on needed an FTP (or TFTP) server to boot from. You&#8217;re likely to install something on your development machine, which is fine, but it&#8217;s convenient to have a central team/company internal server so you can just tell someone that a file is in your public directory on &#8220;the ftp server&#8221;. Microsoft shops and folks that don&#8217;t need to boot via FTP can probably get away with samba shares.</li>
<li><strong>Doc server.</strong> Wiki is probably the best way to go if your team doesn&#8217;t <em>have</em> to produce overly-formal documentation. Wikis and formal document control systems that I&#8217;ve used have had horrible search, which sucks but I haven&#8217;t found a great solution. In the past I&#8217;ve done this with a combination of a formal doc tool plus a blog for the informal &#8220;howto&#8221; kind of notes that are always needed.</li>
<li><strong>Code review.</strong> I can&#8217;t say I&#8217;ve worked anywhere that had a dedicated code review tool. However, when all of the development machines are on NFS so that everyone has a view of your workspace, IM fits the bill reasonably well: post a review request to the chat room with the path to your changes and get an ad hoc on the spot code review. With some discipline and a supportive culture this works very smoothly. (This arrangement could probably be done with an internal pastebin, which I haven&#8217;t listed here as must-have since I haven&#8217;t really seen it used.)</li>
</ol>
<p>What would you add to this list? Any other tools or systems that, if missing, would make you think twice about taking a job?</p>


<p>Related posts:<ol><li><a href='http://blog.bstpierre.org/ssh-remote-port-forwarding-tunnels' rel='bookmark' title='Permanent Link: How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels'>How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels</a> <small>Ssh tunneling can be a bit...</small></li><li><a href='http://blog.bstpierre.org/insist-on-tests' rel='bookmark' title='Permanent Link: Insist on Automatic Tests'>Insist on Automatic Tests</a> <small> At some point your team...</small></li><li><a href='http://blog.bstpierre.org/pid-file-race' rel='bookmark' title='Permanent Link: An Interesting pid File Race'>An Interesting pid File Race</a> <small> ISC&#8217;s dhcpd uses this code...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bstpierre.org/must-have-tools-software-teams/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Use SSH to Forward Multiple Protocols to Multiple Machines</title>
		<link>http://blog.bstpierre.org/ssh-forward-multiple-protocols-to-multiple-machines</link>
		<comments>http://blog.bstpierre.org/ssh-forward-multiple-protocols-to-multiple-machines#comments</comments>
		<pubDate>Fri, 04 Dec 2009 16:03:33 +0000</pubDate>
		<dc:creator>Brian St. Pierre</dc:creator>
				<category><![CDATA[ssh]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[tool]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://blog.bstpierre.org/?p=239</guid>
		<description><![CDATA[Let's say you have a half-dozen machines at work you want to log into. Instead of setting up a remote forwarding connection from each of those machines, you can have the connection from your main machine perform multiple forwardings instead of just one. This even works if some of the machines don't support ssh.


Related posts:<ol><li><a href='http://blog.bstpierre.org/open-an-ssh-tunnel-in-four-seconds-or-less' rel='bookmark' title='Permanent Link: Open an SSH Tunnel in Four Seconds or Less'>Open an SSH Tunnel in Four Seconds or Less</a> <small>As I mentioned in a previous...</small></li><li><a href='http://blog.bstpierre.org/local-ssh-forwarding' rel='bookmark' title='Permanent Link: Use Local SSH Forwarding to Reduce the Number of Manual Hops'>Use Local SSH Forwarding to Reduce the Number of Manual Hops</a> <small>Local port forwarding is the same...</small></li><li><a href='http://blog.bstpierre.org/ssh-remote-port-forwarding-tunnels' rel='bookmark' title='Permanent Link: How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels'>How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels</a> <small>Ssh tunneling can be a bit...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p><em>(This is part five in a <a href="../category/tools/ssh">series of posts on ssh</a>.)</em></p>
<p>Let&#8217;s say you have a half-dozen machines at work you want to log into. Instead of setting up a <a href="http://blog.bstpierre.org/ssh-remote-port-forwarding-tunnels">remote forwarding connection</a> from each of those machines, you can have the connection from your main machine perform multiple forwardings instead of just one. This even works if some of the machines don&#8217;t support ssh.</p>
<p>It shouldn&#8217;t surprise you at this point that you can do this with your config file. On your work machine, you might have something like:</p>
<pre>Host tunnel
  HostName cloud.example.com
  User mycloudusername
  IdentityFile ~/.ssh/id_dsa
  Port 22
  RSAAuthentication yes
  PubkeyAuthentication yes
  ExitOnForwardFailure yes
  # tunnel ssh to myworkmachine
  RemoteForward 4022 localhost:22
  # tunnel remote desktop to mywindowsbox via myworkmachine
  RemoteForward 5389 192.168.4.10:3389
  # tunnel http to mywindowsbox via myworkmachine
  RemoteForward 5080 192.168.4.10:80
  # tunnel remote desktop to otherwindowsbox via myworkmachine
  RemoteForward 6389 192.168.4.11:3389
  # tunnel ssh to workserver via myworkmachine
  RemoteForward 7022 192.168.4.2:22</pre>
<p>You can add a bunch of forwardings as shown above. Each entry will open the given port on cloud and forward it to the specified port on the specified machine. Now when you run &#8220;ssh tunnel&#8221; on your work machine, it will connect to cloud and set up the five port forwardings specified in your config file.</p>
<p>Then when logged in to cloud.example.com, you can do, for example, &#8220;ssh -p 7022 myserverlogin@localhost&#8221; to log into the machine called workserver.</p>
<p>If you mirror the remote forwardings in your home config file as local forwardings, then when you &#8220;ssh work&#8221; from home you can remote desktop to a windows machine from your home pc by doing &#8220;rdesktop -u myworkwinuser localhost:5389&#8243; and it will use the tunnel. (The connection will go from your home pc to cloud, to myworkmachine, to mywindowsbox.) The windows machine does not need to know anything about ssh.</p>


<p>Related posts:<ol><li><a href='http://blog.bstpierre.org/open-an-ssh-tunnel-in-four-seconds-or-less' rel='bookmark' title='Permanent Link: Open an SSH Tunnel in Four Seconds or Less'>Open an SSH Tunnel in Four Seconds or Less</a> <small>As I mentioned in a previous...</small></li><li><a href='http://blog.bstpierre.org/local-ssh-forwarding' rel='bookmark' title='Permanent Link: Use Local SSH Forwarding to Reduce the Number of Manual Hops'>Use Local SSH Forwarding to Reduce the Number of Manual Hops</a> <small>Local port forwarding is the same...</small></li><li><a href='http://blog.bstpierre.org/ssh-remote-port-forwarding-tunnels' rel='bookmark' title='Permanent Link: How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels'>How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels</a> <small>Ssh tunneling can be a bit...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bstpierre.org/ssh-forward-multiple-protocols-to-multiple-machines/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Open an SSH Tunnel in Four Seconds or Less</title>
		<link>http://blog.bstpierre.org/open-an-ssh-tunnel-in-four-seconds-or-less</link>
		<comments>http://blog.bstpierre.org/open-an-ssh-tunnel-in-four-seconds-or-less#comments</comments>
		<pubDate>Thu, 03 Dec 2009 15:28:47 +0000</pubDate>
		<dc:creator>Brian St. Pierre</dc:creator>
				<category><![CDATA[ssh]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[tool]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://blog.bstpierre.org/?p=233</guid>
		<description><![CDATA[As I mentioned in a previous post on ssh configuration, your config file can specify a variety settings for each server. In fact, the Hosts you use don't even have to exist! Consider the following snippet in your ~/.ssh/config.


Related posts:<ol><li><a href='http://blog.bstpierre.org/local-ssh-forwarding' rel='bookmark' title='Permanent Link: Use Local SSH Forwarding to Reduce the Number of Manual Hops'>Use Local SSH Forwarding to Reduce the Number of Manual Hops</a> <small>Local port forwarding is the same...</small></li><li><a href='http://blog.bstpierre.org/ssh-forward-multiple-protocols-to-multiple-machines' rel='bookmark' title='Permanent Link: Use SSH to Forward Multiple Protocols to Multiple Machines'>Use SSH to Forward Multiple Protocols to Multiple Machines</a> <small>Let's say you have a half-dozen...</small></li><li><a href='http://blog.bstpierre.org/ssh-remote-port-forwarding-tunnels' rel='bookmark' title='Permanent Link: How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels'>How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels</a> <small>Ssh tunneling can be a bit...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p><em>(This is part four in a <a href="../category/tools/ssh">series of posts on ssh</a>.)</em></p>
<p>As I mentioned in a previous post on <a href="http://blog.bstpierre.org/configure-ssh-username">ssh configuration</a>, your config file can specify a variety settings for each server.</p>
<p>In fact, the Hosts you use don&#8217;t even have to exist! (The HostName is the important part.) Consider the following snippet in your ~/.ssh/config.</p>
<pre>#
Host work
  HostName localhost
  User myworklogin
  IdentityFile ~/.ssh/id_dsa
  Port 4022
  RSAAuthentication yes
  PubkeyAuthentication yes
  LocalForward 4022 localhost:4022</pre>
<p>I&#8217;m going to assume remote forwarding is set up and the connection is open from work to cloud as described in <a href="http://blog.bstpierre.org/ssh-remote-port-forwarding-tunnels">this post on remote forwarding</a>; and you&#8217;ve got local forwarding set up from home to cloud as described in this post on <a href="http://blog.bstpierre.org/local-ssh-forwarding">local port forwarding</a>.</p>
<p>Now you can do &#8220;ssh work&#8221; from your home pc, and it will automatically log you into your work pc with the right credentials using the tunnel on cloud.example.com. And the scp example above simplifies to &#8220;scp work:/tmp/foo.txt ~/foo.txt&#8221; &#8212; you don&#8217;t have to remember the forwarded port numbers.</p>
<p>Typing &#8220;ssh work&#8221; is nine keystrokes (eight letters plus enter). If you can type 40 wpm, that&#8217;s 200 keystrokes per minute, or 3.33 keystrokes per second, which means you can open the tunnel in four seconds!</p>
<p>If you add &#8220;alias ssw=&#8217;ssh work&#8217;&#8221; to your ~/.bashrc, you&#8217;re down to four keystrokes.</p>


<p>Related posts:<ol><li><a href='http://blog.bstpierre.org/local-ssh-forwarding' rel='bookmark' title='Permanent Link: Use Local SSH Forwarding to Reduce the Number of Manual Hops'>Use Local SSH Forwarding to Reduce the Number of Manual Hops</a> <small>Local port forwarding is the same...</small></li><li><a href='http://blog.bstpierre.org/ssh-forward-multiple-protocols-to-multiple-machines' rel='bookmark' title='Permanent Link: Use SSH to Forward Multiple Protocols to Multiple Machines'>Use SSH to Forward Multiple Protocols to Multiple Machines</a> <small>Let's say you have a half-dozen...</small></li><li><a href='http://blog.bstpierre.org/ssh-remote-port-forwarding-tunnels' rel='bookmark' title='Permanent Link: How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels'>How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels</a> <small>Ssh tunneling can be a bit...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bstpierre.org/open-an-ssh-tunnel-in-four-seconds-or-less/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Use Local SSH Forwarding to Reduce the Number of Manual Hops</title>
		<link>http://blog.bstpierre.org/local-ssh-forwarding</link>
		<comments>http://blog.bstpierre.org/local-ssh-forwarding#comments</comments>
		<pubDate>Wed, 02 Dec 2009 15:12:19 +0000</pubDate>
		<dc:creator>Brian St. Pierre</dc:creator>
				<category><![CDATA[ssh]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[tool]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://blog.bstpierre.org/?p=219</guid>
		<description><![CDATA[Local port forwarding is the same as remote port forwarding but works in the opposite direction. An example is the clearest way to explain...


Related posts:<ol><li><a href='http://blog.bstpierre.org/ssh-remote-port-forwarding-tunnels' rel='bookmark' title='Permanent Link: How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels'>How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels</a> <small>Ssh tunneling can be a bit...</small></li><li><a href='http://blog.bstpierre.org/open-an-ssh-tunnel-in-four-seconds-or-less' rel='bookmark' title='Permanent Link: Open an SSH Tunnel in Four Seconds or Less'>Open an SSH Tunnel in Four Seconds or Less</a> <small>As I mentioned in a previous...</small></li><li><a href='http://blog.bstpierre.org/ssh-forward-multiple-protocols-to-multiple-machines' rel='bookmark' title='Permanent Link: Use SSH to Forward Multiple Protocols to Multiple Machines'>Use SSH to Forward Multiple Protocols to Multiple Machines</a> <small>Let's say you have a half-dozen...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p><em>(This is part three in a <a href="../category/tools/ssh">series of posts on ssh</a>.)</em></p>
<p>Local port forwarding is the same as <a title="How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels" href="http://blog.bstpierre.org/ssh-remote-port-forwarding-tunnels">remote port forwarding</a> but works in the opposite direction. An example is the clearest way to explain.</p>
<p>Assuming you&#8217;ve done the steps in the previous posts, then at home you can run &#8220;ssh -L 4022:localhost:4022 me@cloud.example.com&#8221;. This listens on TCP port 4022 on your home machine. Any connections there will be forwarded through the ssh connection to port 4022 on cloud&#8230; which, as we recall, gets forwarded to port 22 (ssh) at work. If you leave this connection open, you can run &#8220;ssh -p 4022 localhost&#8221; on your home machine and it will connect to work in just one hop. This means that you can use scp to copy files from home to work or vice versa. For example, &#8220;scp -P 4022 localhost:/tmp/foo.txt ~/foo.txt&#8221; will copy a file from work to home. (<em>Note: scp needs capital &#8220;-P&#8221; to give the port. I got it wrong the first time.</em>)</p>


<p>Related posts:<ol><li><a href='http://blog.bstpierre.org/ssh-remote-port-forwarding-tunnels' rel='bookmark' title='Permanent Link: How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels'>How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels</a> <small>Ssh tunneling can be a bit...</small></li><li><a href='http://blog.bstpierre.org/open-an-ssh-tunnel-in-four-seconds-or-less' rel='bookmark' title='Permanent Link: Open an SSH Tunnel in Four Seconds or Less'>Open an SSH Tunnel in Four Seconds or Less</a> <small>As I mentioned in a previous...</small></li><li><a href='http://blog.bstpierre.org/ssh-forward-multiple-protocols-to-multiple-machines' rel='bookmark' title='Permanent Link: Use SSH to Forward Multiple Protocols to Multiple Machines'>Use SSH to Forward Multiple Protocols to Multiple Machines</a> <small>Let's say you have a half-dozen...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bstpierre.org/local-ssh-forwarding/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels</title>
		<link>http://blog.bstpierre.org/ssh-remote-port-forwarding-tunnels</link>
		<comments>http://blog.bstpierre.org/ssh-remote-port-forwarding-tunnels#comments</comments>
		<pubDate>Tue, 01 Dec 2009 14:35:17 +0000</pubDate>
		<dc:creator>Brian St. Pierre</dc:creator>
				<category><![CDATA[ssh]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[tool]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://blog.bstpierre.org/?p=215</guid>
		<description><![CDATA[Ssh tunneling can be a bit mind bending at first, but it's simple when you get used to it.


Related posts:<ol><li><a href='http://blog.bstpierre.org/local-ssh-forwarding' rel='bookmark' title='Permanent Link: Use Local SSH Forwarding to Reduce the Number of Manual Hops'>Use Local SSH Forwarding to Reduce the Number of Manual Hops</a> <small>Local port forwarding is the same...</small></li><li><a href='http://blog.bstpierre.org/open-an-ssh-tunnel-in-four-seconds-or-less' rel='bookmark' title='Permanent Link: Open an SSH Tunnel in Four Seconds or Less'>Open an SSH Tunnel in Four Seconds or Less</a> <small>As I mentioned in a previous...</small></li><li><a href='http://blog.bstpierre.org/ssh-forward-multiple-protocols-to-multiple-machines' rel='bookmark' title='Permanent Link: Use SSH to Forward Multiple Protocols to Multiple Machines'>Use SSH to Forward Multiple Protocols to Multiple Machines</a> <small>Let's say you have a half-dozen...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p><em>(This is part two in a <a href="http://blog.bstpierre.org/category/tools/ssh">series of posts on ssh</a>.)</em></p>
<p>Ssh tunneling can be a bit mind bending at first, but it&#8217;s simple when you get used to it. Assume that you&#8217;re trying to ssh between two sites that do not allow incoming ssh. Maybe your IT at work is unenlightened and doesn&#8217;t have an ssh gateway. And your ISP has braindead configuration rules that don&#8217;t allow incoming ssh or they make it difficult.</p>
<p>What you need to get around this is a server &#8220;in the cloud&#8221; that permits ssh logins. This could be a hosting server that you pay for, or even a friend with an enlightened ISP who will give you a login account.</p>
<p>On your work PC, use ssh to login to the &#8220;cloud&#8221; server. Using the &#8220;-R&#8221; argument, you tell ssh to listen on a TCP port on the cloud server. Any connection coming in to this server will be forwarded back through the ssh connection to the TCP port you specify. For example, on mymachine.work.com, &#8220;ssh -R 4022:localhost:22 me@cloud.example.com&#8221; tells ssh to listen on cloud&#8217;s port 4022. Incoming connections to that port on cloud will be forwarded to port 22 (ssh) on mymachine.</p>
<p>By default, ssh will only listen to port 4022 on cloud&#8217;s localhost interface. So to log in to work, you will first need to log into cloud, and then use &#8220;ssh -p 4022 myworklogin@localhost&#8221; to log into work.</p>
<p>We&#8217;ll work around this limitation in the next post in this series.</p>


<p>Related posts:<ol><li><a href='http://blog.bstpierre.org/local-ssh-forwarding' rel='bookmark' title='Permanent Link: Use Local SSH Forwarding to Reduce the Number of Manual Hops'>Use Local SSH Forwarding to Reduce the Number of Manual Hops</a> <small>Local port forwarding is the same...</small></li><li><a href='http://blog.bstpierre.org/open-an-ssh-tunnel-in-four-seconds-or-less' rel='bookmark' title='Permanent Link: Open an SSH Tunnel in Four Seconds or Less'>Open an SSH Tunnel in Four Seconds or Less</a> <small>As I mentioned in a previous...</small></li><li><a href='http://blog.bstpierre.org/ssh-forward-multiple-protocols-to-multiple-machines' rel='bookmark' title='Permanent Link: Use SSH to Forward Multiple Protocols to Multiple Machines'>Use SSH to Forward Multiple Protocols to Multiple Machines</a> <small>Let's say you have a half-dozen...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bstpierre.org/ssh-remote-port-forwarding-tunnels/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to Tell SSH Who You Are</title>
		<link>http://blog.bstpierre.org/configure-ssh-username</link>
		<comments>http://blog.bstpierre.org/configure-ssh-username#comments</comments>
		<pubDate>Mon, 30 Nov 2009 15:11:10 +0000</pubDate>
		<dc:creator>Brian St. Pierre</dc:creator>
				<category><![CDATA[ssh]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[tool]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://blog.bstpierre.org/?p=222</guid>
		<description><![CDATA[Do you log in to several servers with different usernames via ssh? Save typing by telling ssh which username to use on each server.


Related posts:<ol><li><a href='http://blog.bstpierre.org/open-an-ssh-tunnel-in-four-seconds-or-less' rel='bookmark' title='Permanent Link: Open an SSH Tunnel in Four Seconds or Less'>Open an SSH Tunnel in Four Seconds or Less</a> <small>As I mentioned in a previous...</small></li><li><a href='http://blog.bstpierre.org/ssh-remote-port-forwarding-tunnels' rel='bookmark' title='Permanent Link: How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels'>How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels</a> <small>Ssh tunneling can be a bit...</small></li><li><a href='http://blog.bstpierre.org/ssh-forward-multiple-protocols-to-multiple-machines' rel='bookmark' title='Permanent Link: Use SSH to Forward Multiple Protocols to Multiple Machines'>Use SSH to Forward Multiple Protocols to Multiple Machines</a> <small>Let's say you have a half-dozen...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>Ssh has amazing capabilities that you probably aren&#8217;t using on a daily basis.</p>
<p>The capability that you probably aren&#8217;t using, and the easiest to use, is customizing your config file (in ~/.ssh/config) for the various servers you log into.</p>
<p>For example, I frequently log into about ten different servers using at least four different usernames. By default, if I type &#8220;ssh server&#8221; the client will use my login name on the client machine to try to log into the server &#8212; which is usually wrong. Instead you can <a href="http://superuser.com/questions/64996/how-to-make-ssh-log-in-as-the-right-user">tell your ssh client which username to use on each server</a>. (Thanks to <a href="http://wblinks.com/">Rich Adams</a> for the tip.)</p>
<p>You can customize a variety of settings &#8212; not just the username. For example, I specify a different identity file for a couple of servers.</p>
<p>This saves a bunch of typing and occasional confusion. (By avoiding login errrors as I try to log into a server using the wrong username and can&#8217;t figure out why my password isn&#8217;t working&#8230;)</p>
<p><em>(This is the first post in <a href="../category/tools/ssh">series of posts about how to get the most out of ssh</a>. Make sure you don&#8217;t miss the rest of the series: <a href="http://feeds2.feedburner.com/TheDailyBuild">subscribe to my feed</a> or <a href="http://twitter.com/bstpierre">follow me on twitter</a>.)</em></p>


<p>Related posts:<ol><li><a href='http://blog.bstpierre.org/open-an-ssh-tunnel-in-four-seconds-or-less' rel='bookmark' title='Permanent Link: Open an SSH Tunnel in Four Seconds or Less'>Open an SSH Tunnel in Four Seconds or Less</a> <small>As I mentioned in a previous...</small></li><li><a href='http://blog.bstpierre.org/ssh-remote-port-forwarding-tunnels' rel='bookmark' title='Permanent Link: How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels'>How to Use SSH Remote Port Forwarding to Set Up Secure Tunnels</a> <small>Ssh tunneling can be a bit...</small></li><li><a href='http://blog.bstpierre.org/ssh-forward-multiple-protocols-to-multiple-machines' rel='bookmark' title='Permanent Link: Use SSH to Forward Multiple Protocols to Multiple Machines'>Use SSH to Forward Multiple Protocols to Multiple Machines</a> <small>Let's say you have a half-dozen...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bstpierre.org/configure-ssh-username/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>3 Easy Ways to Stick to a Coding Standard</title>
		<link>http://blog.bstpierre.org/3-easy-ways-to-stick-to-a-coding-standard</link>
		<comments>http://blog.bstpierre.org/3-easy-ways-to-stick-to-a-coding-standard#comments</comments>
		<pubDate>Tue, 25 Aug 2009 18:40:58 +0000</pubDate>
		<dc:creator>Brian St. Pierre</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[codereview]]></category>
		<category><![CDATA[software-engineering]]></category>
		<category><![CDATA[tool]]></category>

		<guid isPermaLink="false">http://blog.bstpierre.org/?p=192</guid>
		<description><![CDATA[When you&#8217;re writing python, you don&#8217;t need a lot of debate over the minutiae of most coding standards. PEP 8 does that for you. Even better, there are some tools that make it really easy to stick to the standard.
Why do this? Well, for one thing it makes code reviews easier when everyone follows the [...]


Related posts:<ol><li><a href='http://blog.bstpierre.org/who-else-wants-better-short-term-memory' rel='bookmark' title='Permanent Link: Who Else Wants Better Short Term Memory?'>Who Else Wants Better Short Term Memory?</a> <small> In &#8220;Talent is Overrated&#8221;, Geoff...</small></li><li><a href='http://blog.bstpierre.org/using-pythons-ctypes-to-make-system-calls' rel='bookmark' title='Permanent Link: Using Python&#8217;s ctypes to Call Into C Libraries'>Using Python&#8217;s ctypes to Call Into C Libraries</a> <small>The ctypes module makes loading and...</small></li><li><a href='http://blog.bstpierre.org/data-vs-code' rel='bookmark' title='Permanent Link: Data vs Code'>Data vs Code</a> <small> I&#8217;ll take an array over...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>When you&#8217;re writing python, you don&#8217;t need a lot of debate over the minutiae of most coding standards. <a href="http://www.python.org/dev/peps/pep-0008/">PEP 8</a> does that for you. Even better, there are some tools that make it really easy to stick to the standard.</p>
<p>Why do this? Well, for one thing it makes code reviews easier when everyone follows the same conventions. It also makes maintenance easier.</p>
<ol>
<li><a href="http://github.com/cburroughs/pep8.py/tree/master">pep8.py</a> is a style checker that enforces the rules of PEP 8. The &#8220;official home&#8221; (?) <a href="http://svn.browsershots.org/trunk/devtools/pep8/pep8.py">at browsershots.org </a>was dead as I was writing this. (Thanks GitHub!) Run pep8.py on your code and it will tell you where you&#8217;ve drifted from the standard.</li>
<li><a href="http://www.logilab.org/857">pylint</a> is lint for python. It provides more functionality than pep8.py, but is not a strict superset. (pep8.py is pickier about whitespace issues.) Pylint is also configurable to enforce various naming rules. Like most lints, the SNR is pretty low, but you can turn off most of the noise and get a reasonable signal for the things you want to check.</li>
<li>Subversion (as well as most other tools) can be configured to run a script every time you check in code. Run one or both of the above tools in the pre-commit hook and bad code will be rejected. (I&#8217;d be wary of doing this with pylint unless you&#8217;ve got the categories of &#8220;noisy&#8221; warnings turned off.) I don&#8217;t have anything cookbook for this yet, but I&#8217;m working on it&#8230;</li>
</ol>


<p>Related posts:<ol><li><a href='http://blog.bstpierre.org/who-else-wants-better-short-term-memory' rel='bookmark' title='Permanent Link: Who Else Wants Better Short Term Memory?'>Who Else Wants Better Short Term Memory?</a> <small> In &#8220;Talent is Overrated&#8221;, Geoff...</small></li><li><a href='http://blog.bstpierre.org/using-pythons-ctypes-to-make-system-calls' rel='bookmark' title='Permanent Link: Using Python&#8217;s ctypes to Call Into C Libraries'>Using Python&#8217;s ctypes to Call Into C Libraries</a> <small>The ctypes module makes loading and...</small></li><li><a href='http://blog.bstpierre.org/data-vs-code' rel='bookmark' title='Permanent Link: Data vs Code'>Data vs Code</a> <small> I&#8217;ll take an array over...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bstpierre.org/3-easy-ways-to-stick-to-a-coding-standard/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Makefiles are Software Too</title>
		<link>http://blog.bstpierre.org/makefiles-are-software-too</link>
		<comments>http://blog.bstpierre.org/makefiles-are-software-too#comments</comments>
		<pubDate>Tue, 14 Apr 2009 03:17:48 +0000</pubDate>
		<dc:creator>Brian St. Pierre</dc:creator>
				<category><![CDATA[engineering]]></category>
		<category><![CDATA[software-engineering]]></category>
		<category><![CDATA[tool]]></category>

		<guid isPermaLink="false">http://blog.bstpierre.org/?p=173</guid>
		<description><![CDATA[This post was inspired by recent experience with some horrible build scripts from the open source world &#8212; but I&#8217;ve seen enough in-house badness over the years that I wanted to establish some basic parameters for build scripts.
This is a really broad way to divide the world, but I see two important categories of build [...]


Related posts:<ol><li><a href='http://blog.bstpierre.org/must-have-tools-software-teams' rel='bookmark' title='Permanent Link: 9 &#8220;Must-Have&#8221; Tools for Software Teams'>9 &#8220;Must-Have&#8221; Tools for Software Teams</a> <small> The items below are useful...</small></li><li><a href='http://blog.bstpierre.org/lenny-jaunty-packages' rel='bookmark' title='Permanent Link: Using Lenny to Build Jaunty Packages'>Using Lenny to Build Jaunty Packages</a> <small> &lt;shameless_plug&gt; I&#8217;m in the middle...</small></li><li><a href='http://blog.bstpierre.org/3-easy-ways-to-stick-to-a-coding-standard' rel='bookmark' title='Permanent Link: 3 Easy Ways to Stick to a Coding Standard'>3 Easy Ways to Stick to a Coding Standard</a> <small> When you&#8217;re writing python, you...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>This post was inspired by recent experience with some horrible build scripts from the open source world &mdash; but I&#8217;ve seen enough in-house badness over the years that I wanted to establish some basic parameters for build scripts.</p>
<p>This is a really broad way to divide the world, but I see two important categories of build scripts. (By &#8220;build script&#8221; I mean Makefiles, SConsfiles, Ant files, and their ilk).</p>
<ol>
<li>Build scripts intended for in-house use, never seen by outsiders.</li>
<li>Build scripts that you distribute to external users.</li>
</ol>
<p>Both sets of build scripts are important. Let&#8217;s consider the build script (or Makefile system, or whatever you&#8217;re using) as a software system independent of the software that is being built. Its primary requirement is to reliably convert your source code into an executable. Any decent build script has numerous other requirements, most of which are probably implied. I have never seen a written requirement for the numerous build scripts I&#8217;ve written. I have only rarely heard them discussed &mdash; and never actually posed as &#8220;requirements&#8221;.</p>
<p>I have, always taken the following meta-requirements for granted. Based on my experience with some fairly awful build scripts, I guess these aren&#8217;t universally acknowledged.</p>
<ul>
<li>The build script should build all the &#8220;normal&#8221; executables with a single command.</li>
<li>The build script must encapsulate all environment variables within the script. (This is a corollary of the above.)</li>
<li>The build script should not unnecessarily rebuild source code in a directory tree that has previously been built. (This is <tt>make</tt>&#8217;s raison d&#8217;etre.)</li>
<li>The build script should be documented. It doesn&#8217;t have to be elaborate, but a five-line comment at the top of the script describing the available command-line variables would be nice.</li>
<li><tt>make clean</tt> or its equivalent must work reliably.</li>
<li>It should rarely be necessary to run <tt>make clean</tt>.</li>
<li>Bonus: the build should be parallelizable, to be able to take advantage of multicore machines and/or distributed builds.</li>
</ul>
<p>Back to those two categories. If you screw up an in-house build script, it&#8217;s primarily your team that&#8217;s going to suffer. I&#8217;m not aware of any bugs from SQA or Customers on projects I&#8217;ve been on that were traced back to a build script, but I can see where it could happen. Mainly what I&#8217;ve seen is developers habitually wasting time rebuilding source that should not need to be rebuilt. The worst offender in this respect was a build script that forced a &#8220;make clean&#8221; at the beginning of every build. In the immortal words of Dave Barry, I&#8217;m not making this up. Really.</p>
<p>(Actually, I think it was even worse when I was dealing with a build script that required a &#8220;make clean&#8221; every time around but didn&#8217;t have it coded into the script!)</p>
<p>I can&#8217;t say I have a completely clean conscience in this area: I wrote a big pile of Makefiles for a past employer in which I unknowingly used features (bugs?) of a specific version of GNU Make that were &#8220;fixed&#8221; in a subsequent version. As time went on it became (a) a much bigger task to fix the Makefile code that used the &#8220;feature&#8221; and (b) harder to keep the specific version of GNU Make that worked with the Makefiles! I imagine they&#8217;re still stuck with this situation&#8230; sorry guys.</p>
<p>In the second category, when you toss a slapped-together build script to your unsuspecting users you do all of human society a disservice. Now they are not only wasting their time fighting with a bad build script, but they often have the disadvantage of being unable to contact the author directly for support or commiserate with other experienced users of the system.</p>
<p>So do us all a favor: if you don&#8217;t know what you&#8217;re doing when you start to write your next build script, please ask for help. Otherwise we&#8217;ll have to resort to some sort of professional licensing scheme for build script authors.</p>


<p>Related posts:<ol><li><a href='http://blog.bstpierre.org/must-have-tools-software-teams' rel='bookmark' title='Permanent Link: 9 &#8220;Must-Have&#8221; Tools for Software Teams'>9 &#8220;Must-Have&#8221; Tools for Software Teams</a> <small> The items below are useful...</small></li><li><a href='http://blog.bstpierre.org/lenny-jaunty-packages' rel='bookmark' title='Permanent Link: Using Lenny to Build Jaunty Packages'>Using Lenny to Build Jaunty Packages</a> <small> &lt;shameless_plug&gt; I&#8217;m in the middle...</small></li><li><a href='http://blog.bstpierre.org/3-easy-ways-to-stick-to-a-coding-standard' rel='bookmark' title='Permanent Link: 3 Easy Ways to Stick to a Coding Standard'>3 Easy Ways to Stick to a Coding Standard</a> <small> When you&#8217;re writing python, you...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bstpierre.org/makefiles-are-software-too/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Toolkit of a Software Engineer</title>
		<link>http://blog.bstpierre.org/the-toolkit-of-a-software-engineer</link>
		<comments>http://blog.bstpierre.org/the-toolkit-of-a-software-engineer#comments</comments>
		<pubDate>Thu, 05 Feb 2009 21:48:30 +0000</pubDate>
		<dc:creator>Brian St. Pierre</dc:creator>
				<category><![CDATA[tools]]></category>
		<category><![CDATA[tool]]></category>

		<guid isPermaLink="false">http://blog.bstpierre.org/the-toolkit-of-a-software-engineer</guid>
		<description><![CDATA[This is a rundown of the things you should have in your toolkit &#8212; doesn&#8217;t matter whether you call yourself a software engineer, programmer, developer, code monkey, etc.
Editor
You must have an excellent editor. It should slice, dice, puree and mince, all with minimal effort. Seriously, it should have support for searching across files, &#8220;tags&#8221; (jumping [...]


Related posts:<ol><li><a href='http://blog.bstpierre.org/must-have-tools-software-teams' rel='bookmark' title='Permanent Link: 9 &#8220;Must-Have&#8221; Tools for Software Teams'>9 &#8220;Must-Have&#8221; Tools for Software Teams</a> <small> The items below are useful...</small></li><li><a href='http://blog.bstpierre.org/3-easy-ways-to-stick-to-a-coding-standard' rel='bookmark' title='Permanent Link: 3 Easy Ways to Stick to a Coding Standard'>3 Easy Ways to Stick to a Coding Standard</a> <small> When you&#8217;re writing python, you...</small></li><li><a href='http://blog.bstpierre.org/lenny-jaunty-packages' rel='bookmark' title='Permanent Link: Using Lenny to Build Jaunty Packages'>Using Lenny to Build Jaunty Packages</a> <small> &lt;shameless_plug&gt; I&#8217;m in the middle...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>This is a rundown of the things you should have in your toolkit &#8212; doesn&#8217;t matter whether you call yourself a software engineer, programmer, developer, code monkey, etc.</p>
<h2>Editor</h2>
<p>You must have an excellent editor. It should slice, dice, puree and mince, all with minimal effort. Seriously, it should have support for searching across files, &#8220;tags&#8221; (jumping to the definition of an identifier), ideally provide tooltips for function calls while you&#8217;re writing, automatic template generation, and pushbutton compilation that can step you through the list of compile errors, if any.</p>
<p>Pick a good editor, and become an expert at using it. It&#8217;s worth the investment.</p>
<h2>Toolchain (Compiler)</h2>
<p>I can&#8217;t really say compiler any more, since many of the languages we&#8217;re using aren&#8217;t compiled in the traditional sense. So instead I&#8217;ll call this the toolchain. For your chosen language, you need to choose the most appropriate toolchain. It may sometimes seem like you don&#8217;t have much choice: there&#8217;s only one python, right? Wrong. You have the choice of targeting different platforms (CPython, Jython or IronPython), and also of choosing the version you&#8217;ll use. You may need to choose an older version so that you can match what&#8217;s installed on your hosting provider. You may even need to keep around multiple versions &mdash; maybe you&#8217;re a library writer and need to ensure portability across various versions.</p>
<p>Things that are part of your toolchain: compiler or interpreter and runtime. In other words, whatever it takes to make the software run on your customers&#8217; computer.</p>
<h2>Version Control</h2>
<p>AKA VC, software configuration management (SCM), source control. This is a tool that keeps track of the various versions of your software and allows you to work effectively with other engineers. There are a number of different VC tools, with a wide variety of features, complexity and costs.</p>
<p>If you haven&#8217;t used VC before, take a look at <a href="http://subversion.tigris.org/">subversion</a>. It&#8217;s free (open source), widely used, easy to install and use, and stable. There are other tools that may have better technical merits, especially for certain environments, but I think subversion is the best place to start from an ease-of-learning perspective.</p>
<h2>Build</h2>
<p>For your software to have value for your customers, you need to be able to convert program text into executable software. If your software is a one-file script, maybe all you need to do is publish it to your website. In this is the case, you&#8217;re allowed a pass on having a build tool, but you should still consider an automated solution.</p>
<p>If you have to deliver something more complex, an automated build tool is required.</p>
<p>Even if you&#8217;re just publishing a handful of scripts to your website as a tar or zip file, you still need to perform the following: gather the scripts, tar them, name the tarball something sensible, and upload. Do this by hand, and eventually you will skip a step and your customers will end up downloading an unusable mess.</p>
<p>At the opposite extreme, you may have hundreds of files that need to be compiled into a handful of libraries and then linked into an executable. You may have dozens of dependencies on external libraries. Translations to other natural languages. All of this needs to be portable across a dozen platforms.</p>
<p>This is why &quot;make&quot; was invented, and why other tools with similar goals continue to evolve to solve these complex problems. Ant, Maven, Scons, an endless parade of Make variants, etc. Pick the build tool that best works with your toolchain and specific situation.</p>
<h2>Review</h2>
<p>You need a way to review your work. If you&#8217;re working alone, it may be enough to simply review your work in your editor &mdash; though I&#8217;d recommend at least printing it out. For whatever reason, it seems harder / less effective to review a work product in the medium that produced it. A better alternative may be to use the view / diff functionality in your VC tool.</p>
<p>If you&#8217;re working with others, it will be helpful to <a href="http://blog.bstpierre.org/code-review-tools">install a code review tool</a> that helps package your work product, distribute it to your peers for review, and manage feedback.</p>
<h2>Test</h2>
<p>Some languages come with support for unit test built in &mdash; python includes it in the standard library. You can find a handful of different libraries for c++, and for <a href="http://www.xprogramming.com/software.htm">seemingly any other programming language known to man</a>.</p>
<p>Your testing needs may also require a framework like selenium, which allows automated testing in a web browser.</p>
<p>If you&#8217;re doing embedded software, you&#8217;re probably going to have to jump through a bunch of hoops to automate your testing. Unfortunately, you&#8217;ll have to figure out how big the hoops are, how many you need, how far off the ground they need to be, whether they should be electrified, and then you&#8217;ll have to build them yourself. Annoying, but very much worth it in the end.</p>
<h2>Continuous Integration / Automated Build</h2>
<p>Again: if you&#8217;re working alone you can skip this, though I still think it&#8217;s useful. To be clear, &#8220;continuous integration&#8221; is more than a tool. It&#8217;s a way of life. However, this post is about your toolkit, and CI is a very useful category of tool. There are a number of <a href="http://blog.bstpierre.org/continuous-integration-tool-roundup">different CI tools available</a>, each with a slightly different focus and set of features. Pick the tool that has the features you need, connect it to your VC system, and enjoy the automation.</p>
<h2>Lint</h2>
<p>For those of you who aren&#8217;t familiar, lint is an old-school tool for finding potential trouble spots in C code. There are many tools available for C and other programming languages that help to sniff out trouble spots in code. Some tools can even spot design anti-patterns. C has lint. Python has pylint. Coverity Prevent is a commercial tool (expensive) that can find deep bugs in C, C++ and Java.</p>
<p>I don&#8217;t want to advocate sloppy programming practices: you shouldn&#8217;t <em>need</em> to run lint on your code. But if there&#8217;s a tool available that can effectively remove defects from my software, I&#8217;m going to use it.</p>
<p>(&#8220;Effective&#8221; defined to mean costing less to remove defects than some alternative, which is often either system testing or &quot;customer testing&quot;. Before you go spending tons of money on an expensive lint, are you doing code reviews? This is an extremely cost effective practice. Spend your time and money there first.)</p>
<p>I&#8217;ll continue this in another post. Meanwhile, what&#8217;s in your toolkit? Favorites from the categories above? Categories of software tools that you want to make sure I don&#8217;t miss?</p>


<p>Related posts:<ol><li><a href='http://blog.bstpierre.org/must-have-tools-software-teams' rel='bookmark' title='Permanent Link: 9 &#8220;Must-Have&#8221; Tools for Software Teams'>9 &#8220;Must-Have&#8221; Tools for Software Teams</a> <small> The items below are useful...</small></li><li><a href='http://blog.bstpierre.org/3-easy-ways-to-stick-to-a-coding-standard' rel='bookmark' title='Permanent Link: 3 Easy Ways to Stick to a Coding Standard'>3 Easy Ways to Stick to a Coding Standard</a> <small> When you&#8217;re writing python, you...</small></li><li><a href='http://blog.bstpierre.org/lenny-jaunty-packages' rel='bookmark' title='Permanent Link: Using Lenny to Build Jaunty Packages'>Using Lenny to Build Jaunty Packages</a> <small> &lt;shameless_plug&gt; I&#8217;m in the middle...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bstpierre.org/the-toolkit-of-a-software-engineer/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
