<?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>#!0 &#187; Bash/Shell</title>
	<atom:link href="http://blog.hashbang0.com/category/computing/programming/bashshell/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.hashbang0.com</link>
	<description>A blog of life and geekery</description>
	<lastBuildDate>Sun, 25 Jul 2010 02:09:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Dissertation is over&#8230;</title>
		<link>http://blog.hashbang0.com/2010/05/31/dissertation-is-over/</link>
		<comments>http://blog.hashbang0.com/2010/05/31/dissertation-is-over/#comments</comments>
		<pubDate>Mon, 31 May 2010 22:26:37 +0000</pubDate>
		<dc:creator>Ben Lavery</dc:creator>
				<category><![CDATA[Bash/Shell]]></category>
		<category><![CDATA[OpenSolaris]]></category>
		<category><![CDATA[Uni]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[CS394]]></category>
		<category><![CDATA[Diss]]></category>
		<category><![CDATA[Dissertation]]></category>
		<category><![CDATA[LaTeX]]></category>
		<category><![CDATA[VAES]]></category>
		<category><![CDATA[zones]]></category>

		<guid isPermaLink="false">http://www.blog.hashbang0.com/?p=982</guid>
		<description><![CDATA[I meant to blog about this ages ago!  Better late than never I suppose&#8230; Back in April (April 22nd to be precise) I handed in two copies of my 72 page document which outlines everything about my project.  I wanted to blog about my dissertation while I was doing it, but the thought was always [...]]]></description>
			<content:encoded><![CDATA[<p>I meant to blog about this ages ago!  Better late than never I suppose&#8230;</p>
<p>Back in April (April 22nd to be precise) I handed in two copies of my 72 page document which outlines everything about my project.  I wanted to blog about my dissertation while I was doing it, but the thought was always pushed back by other thoughts of actually doing the project.<span id="more-982"></span></p>
<p>The project investigated how one could use virtualisation techniques of today and use them to virtualise every application on a machine.  Here&#8217;s a copy of my abstract:</p>
<blockquote><p>In computing, occasionally an application can cause a whole system to be brought down. This wastes valuable time for users and has the potential to lose unsaved data. This project sets out to create a concept whereby applications are virtualised for overall system stability and which appears completely transparent to the<br />
end user. The project attempts to create a system based on this concept using OpenSolaris 2009.06 and a number of its technologies, most notably: Zones.</p>
<p>The project discovers that the choice of technologies used are not yet mature enough to implement the concept, though they are very close to maturing.</p></blockquote>
<p>As the abstract says, I used OpenSolaris Zones to implement the concept.  I created a script which wraps around the OpenSolaris `pkg` command which is used to install applications.  My script creates a new Zone and installs the new application into that Zone.  The application is now basically in it&#8217;s own operating system, to better describe it, it&#8217;s as if the application has been installed onto a whole new machine.  The application is accessed using SSH and tunneling X11 over it, this worked quite well after I had set up the infrastructure, but the user had to input their password when they wanted to launch an application.</p>
<p>The project was really fun, I really enjoyed it and learnt so much.  Now it&#8217;s finished I&#8217;m rather lost as to what to do with myself&#8230;</p>
<p>If anyone would like to read my Dissertation or try implementing my project (with is licensed under the BSD licence), please don&#8217;t hesitate to <a href="mailto:ben.lavery@gmail.com">contact me</a>.  At the end of it all, the documentation consisted of 72 pages in PDF form (that was 1086 lines of LaTeX, excluding comments and blank lines), and the project consisted of 1494 lines of Bash script and 1393 comments!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hashbang0.com/2010/05/31/dissertation-is-over/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Robust Bash Scripts &#8211; Part Four</title>
		<link>http://blog.hashbang0.com/2010/05/19/robust-bash-scripts-part-four/</link>
		<comments>http://blog.hashbang0.com/2010/05/19/robust-bash-scripts-part-four/#comments</comments>
		<pubDate>Wed, 19 May 2010 10:37:55 +0000</pubDate>
		<dc:creator>Ben Lavery</dc:creator>
				<category><![CDATA[Bash/Shell]]></category>
		<category><![CDATA[bash script]]></category>
		<category><![CDATA[traps]]></category>

		<guid isPermaLink="false">http://www.blog.hashbang0.com/?p=966</guid>
		<description><![CDATA[This is part of a series of posts which should aid anyone writing Bash scripts to make them more robust. This post describes how you can use traps to help your code fail more gracefully. Sometimes you write a script, it fails, and leaves a shed load of temporary files over your file system.  Or [...]]]></description>
			<content:encoded><![CDATA[<p>This is part of a series of posts which should aid anyone writing Bash scripts to make them more robust.</p>
<p>This post describes how you can use traps to help your code fail more gracefully.<span id="more-966"></span></p>
<p>Sometimes you write a script, it fails, and leaves a shed load of temporary files over your file system.  Or perhaps (like in part two) some stuff gets set up, your script fails and leaves a network half set up or a naming service half completed.  Whatever the problem, we can trap them (well, almost all of them…).</p>
<p>For my example, I&#8217;m going to use a section of my dissertation.  I have a script which is called &#8220;INSTALL.sh&#8221;, this sets some stuff up itself, and also delegates some tasks to other scripts.  Here is the general gist:</p>
<p>Check for root permissions &#8211; If no permissions, exit with status 1<br />
Move some files about<br />
Create some directories and move files to those directories<br />
Call a script to set up the network<br />
Install NIS (A.K.A. YP)<br />
Set up NIS<br />
Set up ability to share home directories<br />
Call a script to set up a Solaris Zone (virtual machine)<br />
Move a customised file over a system file<br />
Call a cleanup function</p>
<p>Now, if any part of that script goes wrong, the script will fail (it will because I&#8217;ve used the &#8220;set -e&#8221; option).  If the script exists half of the configuration is done, and if you try to run the script again, it will fail because some of the setup is already complete.</p>
<p>To get out of this horrible situation, I have used a trap.  If the script exists with an exit status of 1 or greater, or if it is interrupted by a HUP, INT, QUIT or TERM signal, it will be trapped and run a function called &#8220;abort&#8221;.  Here is my trap statement:</p>
<p>trap &#8216;abort&#8217; 1 2 3 15</p>
<p>My &#8220;about&#8221; method looks something like this:</p>
<p><code>abort(){<br />
echo "ABORTING!  Please take note of any warnings!"<br />
</code><code>#If pkg-manage exists, rename it to pkg<br />
if [[ -a /usr/bin/pkg-manage ]]; then<br />
rm /usr/bin/pkg<br />
mv /usr/bin/pkg-manage /usr/bin/pkg<br />
fi<br />
#Call cleanup to clear away temp files<br />
cleanup<br />
#Remove contents of /var/vaes<br />
rm -rf /var/vaes<br />
#Remove config file<br />
rm $CONFIG_FILE<br />
#Uninstall NIS &amp; related things<br />
pkg uninstall SUNWyp<br />
domainname ""<br />
rm /etc/defaultdomain<br />
cp /etc/nsswitch.files /etc/nsswitch.conf<br />
zfs set sharenfs=off rpool/export/home<br />
cat /etc/auto_home | grep -v "`hostname`:/export/home" &gt; /tmp/auto_home<br />
mv /tmp/auto_home /etc/auto_home<br />
#Delete zones dir<br />
POOL=`zfs list | awk '{ print $1 }' | \<br />
grep "export" | sed 's/\([a-zA-Z]*\)\/.*/\1/g' | head -1`<br />
zfs destroy -Rf $POOL/export/vaes-zones<br />
#Undo zones<br />
bash /tmp/zone_setup.sh abort<br />
#Undo networking<br />
bash /tmp/network_setup.sh abort<br />
}</code></p>
<p>By using the trap statement, you can clean up after your failed script in the majority of cases.  A word of warning though: You cannot trap the KILL (or 9) signal, if your script fails because it has received a KILL signal, it will just exit.</p>
<p>This concludes the series on robust Bash scripting.  I hope it has been of some help to someone.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hashbang0.com/2010/05/19/robust-bash-scripts-part-four/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Robust Bash Scripts &#8211; Part Three</title>
		<link>http://blog.hashbang0.com/2010/05/19/robust-bash-scripts-part-three/</link>
		<comments>http://blog.hashbang0.com/2010/05/19/robust-bash-scripts-part-three/#comments</comments>
		<pubDate>Wed, 19 May 2010 10:28:00 +0000</pubDate>
		<dc:creator>Ben Lavery</dc:creator>
				<category><![CDATA[Bash/Shell]]></category>
		<category><![CDATA[bash script]]></category>
		<category><![CDATA[defensive scripting]]></category>
		<category><![CDATA[making directories]]></category>
		<category><![CDATA[spaces in input]]></category>

		<guid isPermaLink="false">http://www.blog.hashbang0.com/?p=962</guid>
		<description><![CDATA[This is part of a series of posts which should aid anyone writing Bash scripts to make them more robust. This post offers some advice on how to Bash script defensively. Be Prepared is the old Scout motto, and never is it more relevant then when scripting in Bash (or any language come to think [...]]]></description>
			<content:encoded><![CDATA[<p>This is part of a series of posts which should aid anyone writing Bash scripts to make them more robust.</p>
<p>This post offers some advice on how to Bash script defensively.<span id="more-962"></span></p>
<p>Be Prepared is the old Scout motto, and never is it more relevant then when scripting in Bash (or any language come to think of it).</p>
<p><span style="text-decoration: underline;"><strong>Missing files and directories</strong></span></p>
<p>If you are going to be working with files and directories in Bash (and you probably will be 99.9% of the time) you should test to see if they exist.</p>
<p>You can do a very generic test like this:</p>
<p><code>MYFILE=/tmp/test<br />
if [[ -e $MYFILE ]]; then<br />
#Do something<br />
else<br />
#Do something else<br />
#Perhaps create file/directory<br />
fi</code></p>
<p>The &#8220;-e&#8221; will test for the existence of ANY file, including directories.  You will probably be better off using &#8220;-d&#8221; for directories though, and &#8220;-f&#8221; for regular files, see the man page for more information about test (use the command &#8220;man test&#8221; or &#8220;help test&#8221;).</p>
<p>If you are creating a directory somewhere like &#8220;/opt/local/share/lib/foo/bar&#8221;, you should either test for the existence of each folder, or you can simple used the &#8220;-p&#8221; flag on the &#8220;mkdir&#8221; command, this will create any folders that aren&#8217;t created.</p>
<p><span style="text-decoration: underline;"><strong>Spaces</strong></span></p>
<p>Sometimes your script will deal with text that has spaces in it, and you need to be prepared for that, even if you are sure it will never need to handle spaces, there will always be one occasion somewhere down the line.</p>
<p>If we take this example:</p>
<p><code>for EACH in $@;<br />
do<br />
echo $EACH<br />
done</code></p>
<p>Say the input to the script reads something like this:<br />
bash myscript.sh hashbang0 &#8220;Ben Lavery&#8221; Aberystwyth<br />
The for loop shown previously would print out the output like this:<br />
hashbang0<br />
Ben<br />
Lavery<br />
Aberystwyth</p>
<p>If we quote the $@ like this:</p>
<p><code>for EACH in "$@";<br />
do<br />
echo $EACH<br />
done</code></p>
<p>Thou output now becomes:</p>
<p>hashbang0<br />
Ben Lavery<br />
Aberystwyth</p>
<p><span style="text-decoration: underline;"><strong>Failing Gracefully</strong></span></p>
<p>If you are updating a lot of files in a directory, what happens if your script fails halfway through?  Half of your files are unmodified, and the other half are modified.  This could be disastrous, especially in something like a directory full of web documents.</p>
<p>One solution is to copy the contents of the folder before you start working on them, do the work, move the copied files over the old files.  Something a bit like this:</p>
<p><code>cp -a /tmp/mydir /tmp/mydir-temp<br />
#modify files in /tmp/mydir-temp<br />
mv /tmp/mydir /tmp/mydir-BAK #backup<br />
mv /tmp/mydir-temp /tmp/mydir</code></p>
<p>As long as you do the relevant testing and exit the script if anything goes wrong, the script will never overwrite /tmp/mydir, and if it does, you have a backup!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hashbang0.com/2010/05/19/robust-bash-scripts-part-three/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Robust Bash Scripts &#8211; Part Two</title>
		<link>http://blog.hashbang0.com/2010/05/18/robust-bash-scripts-part-two/</link>
		<comments>http://blog.hashbang0.com/2010/05/18/robust-bash-scripts-part-two/#comments</comments>
		<pubDate>Tue, 18 May 2010 15:22:26 +0000</pubDate>
		<dc:creator>Ben Lavery</dc:creator>
				<category><![CDATA[Bash/Shell]]></category>
		<category><![CDATA[bash script]]></category>
		<category><![CDATA[errexit]]></category>
		<category><![CDATA[set -e]]></category>

		<guid isPermaLink="false">http://www.blog.hashbang0.com/?p=957</guid>
		<description><![CDATA[This is part of a series of posts which should aid anyone writing Bash scripts to make them more robust. This post shows you how to use Bash&#8217;s built-in error checking. Sometimes you might write a script where one line of the script may fail, this failure could cause the rest of your script to [...]]]></description>
			<content:encoded><![CDATA[<p>This is part of a series of posts which should aid anyone writing Bash scripts to make them more robust.</p>
<p>This post shows you how to use Bash&#8217;s built-in error checking.<span id="more-957"></span></p>
<p>Sometimes you might write a script where one line of the script may fail, this failure could cause the rest of your script to fail horribly!</p>
<p>For example, you have two scripts: One which sets up the network on a machine, and another which sets up a naming service based on details given in the network script.  The second script calls the network setup script before it sets up the naming service.</p>
<p>If the network setup fails for some reason, the script shouldn&#8217;t attempt to set up the naming service as something has gone wrong.</p>
<p>You might try something like this:</p>
<p><code>bash setup_network.sh<br />
if [ "$?"-ne 0]; then<br />
echo "command failed"<br />
exit 1<br />
fi<br />
#start setting up naming service</code></p>
<p>Although this is fine, what happends if you forget to add it?  Or assume that the network will always be set up so decide not to add it?  If the network doesn&#8217;t get setup, you&#8217;ll be in a bit of a pickle!</p>
<p>Bash provides its own, built-in, error checking for you in the form of the &#8220;<tt>errexit" option, or "set -e".  If a command fails in a script with this option enabled, the script will automatically stop with an error code 1.</tt></p>
<p>If you need to turn off error checking (and you may need to if you are using something like grep which may fail, but you know youve handled it), then you could do this:</p>
<p><code>command1<br />
command2<br />
set +e<br />
command_that-may-fail<br />
set -e<br />
command4</code></p>
<p>&#8220;set +e&#8221; will turn off error checking.</p>
<p>In a later post I will look at the `trap` statement to catch the error this option throws.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hashbang0.com/2010/05/18/robust-bash-scripts-part-two/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Robust Bash Scripts &#8211; Part One</title>
		<link>http://blog.hashbang0.com/2010/05/18/robust-bash-scripts-part-one/</link>
		<comments>http://blog.hashbang0.com/2010/05/18/robust-bash-scripts-part-one/#comments</comments>
		<pubDate>Tue, 18 May 2010 15:10:19 +0000</pubDate>
		<dc:creator>Ben Lavery</dc:creator>
				<category><![CDATA[Bash/Shell]]></category>
		<category><![CDATA[bash script]]></category>
		<category><![CDATA[nounset]]></category>
		<category><![CDATA[set -u]]></category>

		<guid isPermaLink="false">http://www.blog.hashbang0.com/?p=953</guid>
		<description><![CDATA[This is part of a series of posts which should aid anyone writing Bash scripts to make them more robust. This post shows you how you can guard against unset variables. Bash doesn&#8217;t provide any sort of checking for unset variables by default.  You may have something similar to the following piece of code: #!/bin/bash [...]]]></description>
			<content:encoded><![CDATA[<p>This is part of a series of posts which should aid anyone writing Bash scripts to make them more robust.</p>
<p>This post shows you how you can guard against unset variables.<span id="more-953"></span></p>
<p>Bash doesn&#8217;t provide any sort of checking for unset variables by default.  You may have something similar to the following piece of code:</p>
<p><code>#!/bin/bash<br />
#Script is called delete.sh<br />
DEL=$1<br />
rm -rf ~/$DEL</code></p>
<p>You would use it similar to this: `bash delete.sh tmp`, which would delete ~/tmp.  Imagine if you forgot to add the &#8220;tmp&#8221; on the end&#8230;POOF!  That&#8217;s your home directory gone!</p>
<p>You should get into the habit of using the Bash option &#8220;nounset&#8221;, otherwise known as &#8220;set -u&#8221;.  If you put that at the top of your script and run the command without any arguments, you&#8217;ll get something like this:</p>
<p><code>$ bash delete.sh<br />
delete.sh: line 3: $1: unbound variable</code></p>
<p>This is somewhat similar to a runtime error in Python or Perl and could be very annoying, but at least you&#8217;ve saved your home directory, or another critical location on your computer!</p>
<p>As a side note, if &#8220;set -u&#8221; or &#8220;set -o nounset&#8221; is specified at the top of the script and the script exists because of an error, it will exit with an exit status of 1.  In a later post I will explain how to use the `trap` statement to catch this error.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hashbang0.com/2010/05/18/robust-bash-scripts-part-one/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Whence and Whenceman</title>
		<link>http://blog.hashbang0.com/2010/03/31/whence-and-whenceman/</link>
		<comments>http://blog.hashbang0.com/2010/03/31/whence-and-whenceman/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 11:17:52 +0000</pubDate>
		<dc:creator>Ben Lavery</dc:creator>
				<category><![CDATA[Bash/Shell]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac OS]]></category>
		<category><![CDATA[OpenSolaris]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[unix]]></category>
		<category><![CDATA[whence]]></category>
		<category><![CDATA[whenceman]]></category>
		<category><![CDATA[which]]></category>

		<guid isPermaLink="false">http://www.blog.hashbang0.com/?p=912</guid>
		<description><![CDATA[On the UNIX command line, the `which` command is great, it tells you where a command is in the system.  However, if your system has two versions of the `ls` command, it will only tell you which `ls` command you are going to use when tap it in and press enter.  To find all copies [...]]]></description>
			<content:encoded><![CDATA[<p>On the UNIX command line, the `which` command is great, it tells you where a command is in the system.  However, if your system has two versions of the `ls` command, it will only tell you which `ls` command you are going to use when tap it in and press enter.  To find all copies of any command, we need something <a href="http://lamsey.co.uk/journal.htm">Liam</a> called `whence` (I inherited Liam&#8217;s bashrc file when working at Sun, and this little gem was right inside it).  The .bashrc function for `whence` looks something like this:<span id="more-912"></span></p>
<p><code># search for all instances of an executable in $PATH<br />
function whence {<br />
for i in `echo $PATH | sed "s/:/ /g"`<br />
do<br />
/usr/bin/ls $i/$@ 2&gt;/dev/null<br />
done<br />
}</code></p>
<p>It&#8217;s nice and straighforward, nothing complicated about it at all.  In fact, to let everyone on your system use it, you could just stick &#8220;#!/bin/sh&#8221; at the top and stick in a file in /usr/bin !</p>
<p>Today, I wanted to find a man page, the sysidcfg man page to be precise.  Instead of doing the usual trick (`find / | grep sysidcfg&#8221;), I thought I&#8217;d modify `whence` to look for it for me, and seeing as it&#8217;s no longer `whence`, I called it `whenceman`:</p>
<p><code># search for all instances of a man page in $MANPATH<br />
function whenceman {<br />
for i in `echo $MANPATH | sed "s/:/ /g"`<br />
do<br />
/usr/bin/find $i/ 2&gt;/dev/null | grep -i $@<br />
done<br />
}</code></p>
<p>As you can see, it&#8217;s very similar, and you could do the same thing by putting it in /usr/bin so everyone could use it.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hashbang0.com/2010/03/31/whence-and-whenceman/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bash and SED script to play&#8230;Tetris&#8230;?</title>
		<link>http://blog.hashbang0.com/2010/03/30/bash-and-sed-script-to-play-tetris/</link>
		<comments>http://blog.hashbang0.com/2010/03/30/bash-and-sed-script-to-play-tetris/#comments</comments>
		<pubDate>Tue, 30 Mar 2010 09:37:13 +0000</pubDate>
		<dc:creator>Ben Lavery</dc:creator>
				<category><![CDATA[Bash/Shell]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[command line]]></category>
		<category><![CDATA[sed]]></category>
		<category><![CDATA[tetris]]></category>

		<guid isPermaLink="false">http://www.blog.hashbang0.com/?p=903</guid>
		<description><![CDATA[If you navigate your browser to here, you will find a most amazing thing: Tetris crafted out of a SED script with a bash wrapper.  The page is in Russian, but Google or another translation site will tell you that the first few words read: Wrote a small Tetris on sed&#8217;e: sedtris.sed and wrapper on [...]]]></description>
			<content:encoded><![CDATA[<p>If you navigate your browser to <a href="http://uuner.livejournal.com/55238.html">here</a>, you will find a most amazing thing: Tetris crafted out of a SED script with a bash wrapper.  The page is in Russian, but Google or another translation site will tell you that the first few words read:</p>
<blockquote><p>Wrote a small Tetris on sed&#8217;e: sedtris.sed and wrapper on Bashe sedtris.sh</p></blockquote>
<p>Download both scripts to the same directory, on the command line do:</p>
<p><code>bash sedtris.sh</code></p>
<p>It&#8217;s actually very good!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hashbang0.com/2010/03/30/bash-and-sed-script-to-play-tetris/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->