Friday, November 27, 2009

SOT: Heads or Tails? (Windows Resource Kit - Tail.exe Gotcha)

So I was comparing two windows implementations of tail, and came across something unexpected. While I was checking one of my tests, I noticed the results contained less lines than I requested. The base files definitely contained more than enough lines. So I knew that was not problem. After digging deeper, I discovered the lines returned were not even from the end of the file! They were from the middle.

Well, come to find out the file I was testing contained some funky characters. One of them being ascii character 26. Apparently the Windows Resource Kit version of tail.exe interprets ascii 26 as some sort of EOF (end of file) marker. Consequently tail.exe uses that marker as its starting point. Well, naturally that skews the results because that position is not necessarily the actual end of the file.

To see it for yourself, create a simple file containing 50 lines, with the ascii character 26 inserted every ten (10) lines.

<cfset specialChar  = chr(26)  />
<cfset newLine = chr(10) />
<cfsavecontent variable="data">
<cfoutput>
<cfloop from="1" to="50" index="x">Log file line #x# <cfif not x mod 10>#specialChar#</cfif>#newLine#</cfloop>
</cfoutput>
</cfsavecontent>

<cfset filePath = ExpandPath("./testLogFile.log") />
<cfset FileWrite( filePath, trim(data) ) />


Now use tail.exe to grab the last twenty (20) lines of the file. Due to the placement of the special characters, what you will end up with is the first 10 lines of the file, not the last twenty.




<cfset grabLines = 20 />
<cfexecute name='"c:\program files\Windows Resource Kits\tools\tail.exe"'
arguments='-#grabLines# #filePath#'
variable='output'
timeout='20' />

<!--- convert lines to array --->
<cfset linesFound = listToArray(output, chr(10), true) />
<cfset actualLines = listToArray( FileRead( filePath ), chr(10), true) />

<cfoutput>
<p><strong>Log File:</strong> #filePath# </p>
<p><strong>Requested Lines:</strong> #grabLines# </p>
<p><strong>Lines Found:</strong> #arrayLen(linesFound)#</p>
<p><strong>Actual Lines:</strong> #arrayLen(actualLines)#</p>
</cfoutput>


Fortunately, the GNUWin32 version does not suffer from this "problem" and returns the expected results. (Thank goodness someone knows basic subtraction)



As for the Windows Resource Kit version, well.. if we were flipping a coin, this time it was definitely "heads" - as in "head on over to sourceforge.net and get a yourself a working copy of tail.exe".

0 comments:

  © Blogger templates The Professional Template by Ourblogtemplates.com 2008

Header image adapted from atomicjeep