Category Archives: Linux Commands

Configure unixODBC for use with PHP and MSSQL on Oracle Linux

This short article describes how to configure unixODBC 2.2.11-10.el5 in conjunction with PHP 5.3.3-26. Many forums out there contain articles that describe the absence of php_mssql drivers in the oracle yum repo. There various reason for that; non in which Oracle has a part. No matter what reason you like best, there is a decent alternative by using unixODBC.

To help all the people out that are just looking for a solution I wrote this article. I wont go into depths, ill just describe the major steps with some hints and tips. Happy reading ūüôā

The OS version of my virtual box image:

Linux sandboxpinguin 2.6.18- #1 SMP Mon Mar 29 18:27:00 EDT 2010 x86_64 x86_64 x86_64 GNU/Linux
  1. Make sure you have the latest version of unixODBC installed. If Yum is configured correctly the following command should do the trick.
     yum update unixODBC
  2. Download the freeDTS driver, this is the driver unixODBC will use to connect to mssql. If wget is available on your production environment (remove it) after running the command:

    . Make sure you are in an desired location like your home folder.

  3. Unpack the tar-Gzip ball by running the following command
    tar -xf  ./freetds-stable.tgz
  4. Browse into the unpacked folder and run the configure command
    ./configure --with-tdsver=7.2 --enable-msdblib
  5. If the configure ran without any issues you can link/compile the driver by running the command:

    and then

    make install

    and then

    make clean

    Congratulations, you are now the pride owner of the freeDTS driver ūüôā

The next part tend to get a bit fuzzy, feel free to ask questions in the comment and ill try to answer them to the best of my ability.

There are allot of articles available on how to configure the unixODBC DSN correctly. Be adviced: the config is specific for your setup and usually needs to be tweaked. In order to enable you to ill explain the concepts of unixODBC. Ill point out some documentation, commands and stuff. Afterward ill have a short tutorial of the steps i used to configure the odbc connection.

  1. unixODBC is configured properly by using the


  2. unixODBC will write into:

    files and uses input files to do so;

  3. The connection can be tested with osql commands from bash, but! it will use the hidden .odbc.ini file in your profile instead of the /etc/odbc.ini. PHP and odbcinst use the one in /etc/odbc.ini. If the one in your profile works than make sure it is identical to the one located in /etc/ directory. Below how the osql output will look if configured correctly. (charset isnt relevant in this stage)
  4. Documentation on how to use FreeTDS in conjunction with unixODBC can be found here.
  5. Documentation on how to use ODBC can be found here
    (ignore the freetds configuration here and use ad4 to figure the settings out for your setup)

Next ill describe my steps in order to make it work.

Configuring the FreeTDS driver

  1. Create the file /etc/odbcDriver.ini
  2. Insert the following in the file (check the paths)
    Description     = FreeTDS Driver with protocol v5.0
    Driver          = /usr/local/freetds/lib/
  3. Create the file /etc/odbc.ini
  4. Insert the following and tweak this to match your environment
    Description     = FreeTDS Driver with protocol v5.0
    Driver          = /usr/local/freetds/lib/
    Server          = [SERVERIP]
    Port            = [REMOTE_TSQL_PORT]
    ClientCharset   = UTF-8
    TDS_Version     = 7.1
    Database        = [DATABASENAME]
    Trusted_Connection = Yes      # Required with most MSSQL environments.
  5. Register the ODBC driver
     odbcinst -i -d -f /etc/odbcDriver.ini 
  6. Register the data source
     odbcinst -i -s -f /etc/odbc.ini

Finally test your config by using the php odbc functions.

$sql = "select 1 + 5 as outcome";

$conn = odbc_connect("ExampleSource" , "Username", "Password");
$result = odbc_exec($conn, $sql);
$row = odbc_fetch_array($result);
echo $row['outcome'];

Good luck querying ūüôā

Oracle Enterprise Linux 6.x networking

Lately I got many questions regarding the network configuration of Oracle Enterprise Linux 6 (Red Hat Enterprise Linux 6).
Enough to write a little article about it.

It seems that some of the network configuration was altered in OEL6. The reason as far as I know is the implementation of the NetworkManager daemon. I don’t know why they are using CamelCase for the daemon name, but mind that. Even though the NetworkManager should make the configuration as painless as possible (at least thats what the manual page said), it seems to actually make the configuration more of a pain for some.

Below I will cover some topics in an effort to get you going and remove the pain ūüôā

Configuring eth0 for manual operation

  • Step 1: disable the NetworkManager daemon
    service NetworkManager stop
  • Step 2: remove the NetworkManager from Init (start-up)
    chkconfig --level 2345 NetworkManager off
  • Step 3: open the ifcfg-eth0 config file (alter the suffix ‘eth0’ to match the adapter of your choice)
    vi /etc/sysconfig/network-scripts/ifcfg-eth0
  • Step 4: Alter the following to match your environment…
    HWADDR={Your MAC address here}
    #PREFIX=24    [can be used alternativly to NETMASK=]
  • Step 5: Write/close the configuration file¬†(:wq in vi)
  • Step 6: Restart the network service
    service network restart
  • TIP 0: Obviously match the configuration above to match your home network.
  • TIP 1: NetworkManager is not always present in which case you can obviously skip step 1 – 2.
  • TIP 2: There are reports that is actually more stable then PREFIX=xx notation.
    My advice, use NETMASK= which is also better understood by non networking guys.
  • TIP 3: Not sure about the correct NETWORK, NETMASK, BROADCAST or PREFIX¬†settings, give ipcalc a try:
    ipcalc --netmask {IPADDR}
    ipcalc --prefix {IPADDR} {NETMASK}
    ipcalc --broadcast {IPADDR} {NETMASK}
    ipcalc --network {IPADDR} {NETMASK}

Configuring DNS

DNS always seems to be a bugger and a hard one to understand. Do note that DNS is JUST A IP PHONEBOOK. Nothing fancy there. Also there are various ways of configuring DNS. One way is by adding the DNS configuration in the ifcfg-suffix configuration file with the DNS1=ip.ip.ip.ip DNS2=ip.ip.ip.ip keywords.¬†As an¬†effect, the networking service will update the appropriate¬†configuration files.¬†To¬†be frank,¬†I find this to be confusing and do not like duplicate configurations everywhere in my -has to be clean- environment. My advice is to configure the DNS is the appropriate files directly like this…

  • Step 1: Edit¬†the¬†resolve.conf where DNS is configured.
    vi /etc/resolv.conf
  • Step 2: Add or Alter the following to match your environment
    search mydomain.home
  • Step 3: Test to see if name resolution works
    set debug
  • TIP 1: Linux actually tries to find the ip in the /etc/hosts file first. If you know the hostnamename and FQDN to an certain IP and it can be classified as static. Consider using the hostsfile instead of a centralized DNS. This will boost performance if the name is resolved often. If multiple systems use and depend on a machine reference, use centralized DNS in order to lighten the administrative tasks.
    vi /etc/hosts
  • TIP 2: Experiencing slow log on times or slow application performance? A faulty DNS configuration might just be the¬†cause. A quick way to test this is by¬†temp. disabling DNS all together. This can be done by editing the /etc/nsswitch.conf file.
    vi /etc/nsswitch.conf
    • alter the line
      hosts:     files dns
    • to the line
      hosts: files
    • write the file and test if the performance has improved.
  • The reason for this is that DNS is often used to register user logon or session information based on the visitors IP address. Examples are the ssh daemon, ftp servers, webservers, linux logon, etc.


In some case you want linux to use alternative routes to access certain Linux resources. The way to go in these cases are creating routes. In most cases you want these to be presistant in which case ‘route add –‘ wont suffice. In our example we will create two new routes. On describing a route to a specific host, the other describing the route to a specific network. Alter the example to match your needs.

  • STEP 1: Create a new file called static-routes in the¬†/etc/sysconfig/ directory
    vi /etc/sysconfig/static-routes
  • STEP 2: Add the following, obviously matching your specific needs
    any net gw metric 1
    any host gw metric 1
  • STEP 3: Restart the network service
    service network restart
  • TIP 1: SIOCADDRT: No such process means the designated gateway doesnt exsist on any known interface. (typo?)
  • TIP 2: view the route information usint the route command
  • TIP 3: use the ipcalc –prefix {IPADDR} {NETMASK} command to determin the right /prefix for your environment.
  • TIP 4: In older environments the ifup-routes is used, this shscript still exsists in the /etc/sysconfig/network-scripts/ifup-routes

Locate my mac address

The ifcfg-eth# config allows you to configure the specific mac address to guarantee the IP is bound to the right adapter. In virtualized environments this might save you a lot of trouble in the situation where the virtualized domain is altered. On the other hand it might cause trouble when the staticly configured MAC is migrated in virtual environments. Either case, you might want to know the MAC linux sees belonging to an certain adapter. You can find the MAC address in the following location:

 cat /sys/class/net/eth0/address

Obviously you need to alter eth0 in the path to match the adapter you are looking for. Not sure? The change directory to /sys/class/net and perform a list to see all discovered and registered adapters.

IPTables (Linux firewall)

By default IPtables (which is the linux firewall) is enabled. You can view the running configuration by checking the service status like this.

 service iptables status

You can simply turn the firewall off by modifying and applying steps 1-2 of the first configuring eth0 instruction. This will reduce the security of your linux platform significantly. My advice, add the ports you need for your services and let IPtables protect you. The easiest way is by simply editing the iptables configuration file.

 vi /etc/sysconfig/iptables 

Adding a port is as easy as copy/pasting the always present firewall rule that allowes port 22 (ssh). Copy past it and alter the -p (protocol) -dport (destination port) to match your needs. For example, allowing HTTP/HTTPS.

-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT

afterward restart iptables

service iptables restart

TIP: If you are experimenting with IPv6 (then your Instant COOL!), mind that the ipv6 firewall is called ip6tables and the configuration is called the same. The basic iptables doesnt handle ipv6 at all.

TIP: If you are using ipv6 code your IPv4 ip to ease administration. Example:

ipv6: 2001::0192:0168:0010:0001/64
Then route on the nibble of choice.

Additional questions?

Just post it below and maybe ill respond in due time ūüôā

Backup script for GLPI (

If you are using the great GLPI tool, you will notice that the market value of the data inside will increase rapidly. This usually also implicates that it is ‘wise’ to back this data up.

There are many ways to do so using nice plugins, even nicer gui`s and apps. I (headstrong that I am), wanted something very basic and functional, easy to configure, and that will work in an environment that has multiple GLPI installations. Answer to my question: build something for your own.

So i scripted something for Linux that will allow you to backup the entire GLPI tree (where the uploaded files reside), and the sql database.

Because we use a deduped backup storage (datadomain), i dont have to worry about duplicate data. If you need to, then add something to clean the backup store. This script doesn’t account for that ūüôā

This is the script:

# Wrote by Chris
# Goal is to easly backup glpi in a multi installation environment.


#Dont change anything after this point, unless you know what you are doing #
#No guarantees, une this script at own risk                                #

# Do some generic stuff here
# Add checks if you like ūüôā
MYSQLDUMP=`which mysqldump`;
AWK=`which awk`;
FIND=`which find`;
DATE=`date +%d.%m.%Y`;
LOGTIME=`date +"%d-%m-%Y %H:%m"`;
DBCONFIG=`find $GLPI_DIR -name "config_db.php"`;
DBNAME=`grep "dbdefault" $DBCONFIG | awk -F '=' '{ gsub(/\047/,""); gsub(/\;/,""); gsub(/ /,""); print $2;}'`;

# Start working....
echo -e "$LOGTIME \t## New backup started ##" >> $LOGFILE;
echo -e "$LOGTIME \tpacking: $GLPISIZE.. into $BACKUP_DIR/backup.$DATE.tar.bz2 ..." >> $LOGFILE;
tar -cjPf $BACKUP_DIR/backup.$DATE.tar.bz2 $GLPI_DIR >> $LOGFILE;
echo -e "$LOGTIME \tCreating mysqldump into $BACKUP_DIR/sqldump.$DATE.sql ..." >> $LOGFILE;
mysqldump $DBNAME > $BACKUP_DIR/sqldump.$DATE.sql;
# Go back to original working directory.
echo -e "$LOGTIME \tAll done..." >> $LOGFILE;
echo "all done! ";

exit 0;

If you want to install this script follow the following instructions:

#This is for Oracle Enterprise Linux / RedHat EL distro`s
#Your environment might be slightly different.
cd /opt
mkdir ./scripts
cd scripts
vi ./
#insert the code above into the editor and save the lot using ':wq'
#alter the top of the script to match your environment.
chmod +x ./
#next create a symbolic link to the cron.daily, this might be different in your linux distro (see manual pages on your distro using 'man cron').
ln -s /opt/scripts/ /etc/cron.daily/backup
#monitor the /var/log/backup.log for details

Happy backing up ūüôā

(Dont forget to clean the backup dir on a regular basis if you dont have the luxury of an deduping storage)

network issues with Dell Broadcom interfaces?

Experiencing “Copper Link Down” messages with increased network load on Dell R and M Series servers?

Then you might want to look into this thread.

There is a known issue with the bnx2 driver used on the Linux platform that might cause the network card to become inactive. The problem is caused by the drivers MSI (Message Signaled Interface) option.

The two suggested solutions to this problem are;

1. Disable the msi option in the modprobe.conf file by adding the following rule;
options bnx2 disable_msi=1 (Recommended)

2. Load the latest dell driver that disables the msi-x option in the driver itself.

Please read these threads carefully before you decide this problem is the one you might be experiencing.

How to detect the problem on OracleVM / OEL.

1. Make sure the Link-led is lid on the back op the physical machine.
2. Run the ethtool eth# -t to view its current state
3. Make sure the ethtool reports a Link-Down

Applying the fix use the following steps;

1. Logon to the OracleVM Dom0 / OEL / Other Linux box.
2. vi /etc/modprobe.conf
3. Add the following line below alias eth0 bnx2
options bnx2 disable_msi=1
4. Save and quit vi :sq
5. Reinit the module using the following command.
modprobe bnx2
6. Verify the setting using the following command.
modinfo bnx2
The following rule should be listed.
parm: disable_msi:Disable Message Signaled Interrupt (MSI) (int)

Hope this fix resolves the problem for you!


RHEL5 init script for tomcat catalina

I have written an init script for Tomcat Catalina running in RHEL version 5. I have tested this script using Oracle Enterprise Linux 5.5 Carthage. The script should comply to the init standards defined for RedHat Enterprise Linux using the INIT Functions lib.

The script also alows the use of chkconfig eventhough you might want to alter the used priorities (56 10)

# "$Id: catalina ,v 1.0 2010/08/10 Chris_g Exp $"
#   Startup/shutdown script for tomcat(Catalina) Application server.
#   Linux chkconfig stuff:
#   chkconfig: 2345 56 10
#   description: Startup/shutdown script for the tomcat application server.

# Source function library.
. /etc/init.d/functions

# Define where the script is located.
CATALINA_BIN='/u01/tomcat/bin/ 1> /dev/null';

# Find the catalina process using ps / awk.
# The match function will return 0 when no match is found with the string "java".
# Position $9 should contain the path to the Java executable used by catalina.
PROC=`ps -efc | grep apache.catalina | awk 'BEGIN { FS=" "}; { if( match($9, "java") != 0 ) print $9;}'`

# Replace a potential empty string with a fake process so the RH daemon functions are able to parse
# it properly
if [[ "$PROC" == '' ]]; then

# Define the application name that is listed in the daemonize step.
PROG='Tomcat JVM';


start () {
        echo -n $"Starting $PROG: "

        # start daemon
        daemon $CATALINA_BIN start
        [ $RETVAL = 0 ] && touch $LOCK
        return $RETVAL

stop () {
        # stop daemon
        echo -n $"Stopping $PROG: "
        killproc $PROC
        [ $RETVAL = 0 ] && rm -f $LOCK

restart() {

case $1 in
                status $PROC

        echo $"Usage: $prog {start|stop|restart|status}"
        exit 3

exit $RETVAL

1. Touch a new tomcat file in your init directory.
>touch /etc/init.d/tomcat
2. Copy paste the code above into this file using vi
vi /etc/init.d/tomcat
(putty users)
press the insert button (this should put vi in insert mode)
Alter the tomcat path and copy the altered code to your clipboard and paste it into putty using a richt mouse click.
press esc (this should get you out of insert mode)
next press ” shift + : “, “w”, “enter” (this should save the file)
3. If was able to start tomcat (all vars/java configured) then now the tomcat script should be able to handle the startup.
4. If catalina was allready running, try;

     service tomcat status
     This should allready give a result equal to;
¬†¬†¬†¬† java (pid 14389) is running…

5. Add tomcat to the chkconfig for automatic startup
¬†¬†¬†¬† chkconfig –level 2345 tomcat on

Hope this helps ūüėČ

OracleVM & Oracle licensing….

Be aware of licensing, ‘soft’ partitioned virtualized guests with Oracle products installed are a financial RISK!

OracleVM supports ‘Hard’ partitioning.

In essence the OracleVM product is equal to any ‘soft’ partitioning solution. This is because in essence the Oracle (Xen) Hypervisor will also use¬†all of the resources in the¬†pool to spread the workload as efficiently as possible (para virtualized). In this scenario the licensing model will also require you to license all the available CPUs on the fysical box.

There¬†is a supported method to circumvent this. If you configure the domain¬†to map its¬†virtual¬†CPUs to Fysical CPUs, this setup is accepted by Oracle as ‘Hard’ partitioning. A special configuration entry needs to be set to the vm.cfg of each virtual machine¬†running¬†an Oracle Database as described in this Oracle Document.

Remember to set this configuration rule!
Else Oracle Licensing will identify your cool OracleVM infrastructure as just another Soft partitioned VM solution that requires¬†you to license each fysical CPU available to the virtual platform¬†ūüėČ

Additional reading :

-Rgrds, version 0.9.7

Previous version and detaild information

Application Goal:
Check disk IO using a simple perl script and possibly the counters allready available in the linux /proc/ directory. The program must be able to run under Nagios and should return a ‘Nagios’ correct syntax to the prompt. This way the plugin should be usable for Linux users to monitor their Disk IO within Nagios. The program should also report back performance information in the ‘Nagios’ compatible syntax so that graphing is available in the ‘Nagios’ / Cacti / Centreon add-ons.

Fixed lacking devision in validated summed results
Added sprintf functions rounding the validated numbers with 2 dimentions
Fixed some declaration problems
Added -debug switch to enable the debugging options
Coded arround the used math::Complex functions and removed the module
Improved the debugging output (readability)
Small fixes in de syntax

1. Copy the code below to your clipboard (ctr+c or the copy-button inside the code field)
2. Logon to the linuxbox with the nagios or nrpe client.
3. browse to the plugin-dir usually cd /usr/local/nagios/libexec/
4. Create a new file vi ./
5. Press insert and paste the code inside (when using putty paste is done with a rightmouse click)
6. save the file (esc > : > rq > enter, when using vi)
7. give the file execute rights using chmod +x ./check_iostat
8. make nagios the owner chown nagios:nagios ./check_iostat
9. Test it using updatedb& ./check_iostat -d sd -dbu -dbuw 70 -dbuc 88 -kbs -kbsw 10000 -kbsc 50000 -p

Next configure a nagios command or use nrpe and have fun ūüôā

# Written by Chris Gralike @ AMIS.
# Perl based check command to fetch and report the
# TPS (transactions per second) and IO wait times.
# Plugin uses iostat for opperation.
# Verion 0.9.7
# Changes post 0.9.7 >> 28-05-2010
# Line 298...303 Prevent devision by zerro else exit because no data was collected  - Bug reported by Epiq.
# Line 380       Correction of a type that prevented pref data of r/s w/s from being printed. - Bug reported by Epiq.
# Line 40        Added dm as possible device input used by the linux LVM. - Suggested by Epiq.
# Line 269       Extended the device if/pragmatch validation to match more devices - Added by Jean Ventura.
use Switch;
use warnings;

   $debug,	# Print debugging information.
   $DevType,	# Used to match a certain devicetype from the resulting IOstat rows.
   $IOBIN,	# Is used to store a path to the iostat binairy for execution.
   $Samples,	# Used to store the initial Samples returned by iostat.
   @SampleRows, # Used to store the rows generated by the splitted samples.
   $firstseen,  # Used to keep track of the found devices (IOstat might return a set of devices i.e sda, sdb, sdc etc.)
   $Items,      # Used in the foreach to store the row being parsed.
   @cols,       # Used to store the columns in a row after an split.
   $dev,	# Used to create a symbolic link to dynamicly create a var.
   $rws, $rws_warn, $rws_crit,
   $kbs, $kbs_warn, $kbs_crit,
   $awt, $awt_warn, $awt_crit,
   $svc, $svc_warn, $svc_crit,
   $devices, $itd,$v1,$v2,$v3,
   $dbu, $dbu_warn, $dbu_crit

# Preparing to collect the dangerious user input.
# Here is a list of known device types. Please add any device you would like to monitor..
$numArgs = $#ARGV + 1;
$critical_global = 0;
$warning_global = 0;

if($numArgs gt '0'){
	# Process our command line arguments and do some basic testing.
	# Could be make human save in the future.
	switch ($ARGV[$i]) {
		# Enable debugging.
		case '-debug'{
				$debug = 1;
		# Handle device type
		case '-d'    {
		 		if( (index($devtypes, $val)) gt '-1'){
					print "Ivalid Disktype found. Typo?\n"; exit 1;
		# Do we need to check rqm?
		case '-rqm'  { $rqm='1'; }
		# What is the warning treshold?
		case '-rqmw' {
				# Is the value nummeric?
					$rqm_warn= int $val;
				# Possible type?
					print "Non Numeric value used in rqmw, typo? \n"; exit 1;
		case '-rqmc' {
                                # Is the value nummeric?
                                        $rqm_crit= int $val;
                                # Possible type?
                                        print "Non Numeric value used in rqmc, typo? \n"; exit 1;
		# Do we need to check rws?
		case '-rws'  { $rws='1'; }
		case '-rwsw' {
                                # Is the value nummeric?
                                        $rws_warn= int $val;
                                # Possible type?
                                        print "Non Numeric value used in rwsw, typo? \n"; exit 1;
		case '-rwsc' {
                                # Is the value nummeric?
                                        $rws_crit= int $val;
                                # Possible type?
                                        print "Non Numeric value used in rwsc, typo? \n"; exit 1;
		# Do we need to check kbs?
		case '-kbs'  { $kbs='1'; }
		case '-kbsw' {
                                # Is the value nummeric?
                                        $kbs_warn= int $val;
                                # Possible type?
                                        print "Non Numeric value used in kbsw, typo? \n"; exit 1;
		case '-kbsc' {
                                # Is the value nummeric?
                                        $kbs_crit= int $val;
                                # Possible type?
                                        print "Non Numeric value used in kbsc, typo? \n"; exit 1;
		# Do we need to check awt?
		case '-awt'  { $awt='1'; }
		case '-awtw' {
                                # Is the value nummeric?
                                        $awt_warn= int $val;
                                # Possible type?
                                        print "Non Numeric value used in awtw, typo? \n"; exit 1;
		case '-awtc' {
                                # Is the value nummeric?
                                        $awt_crit= int $val;
                                # Possible type?
                                        print "Non Numeric value used in awtc, typo? \n"; exit 1;
		# Do we need to check svc?
		case '-svc'  { $svc='1'; }
		case '-svcw' {
                                # Is the value nummeric?
                                        $svc_warn= int $val;
                                # Possible type?
                                        print "Non Numeric value used in svcw, typo? \n"; exit 1;
		case '-svcc' {
                                # Is the value nummeric?
                                        $svc_crit= int $val;
                                # Possible type?
                                        print "Non Numeric value used in svcc, typo? \n"; exit 1;
		# Do we need to check dbu?
		case '-dbu'  { $dbu='1'; }
		case '-dbuw' {
                                # Is the value nummeric?
                                        $dbu_warn= int $val;
                                # Possible type?
                                        print "Non Numeric value used in dbuw, typo? \n"; exit 1;
		case '-dbuc' {
                                # Is the value nummeric?
                                        $dbu_crit= int $val;
                                # Possible type?
                                        print "Non Numeric value used in dbuc, typo? \n"; exit 1;
		# performance data. Might make the string human unreadable.. ow well, no loss there <img src="" alt=":)" class="wp-smiley">
		case '-p'    { $prf='1'; }
		# Print full messages per device overview.
		#case '-m'    { $fms='1'; }
		# Most used help switches.
		case '--help'{ USAGE(); }
		case '-h'    { USAGE(); }
	# Check if the basic requirements are met.
	if(!($DevType) ||  !(($rqm || $rws || $kbs || $awt || $svc || $dbu))){
		print "Minimal requiremens, device and checktype are not met\n";
	# No input was given. Show the Usage();

# Locate the IOBin binairy needed to fetch the stats.
chomp($IOBIN=`which iostat`);

if( !(-f $IOBIN) || !(-x $IOBIN)){
	print "A working iostat command is needed for this script to work \n";
	print "Also make sure the sysstat service is running! /etc/init.d/sysstat \n";
	exit 1;

	# IF IOStat is found, lets collect some data.
	chomp($Samples=`$IOBIN -d -x -k 1 5 | grep $DevType`);
	print "Please select a valid devicetype \n";
	exit 1;

# Break the samples up in lines so we can evaluate them.
# The first set of samples are avg. values counted from boot.
# We need to discard them and collect the remaining samples.
@SampleRows=split(/\n/, $Samples);

# Firstseen is used to track de device names and to skip the first itteration of iostat that contains
# avg stats counted from system boot time, stats we cant use here sadly <img src="" alt=":)" class="wp-smiley">

# Print Debugging information
	    print "### Data collected ###\n";
	    print "dev|rrqm|wrqm|r/s|w/s|rKB/s|wKB/s|rq-sz|qu-sz|await|svctm|util%|\n";

foreach $Items (@SampleRows){
	 # Break the latter up in usable columns.
	 # We only want a certain device type. So lets match what we know.
	 # Disks usualy have a prefix for example (scsi = sd) its set using
	 # the DevType var.
         if($cols[0]=~m/$DevType-[0-9]$/ || $cols[0]=~m/$DevType[a-z]$/ || $cols[0]=~m/$DevType[a-z][0-9]$/){

		if((rindex $firstseen, $dev) gt '-1'){
			#Declare new $$
			#my @$dev;
			# Store the collected data in the correct (dynamic) vars.
			$$dev[1]+=$cols[1];	# rrqm/s   Read Requests Merged per Second.
			$$dev[2]+=$cols[2];	# wrqm/s   Write Requests Merged per Second.
			$$dev[3]+=$cols[3];	# r/s      Number of read requests issued per Second
			$$dev[4]+=$cols[4];	# w/s      Number of write requests issued per Second
			$$dev[5]+=$cols[5];	# rKB/s    Number of Kilobytes read per Second.
			$$dev[6]+=$cols[6];	# wKB/s    Number of Kilobytes written per Second.
			$$dev[7]+=$cols[7];	# Avgrq-sz Avarage size (in sectors) of the issued requests.
			$$dev[8]+=$cols[8];	# Avgqu-sz Avarage Queue length of the requests issued.
			$$dev[9]+=$cols[9];	# Await	  Avarage wait time in ms for IO requests to be served.
			$$dev[10]+=$cols[10];	# svctm    Avarage service time in ms for IO requests that where issued.
			$$dev[11]+=$cols[11];   # %util    Precentage of CPU time during IO requests (bandwidth util), saturation at 90~100%
			$CT++; # Add a new itteration to the count
			# Print some debugging vars if requested. to show the data is collected.
				    print "$dev|$cols[1]|$cols[2]|$cols[3]|$cols[4]|$cols[5]|$cols[6]|$cols[7]|$cols[8]|$cols[9]|$cols[10]|$cols[11]|\n";

# Prevent $itd (itterations / disk) from becomming zerro and exit when no devices are found.
# on line 299.
if($Devices > 0){
	$itd = ($CT / $Devices);
	print "No performance data was captured. Please check if the device name is correct\n"; exit 1;

# Print debugging information
	print "###Devices Counted###\n";
	print "Number of devices : $Devices\n";
	print "Number of itterations per device : $itd\n";
	print "Total Number of Itterations : $CT\n";
# Lets collect the device information from the firstseen var
# and start processing it for some perf check/data
# Lets also recycle some previously used vars for this.
foreach $Items (@cols){
	# Items now contains the devicenames needed to access the data again.
	# We now need to check them against some basic tresholds
	# Print a nice table with the calculated values when we are in debug.

  	# Print debugging information
		   print "### Counted Values ###\n";
		   print "$Items|$$Items[1]|$$Items[2]|$$Items[3]|$$Items[4]|$$Items[5]|$$Items[6]|$$Items[7]|$$Items[8]|$$Items[9]|$$Items[10]|$$Items[11]|\n";

	#What do we want to check against a treshold?
	#First check the selection if any.
	if($rqm || $rws || $kbs || $awt || $svc || $dbu){

		#Set the counts to zerro
		# Devide
		$v1 = sprintf($round, ($$Items[1] / $itd));
        $v2 = sprintf($round, ($$Items[2] / $itd));
		$v3 = sprintf($round, ($$Items[3] / $itd));
        $v4 = sprintf($round, ($$Items[4] / $itd));
		$v5 = sprintf($round, ($$Items[5] / $itd));
        $v6 = sprintf($round, ($$Items[6] / $itd));
		$v7 = sprintf($round, ($$Items[7] / $itd));
        $v8 = sprintf($round, ($$Items[8] / $itd));
		$v9 = sprintf($round, ($$Items[9] / $itd));
        $v10 = sprintf($round, ($$Items[10] / $itd));
        $v11 = sprintf($round, ($$Items[11] / $itd));

		# Requests Merged per second.
			# Critical
			if(($v1 >= $rqm_crit) || ($v2 >= $rqm_crit)){
			# Warning?
			}elsif(($v1 >= $rqm_warn) || ($v2 >= $rqm_warn)){
			# Ok
			# Add the counters to the performance vars
			$perf.="$Items-rrqm/s=$v1; $Items-wrqm/s=$v2;";
		# Reads / Writes per second.
			if(($v3 >= $rws_crit) || ($v4 >= $rws_crit)){
             		# Warning?
               	 	}elsif(($v3 >= $rws_warn) || ($v4 >= $rws_warn)){
                	# Ok
			# Add the counters to the performance var.
			$perf.="$Items-r/s=$v3; $Items-w/s=$v4; ";
		# KB Read/Writes per second.
			if(($v5 >= $kbs_crit) || ($v6 >= $kbs_crit)){
	                # Warning?
       	         	}elsif(($v5 >= $kbs_warn) || ($v6 >= $kbs_warn)){
                	# Ok
			$perf.="$Items-rKB/s=$v5; $Items-wKB/s=$v6; ";
		# Avarage wait time
			if(($v9 >= $awt_crit)){
                	# Warning?
                	}elsif(($v9 >= $awt_warn)){
                	# Ok
			$perf.="$Items-await=$v9; ";
		# Avarage service time issuing time
			if($v10 >= $svc_crit){
                	# Warning?
                	}elsif($v10 >= $svc_warn){
                	# Ok
			$perf.="$Items-svctm=$v10; "
		# Disk bandwidth Utilization
			if($v11 >= $dbu_crit){
              	  	# Warning?
               	 	}elsif($v11 >= $dbu_warn){
                	# Ok
			$perf.="$Items-util=$v11%; ";
		print "At least select a value to measure..\n";
		exit 1;
	# Print Debugging information about the validated values.
	if($debug){ print "### validated Devisions ###\n";
                    print "$Items|$v1|$v2|$v3|$v4|$v5|$v6|$v7|$v8|$v9|$v10|$v11|\n";

	# Create a messages var.
	$mgs.="$Items=O:$ok_state,W:$warning_state,C:$critical_state; ";

	# Track the global state (1 crit 1 warn)
	if(($critical_state gt '0') || ( $critical_global gt '0')){
	if(($warning_state gt '0') || ( $warning_global gt '0')){

# Compose a nice nagios output.
if($critical_global >= '1'){
	print "CRITICAL:";
}elsif($warning_global >= '1'){
	print "WARNING:";
	print "OK:";
# Print the remainder, the most important data was processed.
print $mgs; if($prf){ print "|$perf"; } print "\n";
exit $exit;

sub USAGE{
	print "
                Usage : $0 -d [Dev] [options]

		-p Print performance data about the measured samples.

		-d {grep string used on IOstat}
                 sd     #All scsi devices.
                 hd     #All Cdrom devices.
		 sda	#Only device sda

                [Available Measurement Options]
                -rqm -rqmw val -rqmc val        # read/write merged             [#]
                -rws -rwsw val -rwsc val        # read/write per second.        [s]
                -kbs -kbsw val -kbsc val        # KBs read/written per second.  [s]
                -awt -awtw val -awtc val        # Avarage IO wait time.         [ms]
                -svc -svcw val -svcc val        # Avarage service IO wait time. [s]
                -dbu -dbuw val -dbuc val        # Disk utilization              [%]\n";
        exit 1;

Linux Filesystems what to know?

Here are some things that might help you out ūüôā
There is much more to know about linux filessytems, but this might be a good start ūüôā

hope this helps ūüôā

# Some commands, they might come in handy ūüėČ

df		        report file system disk space usage
df -h		        use the -h switch to display MBs instead of blocks.
df -i   	        show the free Inodes per file system
du		        estimate file space usage
du {file} -h	        use the -h switch to make the stats human readable.
tune2fs		adjust tunable filesystem parameters on ext2/3 filesystems.
tune2fs -l 	        show the actual filesystem superblock data {dev} should contain a SB.
e2label		Change the label on an ext2/3 filesystem
mkfs		        Build a linux file system
mke2fs		Build a Ext2 file system
mkisofs		Build a iso file system
mkudffs		Build a UDF file system
mkswap		Build a Swap file system
mkdosfs		Build a FAT File system
mkfs.vfat	        --
mkfs.msdos	        --
mount		Mount a linux filesystem
umount		Unmount a linux filesystem
swapon		Enable/disable devices and files for paging and swapping
swapoff		--
fsck		        Check a linux filesystem. (USE WITH CAUTION and RTFM FIRST!)
partprobe		inform the OS of partition table changes or list partitions on a device
parted		a partition manipulation program. A very strong but dangerious tool.

Linux devices
Next to these commands there is more to know about the linux filesystem. Most important aspect to know is how the fysical disks are made accessible. This is done by a process called mounting. When a linux OS boots it will probe for fysical attached disks and will create devices for each detected disk in the /dev/ directory. In some cases a device module (driver) is needed to be loaded into the kernel in order for it to access and probe the disk.

Depending on the device type a file (device) will be created in the /dev/ directory with a very specifik name. Here are some examples you might encounter in the /dev/ directory.

First MFM, RLL and IDE hard disk/CD-ROM interface
0 = /dev/hda		Master: whole disk (or CD-ROM)
64 = /dev/hdb		Slave: whole disk (or CD-ROM)

SCSI disk devices (0-15)
0 = /dev/sda		First SCSI disk whole disk
16 = /dev/sdb		Second SCSI disk whole disk
32 = /dev/sdc		Third SCSI disk whole disk

IBM iSeries virtual disk
0 = /dev/iseries/vda	First virtual disk, whole disk
8 = /dev/iseries/vdb	Second virtual disk, whole disk

For a full list check this site :)

Linux Logical Volume management (LVM)
Linux also supports software raid. I wont be paying to much attention here because I allways advice people to use hardware raid instead. When you encounter “Volgroup##” inside the fstab you know an LVM group has been created. The LVM can be manipulated and verified using one of the following commands.

lvchange     lvdisplay    lvmchange    lvmsadc      lvreduce     lvresize
lvconvert    lvextend     lvmdiskscan  lvmsar       lvremove     lvs
lvcreate     lvm          lvmdump      lvm.static   lvrename     lvscan

please consult the manual for more details about these commands.

linux creating a filesystem and mounting
When a device is available in the devices directory you can actually start to use the device. One way of doing this is simply using the mount command stating, mount {device} {mountpoint}. But before doing this you need to decide what you want to do with the device. In most cases a filesystem will be created ontop of the device. For this task you can use the mkfs command or use parted to create partitions.

Please readup on the various filesystem types available. Commonly the Ext2 / Ext3 filesystems are used because they offer the best safety and manupilation options (ext3 doesnt support all the manipulation options ext2 supports). The following site is a good starting point when you are looking for more information on the subject.

Other options are mounting the disk without a filesystem in place a so called raw device, or use the device as swap space using swapon/off. Clustered filesystems are also an option but not described in this article.

Once you have decided how to use the disk, and the disk is available within linux (drivers etc) the next step would be making the disk available after boot. For this the fstab file is used. Simply add a new line with the correct parameters and the disk will be mounted at boot.

Some Important Files and their Locations.

/etc/fstab           Static Information about filesystems.  
/etc/mtab           Table of mounted filesystems
/etc/mtab~         Table of mounted filesystems lockfile
/etc/mtab.tmp     Temporary file
/etc/filesystems   A list of filesystems to try

Finaly, some tips while working with fylesystems.

TIP. Test the fstab file using the “mount -a” command before attempting a reboot. Best test is to unmount the disk prior to the mount -a command.

TIP. Also best practise is to modify disks, partitions, perform fsck`s in INIT 1. This will limit the ammount of running deamons dramaticly and will make your filesystem manipulation tasks much easier.

TIP. The mtab file will always list “devices” instead of “labels”. If you are wondering which device is used by a label try consulting the /etc/mtab.

TIP. In the /dev/ directory there might be a /disk/ directory. This directory will allow you to mount devices by the following attributes;

This directory might come in handy when you are not sure what device was created by that usb disk you just plugged in. using the by-path for instance will show you de bus that is used by the various available disks, or by label that will show what label mappings exsist.
Always use the “ls -lart” command here to get the full details.

TIP. Be very carefull using the fsck command, it is well capable of destroying data on your disk if using incorrectly. Always read the manual fist using the manpages (man fsck).

check_iostat / check_io for nagios Version 0.9.5

Oke here is the first working version of

NEW Version available HERE

Why this version?
Well to my big surprise I was not able to find any satisfying check plugin for diskio that didnt need all kinds of additional software or undocumented perl plugins. What i really wanted was a simple check plugin that would only require the default sysstat daemon allready present on allot of our systems (Oracle DB requirement).

Because no one seemed to have written such a plug-in I decided to write one myself. And here is the result.

How to get started?
Copy paste the source into a file within nagios/libexec.

The following needs to be on your Linux machine.
sysstat must be installed!
iostat must be available!
perl (base) should be installed!

What can you do?
1. Let us know on what distro you have tested this code! And or what changes you made to make it work.
2. Tell me if you spotted any improvements in the code.
3. Tell me if there are any bugs.

What more?
Questions? Different requirements? Improvements? Code cleanup?
Please let me know…

Tested with?

Enterprise Linux Enterprise Linux Server release 5.3 (Carthage)
Enterprise Linux Enterprise Linux Server release 5.2 (Carthage)
SUSE LINUX Enterprise Server 9 (i586)

the code is still a bit messy but functional. Keep an eye out here for updates. I will be cleaning up this code further.


Code below…
Read the rest of this entry

Phase one, Check IOStat for Nagios.

Full Working version can be found here



Thanks, Rgrds,