Simple script to compare files in two directories..

Here’s a small script to compare the files in two different directories on a Linux machine. The script uses MD5 checksum to compare the files.

prefix1=“/usr/directory1″ # First directory without trailing /
prefix2=“/usr/directory2″ # Second directory without trailing /
find \-L “$prefix1″ \-type f \| while read filename; do
sum1=“$(md5sum \-b ”$prefix1$name“)”
sum2=“$(md5sum \-b ”$prefix2$name“)”
if \[ “${sum1% \*}” = “${sum2% \*}” \]; then
echo “ok: $prefix1$name”
echo “not ok: $prefix1$name”

Google does it again..

The almighty Google has come out with a new toy for me to play with :). I don’t claim, that I am a programmer by any means, but like to dabble in scripting now and then. So, I was really excited to see this new simple API from Google for creating charts. I can already imagine, how this can be used in generating some cool reports. Here’s my “Hello World” graph using the API.

Vinay Rocks

The code I used to generate this graph is


Looks like some smart and entrepenuring programmer is already making some money out of this API :). Check out this link for a very cool and smart implementation of the API

HOW TO : Cognos Installation

I tried setting up Cognos (Business Intelligence tool mainly used for reporting) on a test machine for Lakshmi to play around with. After going through the install, I can say with confidence that Cognos has some of the worst documentation :). Here are some quick tips that you won’t find in the official documentation for someone trying to configure Cognos BI 8.x on a Win2k3 server running MS SQL 2005 and IIS 6.0.

  1. After installing Cognos, run the “Cognos Configuration” tool and change the “Gateway URI” setting to “http://servername:portnumber/cognos8/cgi-bin/cognosisapi.dll” in the environment section.
  2. Edit the default.htm and index.htm file in the “< cognos install directory >\cognos\c8\webcontent” directory and replace cognos.cgi with cognosisapi.dll
  3. Open ISS manager and go to Web Service Extension. Add a new web service extension called isapi and add cognosisapi.dll as a required file. Make sure to set the extension status to Allowed.

This should enable you to launch cognos and log into the web interface.

Programming : C#

I have been itching to program in C# for a long time now.. finally got a chance to try it out due to requirement at work. Here’s a small snippet of code that does a bunch of things
1) Opens a directory and get a list of files in it
2) Parses the file name into multiple variables
3) Connects to Active Directory and gets properties for a user
4) Creates an error file with list of errors.
5) Creat an output file in csv format.

For the programming gurus out there, this should be pretty easy :).. I am sure that there are tons of errors in the way, I wrote the code, but this is a beginning :).

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.DirectoryServices;

namespace sortAssetData
class Program
static void Main(string[] args)
// Create a Log file and output file

System.IO.TextWriter infoLog = new System.IO.StreamWriter(“sortAssetDataLog.txt”);
System.IO.TextWriter outputLog = new System.IO.StreamWriter(“finalAssetData.csv”);

// Write the column headers into the output file
outputLog.WriteLine(“Last_Name, First_Name, Display_Name, Batt_Check_Version, Model_Type, Model_Number, Serial_Number, Batt_Manufacturer, Batt_Model, Batt_Serial_Number, Affected”);

// Define the folder where the data files are sitting
string fixDirectoy = “P:\\BatteryCheck_Results”;

// Change working directory to the folder with all the files

// Create a directory object to get list of asset files
System.IO.DirectoryInfo tempDirObject = new System.IO.DirectoryInfo(fixDirectoy);

// Get list of *.csv files in the asset folder
System.IO.FileInfo[] listOfFiles = tempDirObject.GetFiles(“*.csv”);

// Process each file in the directory
foreach (System.IO.FileInfo tempFile in listOfFiles)
// Display the current file that is being processed
System.Console.WriteLine(“Processing : {0}”, tempFile.Name);
infoLog.WriteLine(“Processing : {0}”, tempFile.Name);

// Split the file name into Domain, Hostname, Username
string tempData = tempFile.Name;
// Removing the .csv at the end of the file name
tempData = tempData.Replace(“.csv”, “”);
string[] sortData = tempData.Split(new Char[] { ‘_’ });

// If file name doesn’t contain 3 records (Domain, ComputerName and UserName), we ignore it
if (sortData.Length != 3)
infoLog.WriteLine(“ERROR : Bad file format : {0}”, tempFile.Name);

// Display the userdata we got from the file name
System.Console.WriteLine(“\nDomain :\t {0}”, sortData[0]);
System.Console.WriteLine(“Computer Name :\t {0}”, sortData[1]);
System.Console.WriteLine(“User Name :\t {0}\n”, sortData[2]);

// Get the users full name from ActiveDirectory
System.DirectoryServices.DirectorySearcher searchUser = new System.DirectoryServices.DirectorySearcher();
searchUser.Filter = String.Format(“(SAMAccountName={0})”, sortData[2]);
System.DirectoryServices.SearchResult resultFromAD = searchUser.FindOne();

// If the username doesn’t have a AD account, note and skip to the next file
if (resultFromAD == null)
System.Console.WriteLine(“ERROR : Bad User name : {0}”, sortData[2]);
infoLog.WriteLine(“ERROR : Bad User name : {0}”, sortData[2]);
//Parse the file and write data to the log file and also to the screen
System.IO.StreamReader tempSoureFile = new System.IO.StreamReader(tempFile.Name);
// Read the first line in the file and ignore it
string tempAssetData = tempSoureFile.ReadLine();
// Read the second line and store it to write to outputfile
tempAssetData = tempSoureFile.ReadLine();

string tempUserFirstName = resultFromAD.Properties[“sn”][0].ToString();
string tempUserLastName = resultFromAD.Properties[“givenname”][0].ToString();
string tempUserDisplayName = resultFromAD.Properties[“cn”][0].ToString();
outputLog.WriteLine(“{0},{1},{2},{3}”, tempUserFirstName, tempUserLastName, tempUserDisplayName, tempAssetData);
System.Console.WriteLine(“User First Name:\t {0}”, tempUserFirstName);
System.Console.WriteLine(“User Last Name:\t\t {0}”, tempUserLastName);
System.Console.WriteLine(“Display Name:\t\t {0}”, tempUserDisplayName);

RRDTOOL – How to remove spikes

We use Cacti at work to graph the usage of our clients links. It is a pretty popular feature with our customers. A problem (well not really. More like a gotcha) with rrdtool is the way it stores data. Here’ a quote from the rrd tutorial
“Round robin is a technique that works with a fixed amount of data, and a pointer to the current element. Think of a circle with some dots plotted on the edge, these dots are the places where data can be stored. Draw an arrow from the center of the circle to one of the dots, this is the pointer. When the current data is read or written, the pointer moves to the next element. As we are on a circle there is no beginning nor an end, you can go on and on. After a while, all the available places will be used and the process automatically reuses old locations. This way, the database will not grow in size and therefore requires no maintenance. RRDTool works with with Round Robin Databases (RRDs).”

So rrd stores the difference in values (between the last value and current) in the database, rather than the value itself. This creates a problem when routers are rebooted. The counters on the interfaces get cleared and rrd is fooled into thinking that there is a spike in usage. This results to “spikes” in the graphs. Sometimes you see that a 128kbps link has maxed out at 98mbps!!! :). The best way to stop this from happening is to set the correct min and max values for the ds names. Coming back to cacti again. When cacti creates a new rrd database, it does not really give one the option to setup the maximum and minimum speeds of a interface. It defaults to a max of 100000000 (i.e. 100mbps). Occasionally when we have to reboot our routers, I do the following to remove the spikes

cp filename.rrd filename.rrd.backup
Any good admin knows that before you mess with a file, you make a backup :).

rrdtool info filename.rrd | more
This gives us the chance to get the ds (data sources) names

rrdtool tune filename.rrd -a ds_name:MAXIMUM_VALUE
Set the maximum of the ds to the required

rrdtool dump filename.rrd > filename.xml
Export all data in the rrd to a xml file

mv filename.rrd filename.rrd.old
Rename the rrd to make way for the new one.

rrdtool restore filename.xml filename.rrd -r
Restore the rrd from the xml file with the -r (range check) option. So any values that are higher than the new maximum value are ignored.

And the spikes are gone..

MySQL – Setting up initial privileges

Ever install MySQL and wondered what to do next? Well, the first thing is to secure the root user (Note: The MySQL root user is different from the OS root user). These three simple steps should deal with it.

shell> mysql -u root mysql
mysql> SET PASSWORD FOR [email protected]=PASSWORD(‘new_password’);

MySQL has really good documentation on their website. It is can be accessed here.