<?xml version="1.0" encoding="iso-8859-1"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:admin="http://webns.net/mvcb/"
xmlns="http://purl.org/rss/1.0/">
<channel rdf:about="http://aplawrence.com/fullrss.rdf">
<title>Main Site News at A.P.Lawrence.com</title>
<link>http://aplawrence.com/</link>
<description>
Main feed at aplawrence.com: Thousands of articles, reviews, consultants listings, skills tests, opinion, how-to's for Unix, Linux and Mac OS X, networking, web site maintenance and more.. 
</description>
<sy:updatePeriod>hourly</sy:updatePeriod>
<sy:updateFrequency>6</sy:updateFrequency>
<sy:updateBase>2008-01-01T00:00+00:00</sy:updateBase>
<dc:language>en</dc:language>
<dc:publisher>A.P. Lawrence</dc:publisher>
<dc:rights>Copyright  A.P. Lawrence</dc:rights>
<dc:creator>A.P. Lawrence (mailto:rssfeeds@aplawrence.com)</dc:creator>
<dc:date>2009-11-21T16:42:08+00:00</dc:date>
<image rdf:resource="http://aplawrence.com/image21.gif">
</image>
<items>
<rdf:Seq>
<rdf:li rdf:resource="http://aplawrence.com/Kerio/connect-beta.html" />
<rdf:li rdf:resource="http://aplawrence.com/Unixart/freeing-disk-space.html" />
<rdf:li rdf:resource="http://aplawrence.com/Books/art-of-seo.html" />
<rdf:li rdf:resource="http://aplawrence.com/Unixart/sort-vs-uniq.html" />
<rdf:li rdf:resource="http://aplawrence.com/Girish/LiveUSB.html" />
<rdf:li rdf:resource="http://aplawrence.com/Unixart/google-go.html" />
<rdf:li rdf:resource="http://aplawrence.com/Unixart/network-fishing.html" />
<rdf:li rdf:resource="http://aplawrence.com/Unixart/awk-vs.perl.html" />
</rdf:Seq>
</items>
</channel>
<image rdf:about="http://aplawrence.com/image21.gif">
<title>A.P.Lawrence Logo</title>
<url>http://aplawrence.com/image21.gif</url>
<link>http://aplawrence.com</link>
</image>


<item rdf:about="http://aplawrence.com/Kerio/connect-beta.html">
<title>Kerio Connect 7 Beta  </title>
<description>
<![CDATA[
Kerio 

2009/11/19<br />
<!-- LEFTADOK -->
<!-- PCOUNT -->
<!-- PCOUNT -->

<p>Kerio is renaming its mailserver to "Kerio Connect".  My initial reaction is that changing "Mailserver" to "Connect" is a bad idea.  They feel that because the product is so much more than a mailserver, changing the name is appropriate.</p>
<p>I do partly agree.  Many of my customers only use the email features and ignore all of the collaboration aspects.   Sometimes that's because they see no need for scheduling, etc. and sometimes it's because they just never noticed those capabilities (someone only using POP or IMAP, for example).</p>
<p>Well, regardless of how I feel about it, the next release will be Kerio Connect.  It's in beta now and looks solid enough that its release is likely not very far way, so let's take a look at what it offers.</p>
<h2>Message Retention</h2>
<p>A few releases back Kerio introduced scheduled administrative deletion of Junk and Deleted Items messages.  With Kerio Connect 7, this has been extended to include all folders (except Contacts, for obvious reasons).  You can set a policy that automatically deletes all messages domain-wide after so many years.</p>
<p>I don't see this as particularly useful for most companies.  First, it's only domain-wide -  at least right now, this hasn't been brought to individual users as the control of Junk and Deleted is now. Some users may need to keep some email (or particularly specific email folders) forever.  I think this needs more fine-grained control to be useful.</p>
<h2>Distributed Domains</h2>
<p>One of the first features I noticed is distributed domains.  From the manual:</p>

<blockquote>If your company uses more Kerio Connect servers physically scattered (located in different cities, countries, continents), you can now add them to a cluster and move all users across all servers involved into a single email domain (distributed domain).</blockquote>

<p>Note that this isn't load balancing.  One server is the master point where all incoming email arrives; it is responsible for relaying any that belong at a satellite server.   The "slave" servers should have the master set as their relay also if you want single-point archiving and backup.</p>
<p>The "Master /Slave" designation is arbitrary.  All servers are really peer to peer and use the same directory service.  You determine which servers mailboxes belong on which server and which is the master. Obviously that would need to be the server that is set as the MX for the domain also.</p>
<h2>Message Submission service </h2>
<p>You'll find this in Services, set to run on port 587.
Kerio suggests using this to get around the problem of outgoing port 25 being blocked at hotels and public access points.  The user sets his outgoing SMTP port to 587 and the Kerio server listens on that.  As this service requires authentication, it can't be used by spammers - unless they've hacked the user's account, of course, but at least we do then absolutely know the source of the spam!</p>
<p>The Message Submission service  is  defined in <a href="http://www.faqs.org/rfcs/rfc2476.html">RFC 2476</a> and has much more to do with mail architecture than just bypassing blocked ports.   This <a href="http://www.imc.org/ietf-submit/mail-archive/msg00299.html">FAQ: SMTP Message Submission to Proposed Standard</a> describes the reasoning behind the RFC.</p>
<h2>Performance improvements</h2>
<p>The release notes say:</p>
<blockquote>
Kerio Connect uses a more efficient file access method to the message store data. This includes the properties.fld database access and listing mailbox folders.
</blockquote>
<p>That doesn't tell us much, does it?</p>
<p>The "properties.fld" file is apparently IMAP annotation data.  It's interesting to look at what these metadata files are:</p>
<pre>
index.fld:      ASCII text, with CRLF line terminators
properties.fld: Berkeley DB 1.85/1.86 (Btree, version 3, little-endian)
search.fld:     SQLite 2.x database
status.fld:     ASCII text, with CRLF line terminators
</pre>
<p>But that still doesn't tell us how any of this helps speed up file access.</p>
<p>Kerio has a problem with <a href="http://aplawrence.com/Kerio/fixing-large-mailboxes.html">very large mailbox folders</a>.  They store individual mail messages rather than packing them all into one database as Exchange does.  I think that's the right approach, but it can cause performance issues.  These files are designed to help that by providing a mix: database files pointing to individual messages.  Apparently this release has made some changes in this area; we'll see if it helps very large folders.</p>
<p>I'd much prefer to see domain or user controlled folder archiving.  I'm not referring to the archiving found in Archiving and Backup but rather moving older messages into another folder at regular intervals.  For example, if this were set for monthly archiving, everything in your Inbox from last month would be moved to Inbox-2009-09.  But that's not a feature of this release and may never be.</p>
<h2>Web Administration</h2>
<p>With Kerio Connect 7, you can now do all administrative functions through your web browser.  For example, on the server itself, I can 
connect to http://localhost/admin.</p>
<p>This actually runs on port 4040 and there's no control over that in Administration.  However, it is listed in mailserver.cfg, so you could adjust this as necessary.</p>
<p><i>Speaking of config files, there's a new cluster.cfg file.  I assume that is for the distributed domains mentioned earlier, but there is also an undocumented Cluster section in the mailserver.cfg, so bigger plans may be afoot.  That's pure speculation, of course.</i></p>
<p>The web administration is  very useful - it's not that it's at all 
difficult to download the free administrative console, but having this available from any web browser is handy, </p>
<h2>Additional changes</h2>
<p>The release notes mention  over-the-air synchronization of HTC Hero mobile devices and that the IMAP server  has been improved for better support of multi-session IMAP connections.  You'll be able to rename a domain also.  That seems to be about it.</p>


<p>Comments: <a href="http://aplawrence.com/cgi-bin/newcomm.pl?commenting=/Kerio/connect-beta.html">Click Here.</a></p>

<p><br /><br /><i><b>Many of the products and books I review are things I purchased for my own use.  Some were given to me specifically for the purpose of   reviewing them.</b></i></p>
<p><i><b>I resell or can earn commissions from the sale of some of these items.  Links within these pages may be affiliate links that pay me for referring you 
to them. That's mostly insignificant amounts of money; whenever it is not I have made my relationship plain.  If you have any question, please do feel free to contact me.</b></i></p>
<div style="font-size:80%">
<table>
<tr>
<td> - </td>
<td><a href="http://aplawrence.com/Tests">Skills Tests</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/psst.html">Psst - wanna work for yourself?</a></td>
<td> - </td><td><a href="http://aplawrence.com/troubleshootingbook.html">Unix/Linux Troubleshooting e-book</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/Kerio">Kerio Mail Server</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/rates.html">Consulting</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/advert.html">Advertise Here</a></td>
</tr>
</table>
</div>
]]>
</description>
<link>http://aplawrence.com/Kerio/connect-beta.html</link>
</item>
<item rdf:about="http://aplawrence.com/Unixart/freeing-disk-space.html">
<title>Freeing disk space with ">"  </title>
<description>
<![CDATA[
Linux,MacOSX,Basics,Shell,Disks-Filesystems 

2009/11/18<br />
<!-- LEFTADOK -->
<!-- PCOUNT -->
<!-- PCOUNT -->


<p>I wrote this up after a forum discussion in which several posters didn't really understand why ">" can free disk space when "rm" cannot.  The basic problem is that if another process has a file open (for reading or writing, it doesn't matter), 
the disk blocks are not freed by an "rm" until the process or process using the file quits (or stops using the file, at least).   That part seems to be well understood.</p>
<p>What is perhaps more difficult to understand is why a simple ">" CAN free up the bytes that "rm' cannot.</p>
<div style="margin-left:10px;margin-right:10px">
<p><i>For those very new to Unix/Linux:  if you are using almost any 
shell but "csh", a ">" followed by a file name will empty that file.  That is, 
it will be truncated to zero bytes without changing the ownership or permissions.  On more recent Linux machines, you may have a "truncate" command that will do the same thing.</i></p>
<p><i>For those NOT new to Unix or Linux, this article isn't meant for you.  Unfortunately, it was linked to from some places frequented by more advanced users.  Feel free to read it, of course, but it's not going to tell you anything you do not already know.</i></p>
</div>
<p>To show that, we need to write a little code.  I'll use Perl for that, but if you don't grok Perl, don't worry -I'll explain it as we go along.   I did this on a Mac, but you'd see the same thing on Linux or BSD.</p>
<p>Let's start with the "rm" issue.   Our Perl code will just open a file and loop.  We'll run that in one Terminal window and do everything else in another.</p>
<pre>
#!/usr/bin/perl
open(I,"./t");
while (1) {
 sleep 10;
 print "I'm still here";
}
</pre>
<p>The script just opens "t" and then loops.  It never reads or writes anything, but it does  have "t" open while running.</p>
<p>The file "t" already exists before running this and is large enough to notice its absence in "df".  Here it is before the script runs and while it runs:.</p>
<pre>
$ ls -l  t;df | head -2
-rw-r--r--  1 apl  apl  20480 Nov 18 08:50 t
Filesystem    512-blocks     Used Available Capacity  Mounted on
/dev/disk0s2   155629664 99862360  55255304    65%    /

# start the script in another window
$ ls -l t; df | head -2
-rw-r--r--  1 apl  apl  20480 Nov 18 10:11 t
Filesystem    512-blocks     Used Available Capacity  Mounted on
/dev/disk0s2   155629664 99862360  55255304    65%    /

</pre>
<p>If we now remove "t", nothing will change:</p>
<pre>
$ rm t   
$ ls -l t; df | head -2
ls: t: No such file or directory
Filesystem    512-blocks     Used Available Capacity  Mounted 
/dev/disk0s2   155629664 99862360  55255304    65%    /
</pre>
<p>When we interrupt the script, disk space is reclaimed:</p>
<pre>
$ ls -l t; df | head -2
ls: t: No such file or directory
Filesystem    512-blocks     Used Available Capacity  Mounted on
/dev/disk0s2   155629664 99862320  55255344    65%    /
</pre>
<p>However, if we do the same thing with ">", diskspace will be reclaimed 
instantly:</p>

<pre>
$ ls -l t;df | head -2
-rw-r--r--  1 apl  apl  20480 Nov 18 09:20 t
Filesystem    512-blocks      Used  Available Capacity  Mounted on
/dev/disk0s2   155629664 100006784  55110880    65%    /
$> t
$ ls -l t;df | head -2
-rw-r--r--  1 apl  apl  0 Nov 18 09:21 t
Filesystem    512-blocks      Used  Available Capacity  Mounted on
/dev/disk0s2   155629664 100006744  55110920    65%    /
</pre>
<p>I demonstrated similar code at the forum and quickly got back this comment:</p>
<blockquote>
The > trick will simply remove the data in the file and have no need for the os to clear up unused data so this might work unless the process remembers where in the file it is appending too and always does a seek.
</blockquote>
<p>Let's see if that's true.   We'll need a different script:</p>
<pre>
#!/usr/bin/perl
open(I,">./t");

while (1) {
 print I "x" x 4096;
 print "Block written\n";
 sleep 10;
}
</pre>
<p>This time, the script writes 4096 bytes (4096 "x"'s) on every loop.     I'm not going to bother to show the listings and df's; the behavior is exactly the same: the bytes are freed as soon as you do "> t".</p>
<p>But our doubting poster mentioned "seek".   For those who do not know, 
a seek moves the writing or reading position of the file to a specific place.    We can do that with Perl:</p>
<pre>
#!/usr/bin/perl
open(I,">./t");
$x=0;

while (1) {
 $mypos=$x * 4096;
 seek I, 0, $mypos;
 print I "x" x 4096;
 print "Block $x written\n";
 $x++;

 sleep 10;
 }

</pre>
<p>This doesn't do anything different than the previous script, it just does it another way.  Instead of just writing bytes, it specifically positions itself before writing.   If nothing else is happening with "t", no different outcome is expected.</p>
<p>What happens when we do "> t" while that puppy is running?</p>
<pre>
$ ls -l t;df | head -2
-rw-r--r--  1 apl  apl  20480 Nov 18 09:20 t
Filesystem    512-blocks      Used  Available Capacity  Mounted on
/dev/disk0s2   155629664 100006784  55110880    65%    /
$ > t
$ ls -l t;df | head -2
-rw-r--r--  1 apl  apl  0 Nov 18 08:36 t
Filesystem    512-blocks      Used Available Capacity  Mounted on
/dev/disk0s2   155629664 100006176  55111488    65%    /
</pre>
<p>Instant reclaim.  But on the next write from the script, the file's 
size is right back up:</p>
<pre>
$ ls -l t;df | head -2
-rw-r--r--  1 apl  apl  20480 Nov 18 08:36 t
Filesystem    512-blocks      Used Available Capacity  Mounted on
/dev/disk0s2   155629664 100006216  55111448    65%    /
</pre>
<p>But - and this is the important part - notice that the available disk 
space did NOT change!</p>
<p>What happens here is that the file goes to zero and available space increases, but then when the writer writes again, it's back to a large size instantly.  That's because of the "seek" - the bytes were written at a specific position. But the available space is NOT back to what it was, and "od" shows why:</p>
<pre>
$ od -c t
0000000   \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
*
0040000    x   x   x   x   x   x   x   x   x   x   x   x   x   x   x   x
*
</pre>
<p>If you had looked at "t" before the ">", it would have looked like this:</p>
<pre>
$ od -c t
0000000    x   x   x   x   x   x   x   x   x   x   x   x   x   x   x   x
*
</pre>
<p>"od" shows repeated bytes by an '*" - since we are writing nothing but "x", there's no need to show more.  After the ">", "od" shows "0" in all of the bytes up to the subsequent write by the script.  Those nul bytes aren't really there - this is a <a href="http://aplawrence.com/Words/2003_10_04.html">"sparse" file</a>.  It was created by the absolute seeks of the perl script after "> t" had emptied the file.</p>
<p>If you didn't understand this, I encourage you to play with these scripts 
on your own system.  To avoid confusion, the system should be relatively "quiet"  while you do this - I couldn't control that absolulutely here so some 
figures shown by "df" are different than you might expect - that's because I had 
a few other things going on while doing this.  You still should be able 
to see that ">" really does reclaim space.</p>
<p>The lesson is this:  if another process has a file open, use ">" to reclaim the disk space.   If the process is doing absolute seeks, you may not be able to tell with "ls -l" that the space has been reclaimed, but it will be.</p>


<p>Comments: <a href="http://aplawrence.com/cgi-bin/newcomm.pl?commenting=/Unixart/freeing-disk-space.html">Click Here.</a></p>

<p><br /><br /><i><b>Many of the products and books I review are things I purchased for my own use.  Some were given to me specifically for the purpose of   reviewing them.</b></i></p>
<p><i><b>I resell or can earn commissions from the sale of some of these items.  Links within these pages may be affiliate links that pay me for referring you 
to them. That's mostly insignificant amounts of money; whenever it is not I have made my relationship plain.  If you have any question, please do feel free to contact me.</b></i></p>
<div style="font-size:80%">
<table>
<tr>
<td> - </td>
<td><a href="http://aplawrence.com/Tests">Skills Tests</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/psst.html">Psst - wanna work for yourself?</a></td>
<td> - </td><td><a href="http://aplawrence.com/troubleshootingbook.html">Unix/Linux Troubleshooting e-book</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/Kerio">Kerio Mail Server</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/rates.html">Consulting</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/advert.html">Advertise Here</a></td>
</tr>
</table>
</div>
]]>
</description>
<link>http://aplawrence.com/Unixart/freeing-disk-space.html</link>
</item>
<item rdf:about="http://aplawrence.com/Books/art-of-seo.html">
<title>The Art of SEO  </title>
<description>
<![CDATA[
Books,Reviews,Web-HTML,Blogging 

2009/11/17<br /><br />
<!-- LEFTADOK -->
<!-- PCOUNT -->
<!-- PCOUNT -->

<div class="hReview">
<div class="item">


<p><a href="http://www.aplawrence.com/Books/bysubject.html" target=
"_self">Index by Subject</a></p>
<ul>
<li><span class="fn">The Art of SEO</span></li>
<li>Enge, Spencer, Fishkin, Stricchiola</li>
<li>0596518862</li>

</ul><br /><br />
<p>I hope this book helps put an end to ridiculously priced SEO "courses".  It 
could also help eliminate some of the shadier practitioners of SEO, but 
I'd be happy if it just helps a few people avoid wasting money on nonsense.</p>
<p>This book isn't nonsense.  It's a complete exposition of the state of SEO 
as it stands today.  More than 500 pages cover everything you could ever 
hope to know about optimizing your website for search engines.</p>
<p>I've said before that it's unnecessary to pay for expensive courses to learn SEO because all of it, every single thing you'd ever need to know, is available on the Internet for free.  That's still true, though of course the problem is that you have to find it and learn to discern good advice from bad, outdated concepts from those that reflect current reality.  This book pulls everything 
together in 500 pages or so,</p>
<p>Of course it's not for everyone.  It assumes some technical knowledge or 
at least access to someone with that knowledge.  As an example, at several points 301 redirects are used as the solution certain SEO issues.  Although 
some minor direction is given about implementing these, you'd need more than 
is provided here if you were a neophyte - someone using Blogger or Wordpress.com isn't going to become proficient with Apache from reading this.</p>
<p>The only small complaint I can make is that sometimes the authors use 
too many examples, especially for the more basic concepts at the beginning 
of the book.  However, too many is far better than too few, so I won't 
complain too much.  I definitely can't complain that they left anything 
out: this could serve as a course book for a SEO class.</p>
<p>So, once more:  don't waste your money on expensive "courses" from self-styled Internet Gurus.  Buy this instead.  If you are already reasonably 
proficient in this area, this book can serve as a reference and refresher. 
Either way, I strongly recommend it.</p>

<div class="summary">
</div>
<br />
<p><span class="reviewer">Tony Lawrence</span> <span class="dtreviewed">2009-05-03</span> Rating:  <span class="rating">4.5</span></p>


<p align="left"><img src="/126X32-b-logo.gif" border="0" width=
"126" height="32" alt="graphic of book cover" /> Order (or just read more about) <a class="url fn" href="http://www.amazon.com/exec/obidos/ASIN/0596518862/aplawrencescouni" target="_top">The Art of SEO</a>  from Amazon.com. Yes, I earn a small referral fee if you use that link to purchase the book.</p>
</div>
</div>


<p>Comments: <a href="http://aplawrence.com/cgi-bin/newcomm.pl?commenting=/Books/art-of-seo.html">Click Here.</a></p>

<p><br /><br /><i><b>Many of the products and books I review are things I purchased for my own use.  Some were given to me specifically for the purpose of   reviewing them.</b></i></p>
<p><i><b>I resell or can earn commissions from the sale of some of these items.  Links within these pages may be affiliate links that pay me for referring you 
to them. That's mostly insignificant amounts of money; whenever it is not I have made my relationship plain.  If you have any question, please do feel free to contact me.</b></i></p>
<div style="font-size:80%">
<table>
<tr>
<td> - </td>
<td><a href="http://aplawrence.com/Tests">Skills Tests</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/psst.html">Psst - wanna work for yourself?</a></td>
<td> - </td><td><a href="http://aplawrence.com/troubleshootingbook.html">Unix/Linux Troubleshooting e-book</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/Kerio">Kerio Mail Server</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/rates.html">Consulting</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/advert.html">Advertise Here</a></td>
</tr>
</table>
</div>
]]>
</description>
<link>http://aplawrence.com/Books/art-of-seo.html</link>
</item>
<item rdf:about="http://aplawrence.com/Unixart/sort-vs-uniq.html">
<title>Sort -u vs. uniq  </title>
<description>
<![CDATA[
Linux,MacOSX,Basics,Shell,Programming 

2009/11/15<br />
<!-- LEFTADOK -->
<!-- PCOUNT -->
<!-- PCOUNT -->

<p>I have sometimes seen people use a pipeline that includes "sort | uniq".  The result of that is no different than just adding a -u flag to sort and absolutely requires more time and processing power - not that it usually matters; unless the input is humongously long, you'd need to run them through "time" to spot any difference.   So why use "uniq"?</p>
<p>For cases like that, where there is no difference in the output, it's probably just habit - you may be accustomed to using "uniq" for other jobs and just reach for it automatically.  I'll argue that it's a good habit to have:  if you are in the habit of using "sort -u", you may tend to forget about "uniq" and that could cause you do do something much more difficult and clumsy when a job needs something that "uniq" does well.</p>
<p>However, it's also true that "sort" has tricks that "uniq" lacks, so if you only know about "uniq", you again could make your life more difficult.</p>
<p>One of the helpful abilities that "sort" has is the ability to specify the field separator.  Let's take a sample file:</p>
<pre>
A:B:C:D
a:b:c:d
t:b:c:d
t:b:c:d
a:b:c:d
a:b:x:d
foo:b:x:d
f:a:x:d
</pre>
<p>If all we cared about was removing duplicatelines, we could use "sort -u file" or "sort file | uniq".  But what if we want to sort by the second field?</p>
<p>We can do that directly with "sort -t: -k 2 -u", but it's much harder to do with "uniq" because you can't tell it a separator character.  You can get around that partially with "tr" or "sed", translating ":"'s to spaces or tabs, but that's clumsy.   Even after translating, "uniq" only lets you skip fields, so you don't get quite the same output:</p>
<pre>
$ sort -t: -k 2 -u file
A:B:C:D
f:a:x:d
a:b:c:d
a:b:x:d
$ cat file | tr ":" " " | sort | uniq -f1
A B C D
a b c d
a b x d
f a x d
foo b x d
t b c d
</pre>
<p>We could argue about which output truly represents unique lines when sorted on field 2, but the point to understand is that skipping fields isn't the same as what "sort" does.</p>
<p>You can also lock down fields with "sort" :</p>
<pre>
$ sort -t: -u -k2,2   file
A:B:C:D
f:a:x:d
a:b:c:d
</pre>
<p>As "uniq" can only skip fields and can't anchor to one field only, it's much harder to get these results.  However, "uniq" again has tricks that "sort" can't do: it can skip a specific number of characters in addition to   skipping fields.  It can also give you only the unique lines or only the lines that were repeated:</p>

<pre>
$ sort file | uniq -u  # only the unique, non-repeated lines
A:B:C:D
a:b:x:d
f:a:x:d
foo:b:x:d
$ sort file | uniq -d  # repeated lines
a:b:c:d
t:b:c:d
</pre>
<p>Either of those is extremely convoluted without "uniq", and the need for one or the other does come up surprisingly often.</p>
<p>Somebody thought that we could use "sort" and "uniq" in one program: <a href="http://256.com/sources/sortu/">Sortu</a> is the result.</p>

<blockquote>
The sortu program is a replacement for the sort and uniq programs. It is common for Unix script writers to want to count how many separate patterns are in a file. For example, if you have a list of addresses, you may want to see how many are from each state. So you cut out the state part, sort these, and then pass them through uniq -c. Sortu does all this for you in a fraction of the time. 
</blockquote>
<p>I think by the time I figured out how to use "sortu" I could have already done the job another way, but you might find it interesting anyway.</p>
<p>I think the important thing is to realize that "sort" and "uniq" have both conflicting and complementary abilities.  Don't tie yourself in pipeline knots with either of them; learn to use each of them appropriately and your scripts will be easier.</p>


<p>Comments: <a href="http://aplawrence.com/cgi-bin/newcomm.pl?commenting=/Unixart/sort-vs-uniq.html">Click Here.</a></p>

<p><br /><br /><i><b>Many of the products and books I review are things I purchased for my own use.  Some were given to me specifically for the purpose of   reviewing them.</b></i></p>
<p><i><b>I resell or can earn commissions from the sale of some of these items.  Links within these pages may be affiliate links that pay me for referring you 
to them. That's mostly insignificant amounts of money; whenever it is not I have made my relationship plain.  If you have any question, please do feel free to contact me.</b></i></p>
<div style="font-size:80%">
<table>
<tr>
<td> - </td>
<td><a href="http://aplawrence.com/Tests">Skills Tests</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/psst.html">Psst - wanna work for yourself?</a></td>
<td> - </td><td><a href="http://aplawrence.com/troubleshootingbook.html">Unix/Linux Troubleshooting e-book</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/Kerio">Kerio Mail Server</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/rates.html">Consulting</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/advert.html">Advertise Here</a></td>
</tr>
</table>
</div>
]]>
</description>
<link>http://aplawrence.com/Unixart/sort-vs-uniq.html</link>
</item>
<item rdf:about="http://aplawrence.com/Girish/LiveUSB.html">
<title>LiveUSB OpenBSD project at sourceforge  by Girish Venkatachalam</title>
<description>
<![CDATA[
Programming,Girish 

2009/11/14 Girish Venkatachalam

<!-- LEFTADOK -->
<!-- PCOUNT -->
<!-- PCOUNT -->

<br /><br />
<p><i>Girish Venkatachalam is a UNIX hacker with more than a decade of
networking and crypto programming experience.
His hobbies include yoga,cycling, cooking and he <a href="http://gayatri-hitech.com/about.html">runs his own
business.</a> Details here:</i><br /><br />

<a href="http://gayatri-hitech.com">http://gayatri-hitech.com</a>
<br /><a href="http://spam-cheetah.com">http://spam-cheetah.com</a>
</p>
<p>
It is really easy to create a USB bootable OpenBSD LiveUSB image. With
that you can do just about anything you want. Don't believe me?
</p>

<p>
Then head to <a href="http://liveusb-openbsd.sf.net" target="_blank">http://liveusb-openbsd.sourceforge.net</a>
and download the USB image. Boot it and find out!

</p>

<p>
You can watch videos with mplayer in full screen, you can bask in the
glory of mplayer's sexy OSD menu, you can read manual pages in color,
you can lookup English words using the dictionary client, you can chat
with pidgin, you can browse with Mozilla Firefox, you can use sox to
convert audio, you can play any video or audio file with mplayer, you
can stream audio from the Internet, you can do whatever you want!
</p>

<p>
Moreover you can also use the rich repertoire of tiny but incredibly
powerful tools like netcat, socat, nmh, mutt, vim, randtype, figlet.
After all the man pages tell you how to use these tools and you have
examples too. You also have ready access to the perl, python and lua
interpreters, you have all the spam control daemons, the routing
protocols like BGP or OSP, you have FTP server, HTTP server or 
 you could do image processing with ImageMagick.
</p>

<p>
There is one detail however.
</p>

<p>
You have to use DHCP to connect to the Internet if your ADSL MODEM
dishes out dynamic IPs or you can configure the IP using the ifconfig
command. Usually this will do.

</p>

<pre>
	# dhclient vr0
	(Your ethernet interface could be fxp0, rl0 or something else,
find out with ifconfig)
</pre>

<p>
Give it a whirl and get in touch with me should you have any issues
using this. After all it is free and open source.
</p>

<p>
And oh by the way the fixed write cycles of USB memory drives is largely
a myth.
</p>


<div style="text-align:center"><a href="http://www.spam-cheetah.com/"><img src="http://www.spam-cheetah.com/images/spam-cheetah.jpg" alt="running cheetah" /><br /> SpamCheetah<br />Stop spam dead in its tracks!</a></div>


<p>Comments: <a href="http://aplawrence.com/cgi-bin/newcomm.pl?commenting=/Girish/LiveUSB.html">Click Here.</a></p>

<p><br /><br /><i><b>Many of the products and books I review are things I purchased for my own use.  Some were given to me specifically for the purpose of   reviewing them.</b></i></p>
<p><i><b>I resell or can earn commissions from the sale of some of these items.  Links within these pages may be affiliate links that pay me for referring you 
to them. That's mostly insignificant amounts of money; whenever it is not I have made my relationship plain.  If you have any question, please do feel free to contact me.</b></i></p>
<div style="font-size:80%">
<table>
<tr>
<td> - </td>
<td><a href="http://aplawrence.com/Tests">Skills Tests</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/psst.html">Psst - wanna work for yourself?</a></td>
<td> - </td><td><a href="http://aplawrence.com/troubleshootingbook.html">Unix/Linux Troubleshooting e-book</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/Kerio">Kerio Mail Server</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/rates.html">Consulting</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/advert.html">Advertise Here</a></td>
</tr>
</table>
</div>
]]>
</description>
<link>http://aplawrence.com/Girish/LiveUSB.html</link>
</item>
<item rdf:about="http://aplawrence.com/Unixart/google-go.html">
<title>Google's Go  </title>
<description>
<![CDATA[
Linux,MacOSX,Programming 

2009/11/12<br />
<!-- LEFTADOK -->
<!-- PCOUNT -->
<!-- PCOUNT -->

<p>Google has introduced <a href="http://golang.org/doc/go_faq.html">Go</a>.  Normally, the announcement of a new language isn't likely to get me to even click through to read about it - what do I need a new language for?  Can't I get myself screwed up enough with the languages I already know?</p>
<p>Well, the names on the Go design team rung a few bells: Robert Griesemer, Rob Pike, Ken Thompson, Ian Taylor, Russ Cox, Jini Kim and Adam Langley.  Yes, THAT Rob Pike, THAT Ken Thompson.</p>

<p>And, what the heck, Google does interesting stuff, so I thought I'd take a look and...  well, Go is interesting.  There's actually a lot to like.</p>
<p>The first thing I noticed as I worked through the sample code was grouping.  In most languages you might do something like this to declare variables and constants:</p>
<pre>

$counter=0;
$pi=3.1415926;
$Space = " ";
$Newline	= "\n";
</pre>
<p>With Go, you can group related items:</p>

<pre>

const (
	Space	= " ";
	Newline	= "\n";
)

var (
	countLock	sync.Mutex;
	inputCount	uint32;
	outputCount	uint32;
	errorCount	uint32;
)
</pre>

<p>This isn't a big deal, but it helps make intentions clear, and it does save a little typing.</p>
<p>Go has other tricks to save typing.  When you initialize a variable, the compiler works like Perl - it takes the clue from the value you provided.  So, while you could say</p>
<pre>
var s string = "";
</pre>
<p>, you can shorten that to</p>
<pre>
var s  = "";
</pre>
<p>I like that you can also do</p>
<pre>
 s := "";
</pre>
<p>because that's the same convention used in loops:</p>
<pre>
 for i := 0;  < flag.NArg(); i++ {
</pre>
<p>Not a big deal, but it makes sense, so it will be easy to remember, and it also stands out - you KNOW that := is initialization, wherever you see it.</p>
<p><b>Formatting</b></p>
<p>Formatting is something i always have trouble with.   I'm just not disciplined enough to be consistent. I'm hardly alone - there have been many "pretty print" programs for C and other languages.  Go introduces its own "gofmt" program.   Unlike general purpose code beautifiers, gofmt knows about Go and won't even touch something it doesn't see as legitimate.  Google says:</p>
<div style="margin-left:25px">
<p>
Formatting issues are the most contentious but the least consequential. People can adapt to different formatting styles but it's better if they don't have to, and less time is devoted to the topic if everyone adheres to the same style. The problem is how to approach this Utopia without a long prescriptive style guide.</p>

<p>With Go we take an unusual approach and let the machine take care of most formatting issues. A program, gofmt, reads a Go program and emits the source in a standard style of indentation and vertical alignment, retaining and if necessary reformatting comments. If you want to know how to handle some new layout situation, run gofmt; if the answer doesn't seem right, fix the program (or file a bug), don't work around it.</p>

<p>As an example, there's no need to spend time lining up the comments on the fields of a structure. Gofmt will do that for you. Given the declaration</p>
<pre>
type T struct {
    name string; // name of the object
    value int; // its value
}
</pre>

<p>gofmt will line up the columns:</p>
<pre>
type T struct {
    name    string; // name of the object
    value   int;    // its value
}
</pre>
</div>
<p>Ok, small details, but still, that is nice. Remember, the point isn't that 
a particular beautifier does this or that, it's that gofmt specifically 
understands Go code.</p>
<p><b>Function return values</b></p>
<p>Again, this is no big deal because no matter what the language there's a workaround, but Go directly supports multiple return values.  No arrays, no pointers to structures, just: </p>
<pre>
return x, i;
</pre>
<p>It's obvious, unhidden, far less confusing.</p>
<p><b>Slices, Maps, comma ok</b></p>
<p>Go doesn't do pointers.  Instead, you pull slices, much like array slices in Perl. So, buffer[10,50] is 50 bytes (or is it 40?)  from buffer, starting at its 10th byte.</p>
<p>Maps are like associative arrays:</p>
<pre>
var weekday = map[string] int {
	"Sun":  0,
	"Mon":  1,
	"Tue":  2,
	"Wed":  3,
	"Thu":  4,
	"Fri":  5,
	"Sat":  6,
}
</pre>

<p>Ordinarily, you'd expect an uninitialized reference to cause some problem or return a null value, and that's true for Go - if you reference  weekday["FOO"], Go crashes.  But, not if you do it this way:</p>
<pre>

day, ok = weekday[which]
</pre>
<p>With that syntax, ok is set to boolean "true" if "which" is valid and false otherwise.  Easy, right?</p>
<p><b>Much more</b></p>
<p>The designers really do seem to have thought things through well.  There's much, much more at the link I gave above.  I don't think I'll use Go for anything real, but it's fun to see the ideas.</p>
<p>See <a href="http://scienceblogs.com/goodmath/2009/11/googles_new_language_go.php?utm_source=nytwidget">Google's New Language: Go</a> also.</p>




<p>Comments: <a href="http://aplawrence.com/cgi-bin/newcomm.pl?commenting=/Unixart/google-go.html">Click Here.</a></p>

<p><br /><br /><i><b>Many of the products and books I review are things I purchased for my own use.  Some were given to me specifically for the purpose of   reviewing them.</b></i></p>
<p><i><b>I resell or can earn commissions from the sale of some of these items.  Links within these pages may be affiliate links that pay me for referring you 
to them. That's mostly insignificant amounts of money; whenever it is not I have made my relationship plain.  If you have any question, please do feel free to contact me.</b></i></p>
<div style="font-size:80%">
<table>
<tr>
<td> - </td>
<td><a href="http://aplawrence.com/Tests">Skills Tests</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/psst.html">Psst - wanna work for yourself?</a></td>
<td> - </td><td><a href="http://aplawrence.com/troubleshootingbook.html">Unix/Linux Troubleshooting e-book</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/Kerio">Kerio Mail Server</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/rates.html">Consulting</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/advert.html">Advertise Here</a></td>
</tr>
</table>
</div>
]]>
</description>
<link>http://aplawrence.com/Unixart/google-go.html</link>
</item>
<item rdf:about="http://aplawrence.com/Unixart/network-fishing.html">
<title>Fishing for an unknown device  </title>
<description>
<![CDATA[
Linux,MacOSX,Networking,Perl 

2009/11/10<br />
<!-- LEFTADOK -->
<!-- PCOUNT -->
<!-- PCOUNT -->

<p>A customer bought a Linksys print server.   It comes with a Windows CD that is supposed to allow you to configure the box, but with his Windows Vista machines, the print server couldn't be found.  Probably the software doesn't  work well with Vista. </p>
<p> More aggravatingly, I couldn't find a MAC address printed anywhere on the device, so I couldn't set an IP with arp -s (which then would have let me finish configuring the device using a browser).</p>
<p><i>Yes, someone pointed out how to get it to spit out a configuration page.  This post really isn't about the Linksys, so read on.</i></p>
<p>What to do?   </p>
<p>If you have a DHCP server anywhere in the network, the device will have obtained an IP address.  The DHCP server should be able to show you addresses it has passed out.  The only problem is recognizing it - if the server doesn't bother to show you when the DHCP lease was acquired, it may not be easy to spot the new addition.</p>
<p>That was my problem - too many leases and without the MAC address (and too many Linksys devices scattered about to start with), I couldn't spot it.  Well, that's not entirely true:  I probably could have, but I was also pressed for time:  this was Boston job and it was getting later in the day and the last thing i want to do is be in Expressway traffic much after 2:00 PM.</p>
<p>So.. . I threw the Linksys in my car and drove home, avoiding rush hour by a comfortable margin.</p>
<p>Back home, I  hooked up the print server to my network and was able to quickly spot it in the router's DHCP list.  I typed that IP into a browser and now had access to the print server admin screens.   That's great, but the customer's network is 192.168.24.0 and mine is 192.168.113.0.    Simple enough to change that - I knew an available IP on their network, so I typed it in.   Of course, immediately after 
doing so, I no longer had access to the print server, right?</p>
<p>Well, no.  All I need to do is temporarily change my machine to use something in that range.   The ethernet cables don't care if some of the devices are using one ip scheme and some are using others (a smart switch might care, but inexpensive little things like I use in my home do not). </p>
<p>Or  could I use an alias.  On the Mac, I'd do </p>
<pre>
sudo ifconfig en0 alias 192.168.24.12 netmask 255.255.255.0
</pre>
<p>For Linux, I'd do:</p>
<pre>
ifconfig eth0:0 192.168.24.12
</pre>
<p>(See <a href="http://aplawrence.com/Linux/adding_ip_aliases.html">Multiple IP addresses on one interface
</a>)</p>
<p>But what if I didn't have a DHCP server?   The Linksys probably comes configured with some IP address (even if it is 0.0.0.0).  If I don't know the MAC, and it isn't getting an IP from DHCP, how can I find it?</p>
<p>Ahh, that's not so easy.  You could guess at the IP range:  many devices default to 192.168.1.x or 192.168.2.x addresses; setting your machine to something in that range (or use an alias) would let you then do a discover ping (ping 192.168.1.255) or use "nmap nmap -s 192.168.4.0/24", but you 
might not find it if it isn't responding to ICMP.  Yes, "nmap" can do a UDP scan, but again - who says this device will respond?</p>
<p>Well, nmap can test against ports you know it will respond on.  For example, that print server is going to be listening on port 80.  I could do  nmap -p 80 192.168.11.0/24 - but again, I'm assuming the ip range and must be configured to be able to access that range.You can't use nmap to discover devices on networks your machine can't talk to.</p>
<p><b>Forget about the printserver - how can we find any unknown device?</b></p>
<p>I'm not aware of any generic layer 2 discovery software (just because I'm not aware of it doesn't mean it doesn't exist!), but you can use tcpdump.  The problem is filtering out all the unrelated traffic.  For example, I changed a spare Windows laptop to use 
172.16.48.9 - that's outside of my normal network.   In a few seconds, a "sudo tcpdump | grep 172.16" started showing activity:</p>
<pre>
11:31:05.578203 IP 172.16.48.9 > igmp.mcast.net: igmp v3 report, 1 group record(s)
11:31:05.579545 ARP, Request who-has 172.16.48.9 tell 172.16.48.9, length 46
11:31:05.883441 ARP, Request who-has 172.16.48.9 tell 172.16.48.9, length 46
11:31:06.517325 IP 172.16.48.9 > igmp.mcast.net: igmp v3 report, 1 group record(s)
</pre>
<p>But that was only easy to find because I knew I was looking for 172.16. </p>
<p>I could do "sudo tcpdump -n  |grep -v 192.168" to cut down a lot of the noise - but if the device I want is in that range, I won't see it, so I have to be careful about what I exclude.  Also, this depends upon the device being noisy - though at a power cycle almost any network device has to make SOME network noise.</p>
<p>A better way might be to use a Perl or Awk script that would sample tcpdump and extract unique IP addresses.  That's not hard:</p>
<pre>
#!/usr/bin/perl
while (<>) {
 @stuff=split /\s+/;
 $ip=sprintf("%d.%d.%d.%d",split /\./,$stuff[2]) if $stuff[1] == "IP";
 $ip2=sprintf("%d.%d.%d.%d",split /\./,$stuff[4]) if $stuff[1] == "IP";

 if (not $stored{"$ip > $ip2"}) {
   print "$ip > $ip2 seen\n";
   $stored{"$ip > $ip2"}=1;
 }
 
}
</pre>
<p>I changed the Windows box to 172.16.13.98 and very quickly saw:</p>
<pre>
192.168.113.2 > 64.226.42.29 seen
64.226.42.29 > 192.168.113.2 seen
192.168.113.2 > 66.249.81.100 seen
66.249.81.100 > 192.168.113.2 seen
192.168.113.2 > 74.125.93.100 seen
<b>172.16.13.98 > 224.0.0.251 seen</b>
74.125.93.118 > 192.168.113.2 seen
192.168.113.2 > 74.125.93.118 seen
<b>172.16.3.98 > 224.0.0.22 seen</b>
<b>0.0.0.0 > 172.16.3.98 seen</b>
192.168.113.2 > 66.249.80.83 seen
66.249.80.83 > 192.168.113.2 seen
<b>172.16.3.98 > 224.0.0.251 seen</b>
<b>172.16.3.98 > 239.255.255.250 seen</b>
</pre>
<p>(bolding added)</p>

<p>Fairly easy to spot that (and eliminating 192.168 addresses would have made it even easier) - though for this, a simple <b> sudo tcpdump -n | grep "who-has"</b> would have worked well, too.  The Perl script has the advantage of spotting any kind of activity (and just might show you activity you didn't expect!).</p>
<p>Did I miss anything?  Do you have any tricks I forgot?  Please do comment if you do.</p>

<p>Comments: <a href="http://aplawrence.com/cgi-bin/newcomm.pl?commenting=/Unixart/network-fishing.html">Click Here.</a></p>

<p><br /><br /><i><b>Many of the products and books I review are things I purchased for my own use.  Some were given to me specifically for the purpose of   reviewing them.</b></i></p>
<p><i><b>I resell or can earn commissions from the sale of some of these items.  Links within these pages may be affiliate links that pay me for referring you 
to them. That's mostly insignificant amounts of money; whenever it is not I have made my relationship plain.  If you have any question, please do feel free to contact me.</b></i></p>
<div style="font-size:80%">
<table>
<tr>
<td> - </td>
<td><a href="http://aplawrence.com/Tests">Skills Tests</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/psst.html">Psst - wanna work for yourself?</a></td>
<td> - </td><td><a href="http://aplawrence.com/troubleshootingbook.html">Unix/Linux Troubleshooting e-book</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/Kerio">Kerio Mail Server</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/rates.html">Consulting</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/advert.html">Advertise Here</a></td>
</tr>
</table>
</div>
]]>
</description>
<link>http://aplawrence.com/Unixart/network-fishing.html</link>
</item>
<item rdf:about="http://aplawrence.com/Unixart/awk-vs.perl.html">
<title>Awk vs. Perl  </title>
<description>
<![CDATA[
Linux,MacOSX,Shell,Perl 

2009/11/09<br />
<!-- LEFTADOK -->
<!-- PCOUNT -->
<!-- PCOUNT -->

<p>At any Linux/Unix forum a large number of posts have to do with sed and awk - how do I do this, how do I do that?</p>
<p>I can see using sed.   It's quick, it's simple  (unless we are doing something complicated) and easy to learn.   On the other hand, we have "awk", which is nasty and error prone even in its most basic invocations.</p>
<p><i>That's just my opinion, of course.</i></p>
<p>Sure, I used to use awk.   When I used it, you weren't likely to find Perl on 
most Unix systems, so for a lot of text mangling, awk was at least easier than writing in C or anything else.  It did the job, and you'd get used to its quirks.</p>
<p>As Perl became ubiquitous, I thought of  awk like something sticky you'd find under your car seat.   Whatever use that thing may have had in the past, it's heading for the trash now.   Why on earth would I suffer with awk's limitations and difficult synatx when I have Perl?</p>
<p>For me, awk synatx always seemed, well, awkward.  Perl immediately 
made sense to me.  In a way, that's scary, because it could mean that my mind works like Larry Wall's mind, and if that wouldn't cause you to check in with a psychiatrist, I don't know what would.  </p>
<p>I'm hardly alone in that opinion. Many of those forum questions end up 
being answwered by a Perl script.  To me, the Perl solution always seems 
easier to read and understand (that may just be my screwy mind, again).</p>
<p>Yet the forum questions persist.  Some of it is homework:  you can often tell when the petitioner includes such damning information as "I have to use awk.  Can't use Perl" or forgets to delete instructions like "Show your work" when cutting and pasting.  But it's not all homework: apparently a large number of people still use awk.</p>
<p>I went looking for why and found this: <a href="http://www.softpanorama.org/Tools/awk.shtml">AWK Programming
</a>.  Some of the arguments made there in favor of awk include:</p>
<div style="font-style:italic">
<ul>
		<li>awk is simpler (especially important if deciding which to learn 
		first) </li>

		<li>awk syntax is far more regular (another advantage for the beginner, 
		even without considering syntax-highlighting editors) </li>
		<li>you may already know awk well enough for the task at hand
		</li>
		<li>you may have only awk installed </li>
		<li>awk can be smaller, thus much quicker to execute for small programs
		</li>
		<li>awk variables don't have `$' in front of them :-) </li>

		<li>clear perl code is better than unclear awk code; but NOTHING 
		comes close to unclear perl code</li>
	</ul>
</div>
<p>I'm not entirely in agreement - I don't think awk is "simpler" or has better syntax, but I can see that you could argue that.  But even that page admits that "Generally Perl might be better for really complex tasks".  I'd argue that awk is clumsy at complex tasks, but I definitely have to agree with that last comment about "unclear" code.</p>
<p>Probably many of the readers here used awk before discovering Perl.  Did  Perl win you over or do you still find yourself typing "awk" frequently?  If you haven't used Perl, is it the learning curve?  Or just that you can do whatever you need with the tools you already have?</p>





<p>Comments: <a href="http://aplawrence.com/cgi-bin/newcomm.pl?commenting=/Unixart/awk-vs.perl.html">Click Here.</a></p>

<p><br /><br /><i><b>Many of the products and books I review are things I purchased for my own use.  Some were given to me specifically for the purpose of   reviewing them.</b></i></p>
<p><i><b>I resell or can earn commissions from the sale of some of these items.  Links within these pages may be affiliate links that pay me for referring you 
to them. That's mostly insignificant amounts of money; whenever it is not I have made my relationship plain.  If you have any question, please do feel free to contact me.</b></i></p>
<div style="font-size:80%">
<table>
<tr>
<td> - </td>
<td><a href="http://aplawrence.com/Tests">Skills Tests</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/psst.html">Psst - wanna work for yourself?</a></td>
<td> - </td><td><a href="http://aplawrence.com/troubleshootingbook.html">Unix/Linux Troubleshooting e-book</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/Kerio">Kerio Mail Server</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/rates.html">Consulting</a></td>
<td> - </td>
<td><a href="http://aplawrence.com/advert.html">Advertise Here</a></td>
</tr>
</table>
</div>
]]>
</description>
<link>http://aplawrence.com/Unixart/awk-vs.perl.html</link>
</item>
</rdf:RDF>