PostgreSQL parsing paths

I’ve been working on a project dealing with file paths inside our PostgreSQL databases and came across a situation where I wanted to parse out the file name from a path. As with everything code related, there are several ways to accomplish the task at hand.

Here are the three easiest methods I’ve came up with.

SELECT '/path/to/my/file.txt' AS str_path
  ,REGEXP_REPLACE('/path/to/my/file.txt', '^[^*?"<>|:]*/','')
  ,ARRAY_TO_STRING(REGEXP_MATCHES('/path/to/my/file.txt','([^/]+)$','g'),'')
  ,SPLIT_PART('/path/to/my/file.txt','/',ARRAY_UPPER(REGEXP_SPLIT_TO_ARRAY('/path/to/my/file.txt','\/'),1));

And now for a breakdown of each method.

REGEXP_REPLACE('/path/to/my/file.txt', '^[^*?"<>|:]*/','')

The first method is the most simple method (and fastest). It uses regex to find and replace everything but the last element in a path with empty space (‘’).

ARRAY_TO_STRING(REGEXP_MATCHES('/path/to/my/file.txt','([^/]+)$','g'),'')

The second method finds the last element (the reverse of the first method). The function REGEXP_MATCHES returns a PostgreSQL array so we use the ARRAY_TO_STRING function to convert the array to a string.

SPLIT_PART('/path/to/my/file.txt','/',ARRAY_UPPER(REGEXP_SPLIT_TO_ARRAY('/path/to/my/file.txt','\/'),1))

This third method is probably overkill but it may be useful if you can’t seem to get a regex expressions to work. The method uses REGEX_SPLIT_TO_ARRAY to split the string into an array. Then using the ARRAY_UPPER function we find out how many elements are in the array. This value is then passed to the SPLIT_PART function , telling it which element we want returned.

Keep in mind that with each of the methods above you can always replace the delimiter with your own search criteria to come up with fun and exciting ways to pull out that gem of information from a string!

Create Online KVM Backups

Running eCommerce sites, downtime is considered a bad deal… at the same time, not having backups is even worse. Here is a simple script that I’ve put together to execute an online backup (not a snapshot) of a Virtual Machine managed by KVM without having to shut down the VM.

Create a new file.

$vi snapshot_backup.sh

And copy and paste the following code.

#!/bin/bash
debug=1

function backup_snapshot {
  date=$1
  filename=$2
  if [ `qemu-img info $filename.qcow2 | grep  --count "file format: qcow2"` -eq 1 ] then
    echo "Backing up $filename"
    # create the snapshot
    if [ $debug -eq 1 ] then
      echo "Creating snapshot"
    fi
    qemu-img snapshot -c $date $filename.qcow2
    #copy the snapshot out
    if [ $debug -eq 1 ] then
      echo "Converting snapshot to standalone qcow2 file"
    fi
    qemu-img convert -c -f qcow2 -O qcow2 $filename.qcow2 $filename-$date.qcow2
    #delete the old snapshot
    if [ $debug -eq 1 ] then
      echo "Deleting snapshot"
    fi
    qemu-img snapshot -d $date $filename.qcow2
  else
    echo "Snapshot backups only support qcow2 files"
 fi
}
date=`date +%d%m%Y`
filename=`echo $1 | sed s/.qcow2//`
backup_snapshot $date $filename

Exit vi, saving the script.

Now make your script executable.

$chmod +x snapshot_backup.sh

To run the script pass it the name of your VM.

$./snapshot_backup.sh /path/to/your/vm/hostname.qcow2

From my experiance, the performance impact to the VM is fairly minimal.

Hope this helps.

Raspberry Pi Slideshow

Wanting to do something productive with my Raspberry Pi, I decided to at least get it showing me new art each day. As it turns out… its a little more challenging than I had originally expected. The main reason was resources on the Pi. Many image viewers, both command line and x windows based like to do some crazy things that tend to blow up the memory consumption on my Raspberry. As a result, the kernel will, in turn, enjoy killing the offending process. The following is how I overcame the challenges.

The Equipment:
Raspberry Pi running Raspbian “wheezy” on a 4GB SD Card
HDMI Monitor
An Internet connection

The Overview:
The idea is to get updated images from Deviantart nightly and display them via slide show over the course of the day.

The Steps:
With a fresh install of Raspbian I booted up the Pi. The initial wizard gives you a few options, here is what I did.
1. Expand the root partition to fill the SD Card
2. Changed the keyboard to the US layout
3. Changed the timezone to reflect where I live
4. Changed the boot into desktop to yes (meaning it will start the desktop after boot).
5. As a matter of security, I also updated the password for the pi user.

Reboot the Pi and you should find yourself looking at the desktop once you log in.

Add Auto Login:
You can skip this part if you don’t want to auto login, it wont affect the outcome unless you reboot your machine.
Making this as automated as possible, we need to set up the Pi to auto login the pi user. Here’s how we do that.

Edit /etc/inittab using vi. Of course vi is just my preferred text editor, feel free to use your own favorite. I’ve heard quite a few people like nano.

sudo vi /etc/inittab

Scroll down till you see the following line:

1:2345:respawn:/sbin/getty --noclear 38400 tty1

Comment it out by adding a pound sign (#) in front of it. Insert a new line and add the following.

1:2345:respawn:/bin/login -f pi tty1 </dev/tty1 >/dev/tty1 2>&1

Your file should now look something like this:

#1:2345:respawn:/sbin/getty --noclear 38400 tty1
1:2345:respawn:/bin/login -f pi tty1 </dev/tty1 >/dev/tty1 2>&1

NOTE: If your using a user different than ‘pi’ you will want to change the user, pi, to your user.

Close and save the file.

Go ahead and reboot your Pi just to make sure your changes have properly taken affect.

sudo shutdown -r now

Update and Install pqiv
Once the machine comes back up, it should automatically boot you into LXDE (the default desktop environment). Go ahead and open a terminal window and update the apt-get repository.

sudo apt-get update

Normally we would issue a simple apt-get install pqiv to install pqiv; however, due to issues with version in the raspbian repository we will need to download, fix, compile, and install pqiv manually. Don’t forget to remove pqiv if you’ve already installed it at some point.

sudo apt-get remove pqiv

Install git and the dependency gtk2 library for pqiv.

sudo apt-get install git libgtk2.0-dev

We have what we need to build the application, now we need to download the source.

cd
git clone https://github.com/phillipberndt/pqiv.git -b 0.12

Now that you’ve downloaded the pqiv source, you will notice a new directory in your home directory called pqiv. Go into this directory and run ./configure to validate all preconditions are met and create a platform specific make file.

cd pqiv
./configure

Now we need to fix the source code by replacing the gchar option; with gint option; in the main() function in the pqiv.c file. The line we are looking for is around 2233.

/*gchar option;*/
gint option;

Save and exit vi. Now you’ve fixed the bug, we will run make and install the application.

sudo make all install

You now have the fixed version of pqiv running on your Pi.

Get the slide show images:
Now we need to create the process to download the images from Deviant art. To do this, first create a directory in your home directory. Open a terminal session and type in the following commands.

cd
mkdir images
mkdir scripts
cd scripts

Now we need to create the script to get the images from DeviantArt. Create a new file in the scripts directory.

vi ~/scripts/get_images.sh

Inside the script copy and paste the following code.

NOTE: Updated wget line to adapt to the change in RSS format from Deviantart.

#!/bin/bash

cd /home/pi/images

rm *.jpg *.png

# go get the files
#landscape files
wget -q -O- "http://backend.deviantart.com/rss.xml?q=boost%3Apopular+in%3Adigitalart%2Fpaintings%2Flandscapes+max_age%3A72h&type=deviation" | grep -o '<media:content url="[^"]*' | grep -o '[^"]*$' | xargs wget -c

FILES=/home/pi/images/*
count=0
one=1

for f in $FILES
  do
    file -b $f
    echo "Checking file number $count"
    count=$(($count + $one))
    if [ "$(file $f|grep JPEG)" ]; then
      mv ${f} $RANDOM.jpg
    elif [ "$(file $f|grep PNG)" ]; then
      mv ${f} $RANDOM.png
    elif [ "$(file $f|grep ASCII)" ]; then
      echo ”Skip Script file”
    else
      echo "unknown file type $f"
    fi
  done
Once you've added the script, save your file and make it executable.
chmod +x ~/scripts/get_images.sh

Just to be sure your script is working execute it via the command line.

cd ~/scripts
./get_images.sh

So… whats this script do you might ask? For starters, using wget, it reaches out and pulls down images from DeviantArt via their RSS feeds. Using grep and sed we save the resulting downloaded file to the images directory. The second part of the script looks at all the files downloaded (some of them end up not being images) and gives them random file names. These random file names are what make the slide show seem a little more “random”.

But we want this pull to be a automated. To do this we add the script to cron. To edit cron:

crontab -e

And then add the following line at the end of the file.

00 01 * * * /home/pi/scripts/get_images.sh > /home/pi/get_images.log 2>&1

The line above kicks off your script every night at 1:00 am and outputs both output and error to a log file in the home directory of pi. (this is really only to help with troubleshooting if needed).

Slide show Image Swapping
Next we need to create a set of scripts to refresh the slide show file and make sure the slide show continues to run.

First up is a really simple script to continually refresh the slide show image. Create a new script file in your scripts directory.

cd ~/scripts
vi update_slideshow_image.sh

Copy and paste this script into your new file.

#!/bin/bash

cd /home/pi/images
while true;
  do for i in *;
    do cp $i /home/pi/slideshow.jpg;
      echo $i;
      sleep 30;
    done;
  done

Save your file and make it executable.

chmod +x update_slideshow_images.sh

Here is a quick outline of what the above script does.

It first changes its current directory to the images directory. Once there, it goes into an infinite loop. Once inside the loop it gets a list of files from your images directory. It then copies the first file to your home directory calling the file slideshow.jpg. The script then waits 30 seconds and then copies the second file, overwriting the existing slideshow.jpg with this new one. The script will do this for each file until it goes through all of them. Then it starts from the begging and does it all over again. At 1:00 am the get_images script will download a new set of images and because the update_slideshow_image get a new file list each time it loops, these new files will get added to the list to be displayed. This may not make much sense now, but it will after in a moment.

Using pqiv to display images:
Now we need to create the script to display the images.

cd ~/scripts
vi start_slideshow.sh

Copy and past this script into your new file.

#!/bin/bash

# Lets start and restart the slideshow if needed
until /usr/bin/pqiv -i -f -s -w /home/pi/slideshow.jpg; do
  echo "Slideshow crashed with exit code $?. Restarting..." >&2
  sleep 2
done

Save your script and make it executable.

chmod +x start_slideshow.sh

This script is really quite simple. Most of the actual slide show work is done by pqiv. This script’s only duty is to kick off pqiv. If the program crashes the script will echo the reason it crashed and then wait a few seconds before restarting the slide show. Why do I do this you might ask? Memory resources on a Raspberry Pi are limited and image viewing software isn’t all that great at being memory friendly, especially when trying to load larger files, scale them, and then display them. Do that over a hundred times and you will quickly get killed by the kernel.

As a side note, I tried several other image viewing programs like fbi, fim, and feh. While they worked, they each had some small issues and more importantly, they were not fond of refreshing the image when the underlying file changed.

Autostart the slide show:
To have our slide show kick off automaticly once the Pi reboots. To do this we need to add two .desktop files to autostart. One file will run our update_slideshow_image script that the other will run the start_slideshow script.

Here is how you create the first file.

cd /etc/xdg/autostart
sudo vi slideshow_image_changer.desktop

Inside this file add the following.

[Desktop Entry]
Type=Application
Name=Slideshow Image Changer
Comment=Slideshow Image Changer
Exec=/home/pi/scripts/update_slideshow_image.sh
Terminal=true

Save this file and create the second file.

sudo vi slideshow_start.desktop

Add the following to this new desktop file.

[Desktop Entry]
Type=Application
Name=Slideshow Image Changer
Comment=Slideshow Image Changer
Exec=/home/pi/scripts/start_slideshow.sh
Terminal=true

Save and close this file.

Prevent the Raspberry from going to sleep:
We are almost done… one thing that drove me nuts for a little while was how the Raspberry would occasionally turn off the monitor. I couldn’t really narrow down what I did to fix the issue. I updated the following config settings and they seem to work as expected.

Update the kbd config file.

sudo vi /etc/kbd/config

Scroll down till you see the BLANK_TIME setting and change it to 0.

# screen blanking timeout. monitor remains on, but the screen is cleared to
# range: 0-60 min (0==never) kernels I've looked at default to 10 minutes.
# (see linux/drivers/char/console.c)
#BLANK_TIME=30
BLANK_TIME=0

Scroll down a little more till you see the POWERDOWN_TIME setting and change it to 0

# Powerdown time. The console will go to DPMS Off mode POWERDOWN_TIME
# minutes _after_ blanking. (POWERDOWN_TIME + BLANK_TIME after the last input)
#POWERDOWN_TIME=30
POWERDOWN_TIME=0

Save and close the config file.

Next I ended updating the lightdm.conf file.

sudo vi /etc/lightdm/lightdm.conf

Scroll down till you see the [SeatDefault] section and add a line towards the end of it.

xserver-command=X -s 0 dpms

My screen no longer goes blank and I have the pleasure of having a dynamic slide show all day.

Reboot your Raspberry Pi. Provided everything goes as planned, your slide show should start shortly after booting into the LXDE desktop… congratulations!

Using Perl to communicate with Single Line LED Sign

SVV-ML-80X7-RG

SVV-ML-80X7-RG

I recently inherited a single line LED sign made by SuperViewVision, Model Number SVV-ML-80X7-RG, and my first thought was “Great! I can stream cool stuff to the sign like tweets”. To my dismay the sign came with windows only software and little documentation. On top of that there was no easy method to programmaticly update the display. Each change to the message had to be done manually. I search for several days looking for protocol documentation. In the product description there is a blurb about protocol documentation available upon request. So, I attempted to communicate with the vendor asking for documentation. The vendor’s response was less than helpful. Evidently they sell the sign but allow resellers to re-flash the sign with their own protocols so they wanted to know the date I bought the sign and who I bought it from. This was information  I wasn’t privy to due to my method of acquiring the sign. After searching I started to get the feeling the sign was really old or its simply not used as often as other signs using some of the more main stream LED sign protocols because I couldn’t find anything!

The stage was set, the challenge clear. I was going to map out the protocol for the sign and use a perl script to communicate with it.

To understand how the sign communicated I used a windows serial port sniffer and started logging commands sent to the sign. As it turns out the protocol is a two (or more) step process. A wakeup signal followed by the command(s). Something like this:

PORT_WRITE -> ~128~
PORT_WRITE -> f01A\Y1\Z4\a\sHello World\r\r\r

To help you out, I’ve built a small perl script to help. Click here to download the perl script. I suggest renaming it from .txt to .pl If your running on a linux machine (like me) you will have to make the script executable before trying to run it.

Here is the usage syntax.

usage: perl post_to_sign.pl --port=/dev/ttyS0 --signid='~128~' --info 'info message' --alert 'alert message' --update 'update message' --setDTM
       --port   '/dev/ttyS0'     Define the port the sign is connected to. Defaults to /dev/ttyS0
       --signid '~128~'          Define the sign ID. Defaults to ~128~
       --info   'info message'   Post the string using the default format (bright green default size)
       --alert  'alert message'  Post the string using the alert format (flashing ALERT and scrolling in bright red)
       --update 'update message' Post string using the update format (flashing UPDATE and scrolling in bright yellow)
       --showDTM                 Will add the current date time to the message displayed
       --setDTM                  Updates the sign with the current date and time

The --info, --alert, and --update are all pre configured displays but you can pass any kind of slash command to send any combination of cool things. Here is an example of passing both an --alert and --info with some embedded embellishments.

perl post_to_sign.pl --port=/dev/ttyS0 --signid='~128~' --info 'Conns db1:\c12\h db2:\c12\h \rC\Y1\h\sServers:\c48\h Up:\c39\h Down:\b2\h \rC\Y1\h\scan you can a can as canners can a can' --alert '\djavtableau\b is NOT responding to ping!'

Now that I had a simple command line interface I built a script (not documented here) to pull my environment health and statistics every few minutes and update the sign.

Something else about the script, I havn’t tested it on a windows machine but I bet if you update the USE statement to point to the Win32::SerialPort module it should work.

That’s about it… each of the modes and other effects are further documented inside the perl file.
Enjoy!

[FIXED] Android DNS not working with WIFI

So I finally upgraded my wireless access point from a G device to a new shiny N device. The Cisco Linksys E1200 to be specific. When I did this change I had several of my Android based devices unable to brows or pull up any type of internet based services (news, stocks, facebook, oh my!). After several attempts to tweak my wireless settings, at one point I event completely turned off security to no avail. I then noticed that I was able to pull up websites via IP but not domain name. Ah ha! DNS. So evidently DNS via wifi is a semi known issue with routers that are not configured to allow some sort of open DNS and Fully Qualified Domain Names (FQDN). To be honest I only vaguely understood what the problem was… only to the point were I knew that my router simply wasn’t going to work regardless what I did to it (besides replace it with a new one).

That left the Android devices to be tweaked. Despite the router passing the DNS servers to the device as part of the IP settings when a connection is established it wont use DNS servers (again related to the FQDN and some other Router magic). So what I ended up doing ultimately is downloading and installing Set DNS. However what do you do if you cant even open Google Play (Marketplace) if you cant resolve anything? Here are the steps that I took to get to the point of being able to connect and brows.

Its worth noting that you must have Super User (su) rights on the devices (in other words you must have root access).

Method 1

Update the /system/etc/resolve.conf

If you already have resolv.conf you simply need to add your favorite DNS servers via command line like this..

# su
# mount -o remount, rw /system
# echo "nameserver 8.8.8.8" >> /system/etc/resolv.conf
# echo "nameserver 8.8.4.4" >> /system/etc/resolv.conf

If there is not a resolv.conf in your /system/etc then you need to create one.

# su
# mount -o remount, rw /system
# echo "nameserver 8.8.8.8" > /system/etc/resolv.conf
# echo "nameserver 8.8.4.4" > /system/etc/resolv.conf

Now you need to set the permissions on the resolve.conf to rw-r-r-

# chmod 4755 /system/etc/resolv.conf

Reboot your phone and try to connect to your favorite wifi access point and brows the web.

Method 2

Update the /system/build.prop

Before you can update the build.prop file you will have to make the filesystem writable. Just like in method 1 fire up a command line interface and remount the /system filesystem.

# su
# mount -o remount, rw /system

Using your favorite text editor edit the file.

# vi /system/build.prop

Once you are inside the file editing it, here is the section I added at the bottom of the file.

# Added by Richard
# Google DNS Tweak
net.rmnet0.dns1=8.8.8.8
net.rmnet0.dns2=8.8.4.4
net.dns1=8.8.8.8
net.dns2=8.8.4.4

Save the file and reboot your device. Once its up try to pull up your favorite site via the browser or check out the Google Play store. If your updates took place properly you might even see an increase in performance.

Its working? Great! Now go download Set DNS. It makes updating DNS settings so much easier.

My Codeing Standards

In computer programming, a naming convention is a set of rules for choosing the character sequence to be used for identifiers which denote variables, types and functions etc. in source code and documentation.

Reasons for using a naming convention

•to reduce the effort needed to read and understand source code
•to enhance source code appearance (for example, by disallowing overly long names or abbreviations)

Here are some of the benefits obtained by adopting a common naming convention:

•to provide additional information (i.e., metadata) about the use to which an identifier is put
•to help formalize expectations and promote consistency within a development team
•to enable the use of automated refactoring or search and replace tools with minimal potential for error
•to enhance clarity in cases of potential ambiguity
•to enhance the aesthetic and professional appearance of work product (for example, by disallowing overly long names, comical or “cute” names, or abbreviations)
•to help avoid “naming collisions” that might occur when the work product of different organizations is combined
•to provide meaningful data to be used in project handovers which require submission of program source code and all relevant documentation and to provide better understanding in case of code reuse after a long interval of time

Business value
Although largely hidden from the view of most business users, well-chosen identifiers make it significantly easier for subsequent generations of analysts and developers to understand what the system is doing and how to fix or extend the source code for new business needs.

For example, although the following:
a = b * c;
is syntactically correct, it is entirely opaque as to intent or meaning. Contrast this with:
dblWeeklyPay = dblHoursWorked * dblPayRate;
which implies the intent and meaning of the source code, at least to those familiar with the underlying context of the application.

Comments
Commented code helps future generations of developers easily understand what sections of code are supposed to be doing. Using comment blocks native to the language make note of the major function of the following few lines as well as outline expected input and output (if applicable). Believe it or not commenting your code will help you too.
# qchecker.pl # This program will check the current Q for any old items # checkActiveQ # Function that will look up items in the Active Q sub checkActiveQ{ # Code here … }

Variables
Variables should be prefixed to indicate their data type. Optionally, especially for large programs, the prefix can be extended to indicate the scope of the variable. The body of a variable or procedure name should use mixed case (CamelCase) and should be as long as necessary to describe its purpose. In addition, function names should begin with a verb, such as initNameArray or closeDialog.

For frequently used or long terms, standard abbreviations are recommended to help keep name lengths reasonable. In general, variable names greater than 16 are considered too long.

When using abbreviations, make sure they are consistent throughout the entire application. Randomly switching between cnt and Count within a project will lead to unnecessary confusion.

Variable Data Types

Use the following prefixes to indicate a variable’s data type.

Data type Prefix Example
Boolean bln blnFound
Byte byt bytRasterData
Collection object col colWidgets
Currency cur curRevenue
Date (Time) dtm dtmStart
Double dbl dblTolerance
Error err errOrderNum
Integer int intQuantity
Long lng lngDistance
Object obj objCurrent
Single sng sngAverage
String str strFName
Variant var varCheckSum

Using CamelCase
Indicate word boundaries using medial capitalization (also called “CamelCase” and many other names), thus rendering “two words” as either “twoWords” or “TwoWords”.

Meh!..

1.capitalizationIsUsuallyAtTheBeginning
2.underlines_are_usually_under_the_words_not_the_spaces
3.subject.verb(noun,noun)

Indentation
Indentation rules (most coding standards impose) really contradict
rules of good writing,
the way people perceive information,
and the grammar rules.
Making things (that group naturally, but not syntactically) inside
parenthesis also contradicts how texts are usually typed.
If (you try to type text that way)
you’ll face misunderstanding even (if programmers read you)
otherwise
your text will be easy to read,
and your writing will be productive
!

If you have questions or comments let me know by posting a comment.

How to fix: “PageHandlerFactory-Integrated” has a bad module when setting up ASP.NET

I was recently setting up IIS 7.5 on Windows 2008 R2 for an ASP.NET site and came across the following 500 error:

Handler “PageHandlerFactory-Integrated” has a bad module “ManagedPipelineHandler” in its module list.

After a bit of searching, it turns out ASP.NET was not completely installed with IIS even though I checked that box in the “Add Feature” dialog. I found a number of suggestions but found this command. It fixed my issues and got rid of the error.

%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -i 

For a 32 bit system, use the following command.

%windir%\Microsoft.NET\Framework\v4.0.21006\aspnet_regiis.exe -i

Simple Bash Script To Email Server Status

I didn’t want to constantly have to log into my servers in order to check on key performance indicators so I decided to write a simple script that would do the checking for me. After collecting results, the script emails them to me.

There are a few tools called within the script you might need to install. I also convert any tabs into spaces in order to make sure things line up nicely inside my email.

#!/bin/bash

SERVER="myserver001"
TOEMAIL="admin@myservers.com"
FROMEMAIL="myserver001@myserverscom"
# Who is logged in and what are they up to
WHO=`w`
# Hows my processor doing
MPSTAT=`mpstat`
# Hows my virtual memory doing
VMSTAT=`vmstat`
# Top 10 memory consumers
PS_MEM=`ps -A -o pid,pcpu,pmem,start_time,state,time,comm | perl -e '($_ = join "",<>) =~ s/(\t)/     /g; print;' |sort -g -k 3 -r | head -10`
# Top 10 cpu consumers
PS_CPU=`ps -A -o pid,pcpu,pmem,start_time,state,time,comm | perl -e '($_ = join "",<>) =~ s/(\t)/     /g; print;' | sort -g -k 2 -r | head -10`
#  Memory usage in MB
FREE=`free -m`
# Procinfo
PROCINFO=`procinfo`
# IPTables status
IPTABLES=`iptables -nL`
# Established connections
NETSTAT=`netstat -na |grep -i esta |grep -v 127.0.0.1 |sort -n -t. -k2`
# Filesystem space
FILESYSTEM=`df -h`
# Line divider
DL="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
# Put the email together
BODY="${DL}
`date`
${DL}
${SERVER}
${DL}
${WHO}
${DL}
${FREE}
${DL}
${MPSTAT}
${DL}
${VMSTAT}
${DL}
${PROCINFO}
${DL}
Top 10 CPU processes
${PS_CPU}
${DL}
Top 10 Memory processes
${PS_MEM}
${DL}
${IPTABLES}
${DL}
${NETSTAT}
${DL}
${FILESYSTEM}
${DL}
"

echo "${BODY}" | perl -e '($_ = join "",<>) =~ s/(\t)/     /g; print;' | sendEmail -f "${FROMEMAIL}" -u "${SERVER} Status Update" -t ${TOEMAIL}

Adding the script to cron, I now get a daily update on how my server is doing.

LED mod for 2012 Ninja Instrument Cluster

Over the weekend I decided to update the LEDs in my instrument cluster. I have a green 2012 650 and I liked the factory white back lighting but I thought it would be cool to have a green tachometer needle and green speed display. I had seen people do a complete replacement of the 09-11 clusters and that look easy enough… Man was I in for a surprise! The new instrument cluster was completely redesigned for the 2012 model and the new assembly provides a new set of challenges.

  1. Disconnect the battery.
  2. Remove the “meter unit” as its called in the service manual. This was easy, simply remove the upper inner fairing and the three mounting screws.
  3. Once the unit is removed from the bike remove the inner circuit board from the housing (four black screws on the back and four silver screws on the inside.)
  4. Very carefully remove the tach needle. I used a fork and slowly wedged it up under the button. With a little convincing it popped off.
  5. WARNING: According to the service manual you should not leave the board upside down (gauges facing down) for any length of time. There is a good chance the unit will later malfunction.
  6. Flip the board upside down (yea I know I just told you not to) and remove the solder from the pins holding the display to the board.
  7. Carefully separate the display and circuit board making sure not to bend any of the display pins.
  8. Remove and replace the desired LEDs. I bought OSRAM LTT68C Green LEDs from ebay for $1 shipped. For this project I only used four. (I’m now looking for more places to add green LED lighting).

    Make sure you solder the LED’s back in the same way you took them out.
    The LED’s have a little notch in one corner and that should be soldered in opposite the “A” on the board (see the white arrow below). Here is a closeup of the stock LED (white and yellow) and the new green one (white and black).
  9. Here’s a photo of the LED’s I replaced (the green ones).
  10. To reassemble the unit make sure you have all of the LCD display pins firmly soldered back to the board.
  11. The tach has a “stop” point when turned all the way to the left. Make sure you turn the gauge all the way to the stop point and then push the needle back onto the pin with the needle pointing to zero. I thought i did this and the first time it ended up being about 300 rpm off.
  12. Here is a photo with the garage door closed and lights out. The photo really doesn’t do it justice because at night the green shows up much brighter.

    Start to finish the project took about 4 hours. Most of that time is attributed to cleanly removing all of the solder to separate the display from the circuit board.

2012 Ninja Fender Mod

The new-ness of my bike has worn off and I’ve started modifying it a bit to make it “my own”. I recently posted my Garage Door opener mod. I recently had a bit more time so I decided to mod my fender, using all factory parts. Here are the before and after photos:

The great thing about this mod is, besides a little time, I didn’t spend a dime. With a hacksaw you too can mod your fender and save some coin.

  1. Remove the fender.
    • The fender on the 2012 Ninja is held on by three bolts and one screw (why, I have no idea)
  2. Now that you have the fender off, strip it down to the core structure leaving an elephant like looking object.
  3. I wanted to retain the tie down loops because my bike didn’t come with the grab handles (none of the 2012′s did). As a result I hacked off the bottom of the fender support after the loops.

    Here is what the support looks like on the bike without the lights or plates.
  4. The brackets that are welded to the tie downs have a bolt hole in them where the plastic factory fender was bolted. Using a little of the stock plate from underside of the stock fender I cut out L brackets. I then used these to mount the turn signals to the fender support.
  5. I reused the license plate holder and using the space between the tag and inspection sticker I drilled a hole large enough to mount the license plate light (facing up onto the plate).
  6. All of the wiring was re-run up through the support and under the seat where it all plugged back in with no issues.
  7. Here is the modified fender prior to mounting back up to the bike.

The whole process took about 5 hours simply because I was learning as I went. Thinking back on it I bet it would only take an hour or two depending on your skill with a hacksaw, hammer, and drill. Here are a few pics of the fender on the bike.