<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8111070121637504701</id><updated>2024-09-21T07:56:30.998-05:00</updated><category term="bash"/><category term="bash shell"/><category term="best practices"/><category term="clearcase"/><category term="corporate policies"/><category term="guide"/><category term="intro"/><category term="joelonsoftware"/><category term="key servers"/><category term="mercurial"/><category term="parallel processing"/><category term="password"/><category term="process"/><category term="process managment"/><category term="scm"/><category term="scripts"/><category term="security"/><category term="shell"/><category term="ssh"/><category term="ssh-agent"/><category term="subversion"/><category term="summary"/><category term="vcs"/><title type='text'>Insights into Software</title><subtitle type='html'>Observations on software: from &quot;State of the Nation&quot; to nitty-gritty technical details.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://insights-into-software.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8111070121637504701/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://insights-into-software.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Kevin L. Sitze</name><uri>http://www.blogger.com/profile/03893988495184767671</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>5</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8111070121637504701.post-3945317017763543602</id><published>2010-04-01T15:14:00.009-05:00</published><updated>2010-04-01T21:46:36.831-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="best practices"/><category scheme="http://www.blogger.com/atom/ns#" term="clearcase"/><category scheme="http://www.blogger.com/atom/ns#" term="joelonsoftware"/><category scheme="http://www.blogger.com/atom/ns#" term="mercurial"/><category scheme="http://www.blogger.com/atom/ns#" term="scm"/><category scheme="http://www.blogger.com/atom/ns#" term="subversion"/><category scheme="http://www.blogger.com/atom/ns#" term="vcs"/><title type='text'>Distributed version control</title><content type='html'>Recently, &lt;a href=&quot;http://www.joelonsoftware.com/&quot;&gt;Joel on Software&lt;/a&gt; published a blog &lt;a href=&quot;http://www.joelonsoftware.com/items/2010/03/17.html&quot;&gt;entry&lt;/a&gt; discussing the advantages a distributed version control system [DVCS] has over a version control system [VCS] with its dependency on a central repository. &amp;nbsp;The key point, Joel says, is that &quot;with distributed version control, the distributed part is actually not the most interesting part,&quot; but &quot;that these systems think in terms of changes, not in terms of versions.&quot; &amp;nbsp;Joel doesn&#39;t get it.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
There is no magic merge bullet going on here; &lt;a href=&quot;http://mercurial.selenic.com/&quot;&gt;Mercurial&lt;/a&gt; (which has a great &lt;a href=&quot;http://www.thefreedictionary.com/mercurial&quot;&gt;name&lt;/a&gt; (see definition 4)) doesn&#39;t track every refactoring operation the developer performs. &amp;nbsp;It doesn&#39;t know (or care) that the developer moved a function from file A to file B. &amp;nbsp;Rather, just like any other VCS it simply tracks the changes to the individual files A and B. &amp;nbsp;While it can and should know that stuff was removed from file A and that stuff was added to file B, it cannot and should not know whether what was removed from A was transferred over to B. &amp;nbsp;So, what is it that really differentiates a DVCS from other VCS applications?&lt;br /&gt;
&lt;br /&gt;
According to Joel&#39;s own Mercurial &lt;a href=&quot;http://hginit.com/&quot;&gt;manual&lt;/a&gt; the developer should use the tool as follows:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;check in often&lt;/li&gt;
&lt;li&gt;branch to test new approaches (branch to spike)&lt;/li&gt;
&lt;li&gt;synchronize branches quickly&lt;/li&gt;
&lt;li&gt;propagate changes (push and pull) often&lt;/li&gt;
&lt;li&gt;add new code into the VCS quickly&lt;/li&gt;
&lt;/ol&gt;Now, here&#39;s the interesting thing. &amp;nbsp;All of these are factors described as &quot;&lt;a href=&quot;http://www.sts.tu-harburg.de/intranet/perforce/bestpractices/index.html&quot;&gt;best practices&lt;/a&gt;&quot; for &lt;a href=&quot;http://en.wikipedia.org/wiki/Software_configuration_management&quot;&gt;Software Configuration Management&lt;/a&gt; [SCM]. &amp;nbsp;What a surprise.&lt;br /&gt;
&lt;br /&gt;
It isn&#39;t (just) about whether or not the tool tracks changesets or file versions, it is about whether the tool facilitates best practices for SCM. &amp;nbsp;It turns out that Mercurial does an outstanding job across the board:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;it makes cloning (branching) incredibly fast and easy. &amp;nbsp;This encourages developers to branch quickly and often when working on spikes or adding new features.&lt;/li&gt;
&lt;li&gt;it makes pushing and pulling fast and easy. &amp;nbsp;This reduces the probability of sharing workspaces and allows easy synchronization of new code between developers.&lt;/li&gt;
&lt;li&gt;it differentiates between commits (which are local to the current repository) and push/pulls (where code is shared). &amp;nbsp;This encourages developers to commit more frequently, because the fear of &quot;breaking the build&quot; is removed.&lt;/li&gt;
&lt;li&gt;it separates the operation of pulling changes from other developers and merging those changes into your own repository. &amp;nbsp;This means that a developer can accept a change to their repository at any time without having to worry about breaking their own build, until such time they are ready to perform the merge.&lt;/li&gt;
&lt;li&gt;it enables developers working on a new feature to distribute changes between themselves without affecting the central repository (yes, CRs are allowed in Mercurial, they just don&#39;t take as &quot;central&quot; a &quot;role&quot; as with VCS tools). &amp;nbsp;Again, fear of &quot;breaking the build&quot; is completely removed.&lt;/li&gt;
&lt;li&gt;it does an outstanding job merging changes, in part because merges occur more frequently than in other systems, and in part because it does have an excellent merge algorithm.&lt;/li&gt;
&lt;/ol&gt;I find it interesting that SCM best practices have been around for many years (the above abstract and its corresponding paper were written over a decade ago), but they are not well understood in the developer community. &amp;nbsp;Developers have been repeatedly told that using some kind of VCS is good, the problem has been simply getting developers on-board with this. &amp;nbsp;SCM suffers because most VCSs available actually discourage their use.&lt;br /&gt;
&lt;br /&gt;
For example, compare Mercurial with &lt;a href=&quot;http://subversion.tigris.org/&quot;&gt;Subversion&lt;/a&gt; (a popular open-source VCS).&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;the latter has no cloning operation, to &quot;clone&quot; a repository requires performing a complete checkout of the source tree from the Central Repository [CR]. &amp;nbsp;Checking code out from the CR is a lengthy operation, because full copies of everything has to be transferred (probably across a network) to your development machine.&lt;/li&gt;
&lt;li&gt;the Mercurial &quot;clone&quot; operation actually creates a new branch. &amp;nbsp;In Subversion you &quot;copy&quot; an entire directory tree to another location in your repository. &amp;nbsp;The former is local, the latter requires interaction with the CR, which means that a branch in Subversion is forever embedded in the SVN database, even if it was for a spike.&lt;/li&gt;
&lt;li&gt;it has no concept of push/pull, you commit code directly to the CR. &amp;nbsp;The only way to get new code to other developers are either through creating and emailing diffs (that may or may not break when applied to their repository, depending on the changes they made) or by committing your changes. &amp;nbsp;The former is painful, the latter raises the specter of breaking the build and is hence relatively distasteful.&lt;/li&gt;
&lt;li&gt;it has no concept of a &quot;local&quot; commit, the only mechanism available to the developer to &quot;place a stake in the ground&quot; is to commit code to the CR. &amp;nbsp;Again, this raises the specter of breaking the build.&lt;/li&gt;
&lt;li&gt;it requires that changes must be merged prior to the next commit. &amp;nbsp;If you branch then merging isn&#39;t required, but branches are more painful to use, and are merged less frequently.&lt;/li&gt;
&lt;/ol&gt;As you can see the central role that the CR takes with Subversion actually hurts. &amp;nbsp;I know from personal experience that I tend to refrain from checking stuff in for long periods of time when working in the Subversion realm. &amp;nbsp;I&#39;m going out on a limb here, but I suspect this is a common problem among developers. &amp;nbsp;We have heard for years that &quot;breaking the build&quot; is bad so the natural tendency is to avoid doing things that might break the build, like committing changes to a CR.&lt;br /&gt;
&lt;br /&gt;
In any case, using Subversion (and similar VCS tools) actually reduces the likely-hood of the developer to use SCM best practices because proper use of the VCS actually encourages you to do things that cause pain. &amp;nbsp;DVCS tools, on the other hand, makes the branching to explore new ideas and add new features a natural, meaningful way of thinking and working with your code. &amp;nbsp;That is the real reason that DVCS tools deserve praise.</content><link rel='replies' type='application/atom+xml' href='http://insights-into-software.blogspot.com/feeds/3945317017763543602/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insights-into-software.blogspot.com/2010/04/distributed-version-control.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8111070121637504701/posts/default/3945317017763543602'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8111070121637504701/posts/default/3945317017763543602'/><link rel='alternate' type='text/html' href='http://insights-into-software.blogspot.com/2010/04/distributed-version-control.html' title='Distributed version control'/><author><name>Kevin L. Sitze</name><uri>http://www.blogger.com/profile/03893988495184767671</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8111070121637504701.post-5049634136048254424</id><published>2010-03-30T19:23:00.007-05:00</published><updated>2010-04-01T21:46:00.180-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="corporate policies"/><category scheme="http://www.blogger.com/atom/ns#" term="guide"/><category scheme="http://www.blogger.com/atom/ns#" term="password"/><category scheme="http://www.blogger.com/atom/ns#" term="security"/><title type='text'>Introduction to security via password policies</title><content type='html'>Security is an enormously complicated topic and it has a surprisingly large number of subtopics. &amp;nbsp;Security, at the 10,000 meters level, is all about making sure that a person or program (the privileged user) that should have access to some data, information, program, system or physical location (the asset) can obtain such access reasonably quickly and easily, with a common caveat that such access is logged and recorded. &amp;nbsp;Every other individual or program (the attacker) that may deliberately or accidentally attempt to obtain access is &quot;satisfactory&quot; denied, with a similar caveat that as much information as possible about the denied access is also logged and recorded.  Here we explore how and why corporations rely on passwords. &lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Perhaps unsurprisingly this process of allowing one group of individuals access to something, while denying other groups (i.e., everyone else) creates a dichotomy between ease of access and level of protection. &amp;nbsp;The easier you make it for the &quot;good&quot; group to access the protected asset, the less likely it is that you will be able to deny access to every member of the &quot;bad&quot; group (hence the &quot;satisfactory&quot; part in the original definition). &amp;nbsp;If you want to deny access to 100% of everyone in the &quot;bad&quot; group, you are correspondingly going to make it quite difficult for members of the &quot;good&quot; group to gain access. &amp;nbsp;This give and take between the &quot;control&quot; and &quot;access&quot; of controlled access to assets is pretty much true at all levels of security. &amp;nbsp;What this implies is that security is not a destination, it is a multi-layered synthesis of processes and principals all working (hopefully) together for the common goal of protecting assets.  For the curious, &lt;a href=&quot;http://www.sans.org/security-resources/glossary.php&quot;&gt;here&lt;/a&gt; is a glossary of security related terms.&lt;br /&gt;
&lt;br /&gt;
With this baseline introduction to security in place, I wish to focus on the security subtopic commonly known as &quot;passwords&quot; (alternative labels include &quot;passphrase,&quot; &quot;passcode,&quot; &quot;keyphrase&quot;, &quot;keys&quot; and several other pseudonyms) &amp;nbsp;In this case the asset protected is typically a digital asset, and the password is the key to the protection mechanism; in such a system passwords are the first (and, unfortunately, often the only) line of defense. &amp;nbsp;A privileged user is authenticated to access the asset (given permission) by virtue of knowing the password. &amp;nbsp;Other users are denied access by virtue of not knowing or not being able to guess the password. &amp;nbsp;Note that access to the protected asset might be obtained through other means, but this would require a detailed discussion of protection mechanisms that is not really suitable here.&lt;br /&gt;
&lt;br /&gt;
Attributes of Effective Passwords&lt;br /&gt;
&lt;br /&gt;
Already we can gain quite a bit of insight into the strengths and weakness of a system that uses  passwords to authenticate users.&lt;br /&gt;
&lt;br /&gt;
Passwords are more effective when...&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;they are more complicated (random) because this makes them harder to guess.&lt;/li&gt;
&lt;li&gt;what each one protects is limited in scope because fewer assets protected by the password means less assets are at risk if a password attack is successful.&lt;/li&gt;
&lt;li&gt;fewer people know a password because there is less risk of exposure, accidental or deliberate. &amp;nbsp;For critically important passwords this has the disadvantage that an attacker can choose a narrower focus of attack - one reason the U.S. President wanders around with Secret Service bodyguards all the time, a good thing since he holds the primary key to the USA nuclear arsenal.&lt;/li&gt;
&lt;li&gt;they are spread across multiple people, because this reduces the risk that one individual can or will abuse their asset privileges if all are required to be present when it is used.&lt;/li&gt;
&lt;li&gt;provided to the authentication mechanism in such a fashion as to prevent (or at least make difficult) external observation.&lt;/li&gt;
&lt;li&gt;they are not written down, a corollary of the above that helps to make observation of the password difficult.&lt;/li&gt;
&lt;li&gt;they are not logged, recorded or stored by the authentication system (not even failed attempts), another corollary to help make observing a password difficult.  Passwords are commonly stored using a &quot;one-way&quot; encryption system, this reduces the ability of an attacker to use the encrypted form for purposes of determining a password.&lt;/li&gt;
&lt;li&gt;they are changed often, this is because constantly changing passwords prevents an attacker from continuing to use a known password for an unlimited time in the future.&lt;/li&gt;
&lt;/ol&gt;To understand this last point better, consider a credit card. &amp;nbsp;A credit card contains a digital and printed password for accessing your bank account; an individual who can obtain the numbers on both front and back of your card may successfully pass themselves off as you at a wide variety of retailers. &amp;nbsp;They can draw against your account and may continue to do so over and over again until you &quot;change the password&quot; (i.e., call the card issuer and cancel the card). &amp;nbsp;If such a thief is careful in their transactions over a long period of time they can potentially go for months, or even years before the &quot;password is changed.&quot; &amp;nbsp;Banks understand this risk, they&#39;ve seen it before, and their potential liability in such cases is why they periodically &quot;change the password&quot; by reissuing a new card with new numbers front and back on a regular schedule.&lt;br /&gt;
&lt;br /&gt;
Not all of these strengths and weaknesses we just discussed are readily apparent to the normal computer user. &amp;nbsp;It says something about human nature that, on systems that allow users to select their own passwords with no guidance or restrictions on the chosen value, the most common password chosen is &quot;123456&quot; with &quot;password&quot; and &quot;stupid&quot; close runner-ups. &amp;nbsp;This inherent weakness in choosing good passwords is one reason many companies have a &quot;password policy&quot; in place for their computer users.&lt;br /&gt;
&lt;br /&gt;
If you&#39;re unfamiliar with the term &quot;password policy&quot; then you should understand that they are a set of guidelines primarily enforced at the computer itself, the use of which is intended to encourage users to create relatively secure passwords. &amp;nbsp;Most modern computer systems contain software that helps IT manage the kinds of passwords that are acceptable and how often the user must change their password. &amp;nbsp;The fact that the computer will do most of the enforcement grunt work makes corporate management of passwords a snap. &amp;nbsp;As an example, here is a password policy that your IT group may enforce:&lt;br /&gt;
&lt;br /&gt;
Password Policy for XYZ Corp:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Must be changed every 90 days.&lt;/li&gt;
&lt;li&gt;Must have between 8 and 20 characters.&lt;/li&gt;
&lt;li&gt;Must use both lower and UPPER case letters.&lt;/li&gt;
&lt;li&gt;Must use at least two digits or symbols.&lt;/li&gt;
&lt;li&gt;Cannot be a password you have used in the past.&lt;/li&gt;
&lt;/ol&gt;As you may see, these rules are to address several of the points listed in the &quot;Attributes of Effective Passwords&quot; list above.  This policy basically encourages regular password changes and fairly reasonably enforces the creation of complicated passwords.  Such a written policy statement is the digital equivalent to having OSHA safety guidelines posted on the company&#39;s legal notice board.&lt;br /&gt;
&lt;br /&gt;
If you are a corporation (especially a public corp), the officers of the company actually have a legal obligation to protect the corporate assets, failure to do so (or rather failure to make reasonable attempts at doing so) means that you, the officer, or you, the corporation, can loose all sorts of rights and/or open yourself to all sorts of trouble (often in the form of lawyers serving papers, undesirable stock action or both - multiplexed).  A public corporation who fails to reasonably protect its assets is just asking for a shareholder&#39;s lawsuit.  This protection requirement extends to and includes corporate digital assets (a phrase that really means &quot;bits stored on some hard drive somewhere (and, by the way, the latter had better be owned or controlled by the company, or a serious looking man (woman) in a pinstripe suit (dress) is going to be dispatched somewhere as soon as we know where we&#39;re going to send him (her))&quot;) and in certain situations may have even more egregious requirements than physical assets.  Just examine the actions of the RIAA &quot;on behalf of music artists&quot; for the last decade or two if you don&#39;t believe me (what a great business idea, sue your customers).&lt;br /&gt;
&lt;br /&gt;
Strangely, one of the best and easiest ways to show your shareholders (or the judge) that you are taking seriously the protection of your digital assets is to have your IT department put into place a password policy similar to the one above.  There is more than this, of course, but a question similar to, &quot;Does your company have a password policy?&quot; will invariably be one of the first questions asked; followed closely by, &quot;What actions does your company take to enforce such a policy?&quot;&lt;br /&gt;
&lt;br /&gt;
Of course, under your newly minted policy the most likely password in the above system may now be &quot;Pa$$w0rd&quot; but at least you tried (besides, the first and last policy guidelines listed above will at least ensure that the obvious alternatives to common passwords will be flushed out of the system fairly quickly).&lt;br /&gt;
&lt;br /&gt;
An IT security professional will need to be careful, however.  Aggressive policies can actually work against you.  Forcing users to frequently create new passwords increases your chance that they will act against you in other ways (i.e., writing down the password on a sticky note they then tack to the bottom of their screen).  The best password systems make as much of this automated as possible.&lt;br /&gt;
&lt;br /&gt;
To reiterate: from the user&#39;s perspective, the best system should be an easy to remember password and be trivial to use.  From the security perspective: the ideal password is a randomly generated password that may be used exactly once, a different password is required for each successive authentication for an asset.  Such a &lt;a href=&quot;http://www.rsa.com/node.aspx?id=1156&quot;&gt;system&lt;/a&gt; exists, but the cost is fairly high.  Thankfully, competitors are starting to offer lower priced alternatives.&lt;br /&gt;
&lt;br /&gt;
If you are a private citizen you don&#39;t have the same legal responsibility to protect personal assets (i.e., someone can steal from you and may be prosecuted even if you didn&#39;t lock your front door), and such assets are not normally protected by passwords anyway.  This doesn&#39;t mean that you should&#39;t pay attention to these password issues.  You still need to take reasonable action (if only for self interest) in selecting passwords for your bank accounts, utility account, mortgage accounts and any internet retailers you frequent.&lt;br /&gt;
&lt;br /&gt;
An exercise for the reader: are password policies the cause for such idiomatic trash as 1337 $934|&lt; (elite speak)?</content><link rel='replies' type='application/atom+xml' href='http://insights-into-software.blogspot.com/feeds/5049634136048254424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insights-into-software.blogspot.com/2010/03/introduction-to-security-via-password.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8111070121637504701/posts/default/5049634136048254424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8111070121637504701/posts/default/5049634136048254424'/><link rel='alternate' type='text/html' href='http://insights-into-software.blogspot.com/2010/03/introduction-to-security-via-password.html' title='Introduction to security via password policies'/><author><name>Kevin L. Sitze</name><uri>http://www.blogger.com/profile/03893988495184767671</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8111070121637504701.post-7867668630205620256</id><published>2010-03-29T19:58:00.006-05:00</published><updated>2010-04-01T21:47:18.513-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="key servers"/><category scheme="http://www.blogger.com/atom/ns#" term="ssh"/><category scheme="http://www.blogger.com/atom/ns#" term="ssh-agent"/><title type='text'>Caching ssh private keys using openssh on GNU/Linux</title><content type='html'>You probably use ssh on a daily basis, I know I do. &amp;nbsp;I find that many people I talk to don&#39;t know that typical ssh installations have the ability to cache their private keys, so they wind up having to type their private key passphrase several times a day. &amp;nbsp;Some people actually get frustrated enough with this process that they remove the passphrase from their private key file entirely. &amp;nbsp;Don&#39;t do that! &amp;nbsp;Trust me, there is a safer and better way.&lt;br /&gt;
&lt;br /&gt;
In this article I discuss how to setup GNU/Linux (using openssh) hosts to cache your private keys on startup. &amp;nbsp;I will discuss how to configure Microsoft Windows hosts using Simon Tatham&#39;s excellent &lt;a href=&quot;http://www.chiark.greenend.org.uk/~sgtatham/putty/&quot;&gt;PuTTY&lt;/a&gt; applications in another article.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
I set up my more secured environments (from which I ssh to any other machine I require) so that my passphrases are cached in memory using the ssh-agent daemon. &amp;nbsp;Here is what my .bash_profile runs every time I log into my primary GNU/Linux machine.&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;run_ssh_agent=&quot;${HOME}/.ssh/agent-for-${HOST}.pid&quot;
[ -f &quot;$run_ssh_agent&quot; ] &amp;amp;&amp;amp; . &quot;$run_ssh_agent&quot; &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
if kill -0 $SSH_AGENT_PID &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
then echo Agent pid $SSH_AGENT_PID
else
    ssh-agent -s &amp;gt; &quot;$run_ssh_agent&quot;
    . &quot;$run_ssh_agent&quot;
    ssh-add
fi
ssh-add -l
&lt;/pre&gt;&lt;br /&gt;
This bash script (backwards compatable to sh) starts up and installs your private keys into the ssh-agent daemon. &amp;nbsp;Every time you login to this machine thereafter your shell is configured to use the same agent as before, so you don&#39;t need to retype your passphrase until either the daemon is killed or the machine is restarted.&lt;br /&gt;
&lt;br /&gt;
How it works:&lt;br /&gt;
&lt;br /&gt;
Note that the &lt;tt&gt;run_ssh_agent&lt;/TT&gt; shell variable references a host specific file. &amp;nbsp;This file is used to retain shell settings required to contact the &lt;em&gt;ssh-agent&lt;/em&gt; key server so that they are accessible across multiple login sessions. &amp;nbsp;We now load these settings and check to see if the &lt;em&gt;ssh-agent&lt;/em&gt; key server daemon has already been started using the &lt;tt&gt;kill -0 $SSH_AGENT_PID&lt;/TT&gt; command.&lt;br /&gt;
&lt;br /&gt;
The special environment variables that &lt;em&gt;ssh&lt;/em&gt; applications (i.e., ssh, scp, sftp) require from your shell include &lt;tt&gt;SSH_AUTH_SOCK&lt;/TT&gt; and &lt;tt&gt;SSH_AGENT_PID&lt;/TT&gt;.  The first references a FIFO located in a secured directory (normally in /tmp) and the second indicates the process identifier of the agent. &amp;nbsp;The &lt;em&gt;ssh&lt;/em&gt; applications use the former when use of the private key is required, typically passing the actual authentication work off to the &lt;em&gt;ssh-agent&lt;/em&gt;. &amp;nbsp;This script uses the PID variable to determine whether or not the agent is running.&lt;br /&gt;
&lt;br /&gt;
The program &lt;em&gt;ssh-agent&lt;/em&gt; is a daemon that stores your private keys on behalf of other &lt;em&gt;ssh&lt;/em&gt; applications. &amp;nbsp;The -s option to &lt;em&gt;ssh-agent&lt;/em&gt; tells it to dump to STDOUT a script that sets up the above named environment variables for Bourne compatible shells (i.e., bash) and the following line then tells the running shell to evaluates the just-generated script.  This loads the &lt;tt&gt;SSH_*&lt;/TT&gt; environment variables into the running shell.&lt;br /&gt;
&lt;br /&gt;
The &lt;em&gt;ssh-add&lt;/em&gt; application is then executed.  The job of &lt;em&gt;ssh-add&lt;/em&gt; is to perform user authentication via the passphrase attached to each private key when it was generated, and then load each corresponding key into the &lt;em&gt;ssh-agent&lt;/em&gt; daemon.  Finally, after everything has been started or installed the &lt;tt&gt;ssh-add -l&lt;/TT&gt; command is executed to list each identity found in the key server.&lt;br /&gt;
&lt;br /&gt;
After installing the above code in your &lt;tt&gt;.profile&lt;/TT&gt; or &lt;tt&gt;.bash_profile&lt;/TT&gt; you should see something like this the first time you login or run &lt;tt&gt;bash -login&lt;/TT&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;Agent pid 22535
Enter passphrase for /home/kevin/.ssh/id_rsa:
Identity added: /home/kevin/.ssh/id_rsa (/home/kevin/.ssh/id_rsa)
Identity added: /home/kevin/.ssh/id_dsa (/home/kevin/.ssh/id_dsa)
Identity added: /home/kevin/.ssh/identity (kevin@linux)
3072 bb:55:6d:a0:b9:c6:c9:10:03:72:9e:e4:cf:3b:a4:44 kevin@linux (RSA1)
3072 64:42:98:8f:05:8c:a5:df:52:fa:6a:d0:fd:5a:78:bd /home/kevin/.ssh/id_rsa (RSA)
3072 cf:05:ae:d6:91:c0:9b:ce:03:81:88:35:f2:af:c6:49 /home/kevin/.ssh/id_dsa (DSA)
&lt;/pre&gt;&lt;br /&gt;
The &lt;em&gt;ssh-add&lt;/em&gt; application will prompt for a passphrase for each identity file located in your &lt;tt&gt;~/.ssh&lt;/TT&gt; directory that has a different passphrase.  As you see here, I use the same passphrase on all of my ssh private key files.&lt;br /&gt;
&lt;br /&gt;
Every time you login thereafter you will see something like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;Agent pid 22535
3072 bb:55:6d:a0:b9:c6:c9:10:03:72:9e:e4:cf:3b:a4:44 kevin@linux (RSA1)
3072 64:42:98:8f:05:8c:a5:df:52:fa:6a:d0:fd:5a:78:bd /home/kevin/.ssh/id_rsa (RSA)
3072 cf:05:ae:d6:91:c0:9b:ce:03:81:88:35:f2:af:c6:49 /home/kevin/.ssh/id_dsa (DSA)
&lt;/pre&gt;&lt;br /&gt;
You can now take advantage of these private keys by distributing an associated public key to whom you please.  Configure one in your Subversion server so you can use the svn+ssh scheme.  Add one to your normal remote machines.</content><link rel='replies' type='application/atom+xml' href='http://insights-into-software.blogspot.com/feeds/7867668630205620256/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insights-into-software.blogspot.com/2010/03/caching-ssh-private-keys-using-openssh.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8111070121637504701/posts/default/7867668630205620256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8111070121637504701/posts/default/7867668630205620256'/><link rel='alternate' type='text/html' href='http://insights-into-software.blogspot.com/2010/03/caching-ssh-private-keys-using-openssh.html' title='Caching ssh private keys using openssh on GNU/Linux'/><author><name>Kevin L. Sitze</name><uri>http://www.blogger.com/profile/03893988495184767671</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8111070121637504701.post-7798144423739806909</id><published>2010-03-28T23:22:00.009-05:00</published><updated>2010-04-01T21:48:55.665-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="bash"/><category scheme="http://www.blogger.com/atom/ns#" term="bash shell"/><category scheme="http://www.blogger.com/atom/ns#" term="parallel processing"/><category scheme="http://www.blogger.com/atom/ns#" term="process"/><category scheme="http://www.blogger.com/atom/ns#" term="process managment"/><category scheme="http://www.blogger.com/atom/ns#" term="scripts"/><category scheme="http://www.blogger.com/atom/ns#" term="shell"/><title type='text'>Elegant parallel processes in bash</title><content type='html'>Thanks in large part to a desire to facilitate better use of my multi-CPU GNU/Linux system I decided to put together a script that would allow spawning parallel tasks according to a simple template provided on the command line.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
The bash shell has been a scripting staple for decades. No other scripting system (no, not even Perl) gives the developer more control over processes, descriptors and pipes as an innate part of the language. The bash shell (its name was originally a pun: the Bourne Again Shell) inherits much of this facility from its predecessor &#39;sh&#39; (the Bourne Shell).  It seemed natural to use the process control facility of bash to build a script that dispatched processes in parallel.&lt;br /&gt;
&lt;br /&gt;
Hunting around I found that several people have done something similar, but looking closely at the scripts on the internet I realized that all were fundamentally flawed in that they all polled the dispatched subprocesses to determine whether they have completed or not. The most egregious of these systems actually used the bash &#39;wait&#39; command with no arguments, hence requiring all subprocesses to complete before the next batch were dispatched. Unix is a resource sharing system and processes ideally should avoid using any resource unnecessarily. Polling by periodically waking up and seeing if the world has changed is inelegant.&lt;br /&gt;
&lt;br /&gt;
I&#39;m a &quot;make&quot; fan, I wanted something that works just like &quot;make -j 9&quot; but was easier to use such that spawning a multiplicity of commands from a single template should be trivial. Hence I wrote parallel.sh, a short (200 lines, including 50 lines of usage) script that elegantly solves the problem of multiplexing subprocesses. The parallel.sh script blocks (it does NOT poll) waiting until one of its subprocesses completes; at which point it wakes up long enough to harvest the child&#39;s result code, read in the arguments for the next pending task, and fork. It does all the right things that a good UNiXy program should do: using only those resources (i.e., CPU, memory, disk) that it must to get the job done and then get out of the way.&lt;br /&gt;
&lt;br /&gt;
What it does:&lt;br /&gt;
&lt;br /&gt;
The parallel.sh script reads one or more lines off STDIN to compose the optional arguments for a command whose template is specified on the parallel.sh command line, and then forks as many subtasks as it can up to a user imposed limit (i.e., -j 4). As each subtask completes it reaps the child and starts a new one until EOF is reached on STDIN, at which point it waits for all child processes to complete and exits.&lt;br /&gt;
&lt;br /&gt;
How to do it wrong:&lt;br /&gt;
&lt;br /&gt;
The easiest (and worst) approach is simply to spawn each child process gunshot style using the &#39;&amp;amp;&#39; background operator:&lt;br /&gt;
&lt;pre&gt;while read line ; do eval &quot;$line&quot; &amp;amp; ; done
&lt;/pre&gt;No job control, no resource management, simply shoot the whole wad in one go. What this does is bring your system to its knees if more than 3-5 processes per CPU are spawned. Everything goes slow. The system is constantly context switching and flushing cache lines and if each process is disk intensive you&#39;ll quickly bring your entire system to a crawl. The security concerns of exec&#39;ing shell scripts should bother you too (though this article is not about security). Don&#39;t do this.&lt;br /&gt;
&lt;br /&gt;
After a child process is successfully started in the background using &#39;&amp;amp;&#39;, its identifier is accessible to the parent shell via the &#39;$!&#39; variable. What most people do is spawn the subprocess, store the PID of the spawned process and then periodically wake up and see if the PID is still running. There are several ways of checking that a child process is alive, here are two:&lt;br /&gt;
&lt;pre&gt;% [[ -d /proc/$pid ]] &amp;amp;&amp;amp; echo &quot;child $pid is alive and well&quot;
% kill -0 $pid 2&amp;gt; /dev/null &amp;amp;&amp;amp; echo &quot;child $pid is alive and well&quot;
&lt;/pre&gt;As an example of the prototypical (but inelegant) approach of running parallel processes in a shell script, I give you the naive script that reads commands off STDIN and dispatches up to a &quot;maximum&quot; number of jobs at a time. This is a more practical approach to resource usage than the first example.&lt;br /&gt;
&lt;pre&gt;maximum=4
declare -a cpids
while read line ; do
    until (( ${#cpid[*]} &amp;lt; maximum )) ; do
        for (( i = 0; i &amp;lt; maximum; ++i )); do
            if [[ ! -d /proc/${cpid[$i]} ]] ; then # or kill
                wait ${cpid[$i]} # harvest child
                unset cpid[$i]
                break 2
            fi
        done
        sleep 1
    done
    eval &quot;$line&quot; &amp;amp;
    cpid=( &quot;${cpid[@]}&quot; $! ) # cpid[${#cpid[*]}]=$! # does not work
done
wait
exit 0
&lt;/pre&gt;Phew! This probably works, but the logic is fairly complicated. There are several issues that bother me with this code. The &#39;until&#39; test is redundant after the first iteration. The polling of the subprocesses and sleep is inelegant. This code (as with the first example above) blurs the line between instruction and data. Finally, this is really quite complex code and does not really leverage the strengths of bash.&lt;br /&gt;
&lt;br /&gt;
How to do it right:&lt;br /&gt;
&lt;br /&gt;
The following code is the crux of the parallel.sh script.&lt;br /&gt;
&lt;pre&gt;# setup a named pipe (FIFO)
myfifo=$( mktemp --dry-run )
mkfifo --mode=0700 $myfifo
exec 3&amp;lt;&amp;gt;$myfifo # hook pipe up to descriptor 3 for read/write
rm -f $myfifo # pipe remains intact until closed
maximum=4 # cpus
running=0
while read line ; do
    while (( running &amp;gt;= maximum )) ; do
        if read -u 3 cpid ; then
            wait $cpid
            (( --running ))
        fi
    done
    ( # child process
        &quot;$@&quot; &quot;$line&quot;
        echo $BASHPID 1&amp;gt;&amp;amp;3
    ) &amp;amp;
    (( ++running ))
done
wait
exit 0
&lt;/pre&gt;My parallel.sh script actually does a bit more than this, but that is due to some of the other features it supports: template commands (i.e., commands that accept multiple arguments), blocking the output into a log file, option processing (i.e., -j #cpus) and several other items.&lt;br /&gt;
&lt;br /&gt;
So what did I do here? I&#39;m using a named pipe. The pipe is created in your temp directory, and then removed so only this script has access to the fifo. All pipes require a reader and a writer. In this case the reader is the parent process, which allows it to block until a writer sends something through the pipe. The writer is the child process which holds the pipe in escrow until the underlying command in the subprocess completes at which point the PID of the child is written to the fifo and the child exits. Upon EOF the script waits for all children to complete and then exits.&lt;br /&gt;
&lt;br /&gt;
Note also how the command itself is formulated. No longer is the entire command read off of each line from STDIN. Rather the command is entered on the command line itself (under direct control of the developer, rather than trusting a data feed) and each line from STDIN is appended to the end of the command (if you really want the behavior of the first two examples, simply run &quot;process.sh exec&quot;).&lt;br /&gt;
&lt;br /&gt;
Cut and paste the above code into parallel.sh, add &quot;#!/bin/bash&quot; to the top, chmod +x process.sh and you now have a basic parallel processing command for your multi-CPU system. You can now run xargs style command sequences in parallel as this version of parallel.sh has similar operating semantics to xargs.&lt;br /&gt;
&lt;br /&gt;
The only additional major feature that I have in my actual parallel.sh script is the ability to templatize specific arguments in the command line, such that each dispatched command may reference multiple lines as individual arguments. For example, I&#39;m able to process images in parallel using ImageMagick and parallel.sh thus:&lt;br /&gt;
&lt;pre&gt;% /bin/ls my_camera/*.jpg | sed -e &#39;p;s/camera/website/&#39; |
&amp;gt; parallel.sh -j 8 mogrify -resample 800x600 --write &#39;$2&#39; &#39;$1&#39;
&lt;/pre&gt;The above command processes all JPEG files in the directory &quot;my_camera&quot; and down-samples them to 800x600, writing the final image into the directory &quot;my_website&quot;. A total of 8 processes will be allowed to run simultaneously.&lt;br /&gt;
&lt;br /&gt;
UPDATE: I&#39;ve uploaded the complete source code of parallel.sh to &lt;a href=&quot;http://code.activestate.com/recipes/577173-parallelize-your-shell-commands/&quot;&gt;ActiveState Code&lt;/a&gt;.</content><link rel='replies' type='application/atom+xml' href='http://insights-into-software.blogspot.com/feeds/7798144423739806909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insights-into-software.blogspot.com/2010/03/elegant-parallel-processes-in-bash.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8111070121637504701/posts/default/7798144423739806909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8111070121637504701/posts/default/7798144423739806909'/><link rel='alternate' type='text/html' href='http://insights-into-software.blogspot.com/2010/03/elegant-parallel-processes-in-bash.html' title='Elegant parallel processes in bash'/><author><name>Kevin L. Sitze</name><uri>http://www.blogger.com/profile/03893988495184767671</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8111070121637504701.post-877748688070543762</id><published>2010-03-28T19:40:00.001-05:00</published><updated>2010-04-01T21:49:13.702-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="intro"/><category scheme="http://www.blogger.com/atom/ns#" term="summary"/><title type='text'>Welcome to Insights into Software</title><content type='html'>Here I will post my observations on software.  My primary focus is on GNU/Linux software.  This blog is going to be on technical issues of particular interest to software developers.</content><link rel='replies' type='application/atom+xml' href='http://insights-into-software.blogspot.com/feeds/877748688070543762/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insights-into-software.blogspot.com/2010/03/welcome-to-insights-into-software.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8111070121637504701/posts/default/877748688070543762'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8111070121637504701/posts/default/877748688070543762'/><link rel='alternate' type='text/html' href='http://insights-into-software.blogspot.com/2010/03/welcome-to-insights-into-software.html' title='Welcome to Insights into Software'/><author><name>Kevin L. Sitze</name><uri>http://www.blogger.com/profile/03893988495184767671</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>