2012
03.15

Here’s a little snippet that I use to remove all the unused kernels on my Ubuntu servers/desktops. Unused means all the kernel that are currently not in use. For servers that don’t reboot so often that could mean removing kernels that are newer than uname -r. So make sure to pay attention…

dpkg -l | egrep '^ii  linux-(image|headers)-2' | awk '{print $2}' \
  | grep -v $(uname -r | sed 's/-generic//' | sed 's/-server//') \
  | xargs apt-get remove --purge -y \
;
2011
11.28

For a while I wanted to graph the HTTP response time of my server(s). I already had Nagios monitor it but now I wanted a nice Cacti image. Based on the check_http script I created (thanks to guy2006) a Perl wrapper to return the response time part:

# /usr/lib/nagios/plugins/check_http -H foo.bar.com -f follow -t 60
HTTP OK: HTTP/1.1 200 OK - 17235 bytes in 0.135 second response time |time=0.134897s;;;0.000000 size=17235B;;;0

The response time part is used as a “Data Input Method” for Cacti.

Implementation:

Create the file check_http.pl in /usr/share/cacti/site/scripts/.

#!/usr/bin/env perl
$response = `/usr/lib/nagios/plugins/check_http -H $ARGV[0] -f follow -t 60`;
chomp $response;
($load) = ($response =~ /time=(\d+\.\d+|\d+\.|\.\d+|\d+)/);
print "$load\n";

Make sure you have the file check_http (it’s in the nagios-plugins-basic package) and it’s located in /usr/lib/nagios/plugins/.

# apt-file search check_http
kannel-extras: /usr/lib/kannel/checks/check_http.sh
kannel-extras: /usr/lib/kannel/checks/check_httpsmsc_kannel.sh
nagios-plugins-basic: /usr/lib/nagios/plugins/check_http
nagiosgrapher: /usr/share/nagiosgrapher/debian/cfg/ngraph.d/standard/check_http.ncfg
# locate check_http
/usr/lib/nagios/plugins/check_http

Test the Perl wrapper, preferably as user cacti:

# perl check_http.pl foo.bar.com
0.425045

Import the XML Template into Cacti (it’s under Import/Export).

Make sure to change the “Consolidation Function” (of Item # 1) from LAST to Average (it’s under Templates -> Graph Templates). Also make sure to fill in an ip address or hostname. Otherwise your graph will be blank.

Your graph will look something like this:

Cacti - HTTP Response Time

Cacti - HTTP Response Time

References:

2011
11.08

While installing RMySQL on OS X and Linux is really simple this is not the case for Windows. After trying several how to’s RMySQL still wasn’t working. Then I started experimenting my self… With success!

This is what I did:

  • Install R 2.14
  • Install R tools (2.14) (with modifying path option)
  • Install MySQL (5.5.17) (with modifying path option)
  • Create the file Renviron.site in the folder C:\Program Files\R\R-2.14.0\etc and add:

    MYSQL_HOME=C:/Program Files/MySQL/MySQL Server 5.5
    
  • Copy libmysql.lib and libmysql.dll from

    C:\Program Files\MySQL\MySQL Server 5.5\lib to
    C:\Program Files\MySQL\MySQL Server 5.5\lib\opt (must be created)

  • Copy libmysql.dll from
    C:\Program Files\MySQL\MySQL Server 5.5\lib to
    C:\Program Files\R\R-2.14.0\bin\i386
  • Open R and install RMYSQL

    install.packages('RMySQL', type = 'source');
    

If everything went well you’ll now be able to load the RMySQL package by invoking:

library(RMySQL);

in R.

Resources:

2011
09.04

For a long time I wanted Google Calendar to display the duration of events (in hours). Unfortunately this feature is not supported (as far as I know), not even by Labs. So I created a little piece of JavaScript which can be executed via a bookmark (at an event page with a start and end date).

Event page

Google Calendar - Event page

This is how the snippet look like:

// select elements by classname
var getElementsByClassName = function (classname, node) 
{
  if(!node) 
  {
    node = document.getElementsByTagName("body")[0];
  }
  var a = [];
  var re = new RegExp('\\b' + classname + '\\b');
  var els = node.getElementsByTagName("*");
  for(var i = 0, j = els.length; i < j; i++)
  {
    if(re.test(els&#91;i&#93;.className))
    {
      a.push(els&#91;i&#93;);
    }
  }
  return a;
};

// parse a date based on a dateDay field (e.g. 2011-09-03) and a dateTime field (e.g. 09:30)
var parseDate = function (dateDay, dateTime)
{
  var dateDay = dateDay.split('-');
  var dateTime = dateTime.split(':');
  var fullDate = dateDay.concat(dateTime).map( function( num ) { return parseInt( num, 10 ) } );
  
  return new Date(fullDate.shift(), fullDate.shift(), fullDate.shift(), fullDate.shift(), fullDate.shift());
};

// calculate the difference between two dates in hours
var dateDiff = function (startDate, endDate)
{
  var diff = endDate - startDate;
  return diff / ( 1000 * 60 * 60 );
};

var startDateDay = getElementsByClassName('dr-date')&#91;0&#93;.value;  // 2011-09-03
var startDateTime = getElementsByClassName('dr-time')&#91;0&#93;.value; // 09:30
var endDateDay = getElementsByClassName('dr-date')&#91;1&#93;.value;    // 2011-09-03
var endDateTime = getElementsByClassName('dr-time')&#91;1&#93;.value;   // 17:45

alert(dateDiff(parseDate(startDateDay, startDateTime), parseDate(endDateDay, endDateTime)));
&#91;/code&#93;

The compressed bookmark version looks like this:

&#91;/code&#93;&#91;code lang="javascript"&#93;
javascript:var%20getElementsByClassName=function(h,g){if(!g){g=document.getElementsByTagName("body")&#91;0&#93;}var%20b=&#91;&#93;;var%20f=new%20RegExp("\\b"+h+"\\b");var%20e=g.getElementsByTagName("*");for(var%20d=0,c=e.length;d<c ;d++){if(f.test(e&#91;d&#93;.className)){b.push(e&#91;d&#93;)}}return%20b};var%20parseDate=function(a,b){var%20a=a.split("-");var%20b=b.split(":");var%20c=a.concat(b).map(function(d){return%20parseInt(d,10)});return%20new%20Date(c.shift(),c.shift(),c.shift(),c.shift(),c.shift())};var%20dateDiff=function(a,c){var%20b=c-a;return%20b/(1000*60*60)};var%20startDateDay=getElementsByClassName("dr-date")&#91;0&#93;.value;var%20startDateTime=getElementsByClassName("dr-time")&#91;0&#93;.value;var%20endDateDay=getElementsByClassName("dr-date")&#91;1&#93;.value;var%20endDateTime=getElementsByClassName("dr-time")&#91;1&#93;.value;alert(dateDiff(parseDate(startDateDay,startDateTime),parseDate(endDateDay,endDateTime)));
&#91;/code&#93;
</c>

When clicking the bookmark you’ll see an alert box with the duration in hours:

Event page

Google Calendar - Event duration

In the future I will probably create something more fancy with the “Google Calendar APIs and Tools” but for now this is it. Have fun!

2011
08.15

Since libreoffice is the default office suite in Ubuntu 11.04, which I use on my desktop, I also wanted to install that on my laptop (using Ubuntu 10.10). To do so we have to remove openoffice first.

sudo apt-get purge openoffice*.*

After that we can add the libreoffice ppa repository and install!

sudo add-apt-repository ppa:libreoffice/ppa
sudo apt-get update
sudo apt-get install libreoffice
sudo apt-get install libreoffice-gnome
2011
08.14

The default Ubuntu Flash Player was really unstable on my machine. That’s why I went searching for a more stable 64bit version. On Ubuntu 10.04 I used the file libflashplayer-10.0.45.2.linux-x86_64.so.tar.gz that circulated on the web. On 11.04 I found out there’s a nice repository with the latest x86_64 version. Thanks to SevenMachines it is really easy to install.

add-apt-repository ppa:sevenmachines/flash
apt-get update
apt-get install flashplugin64-installer
2011
08.14

You might get this message when the virtual machine you’re opening is out of disk space or at least it thinks it is.

The file system upon which ‘~/VMware/Windows XP Professional – SP3’ resides is critically low on free space. Allowing this virtual machine to continue may cause it to fail unexpectedly. VMware Workstation has paused this virtual machine because the disk on which the virtual machine is stored is almost full. To continue, free up at least 495.2 MB of disk space.

When booting you’ll get stuck in an endless loop. To ignore the above warning and be able to start again add the line below to your (Windows XP Professional).vmx file.

mainMem.freeSpaceCheck = "FALSE"
2011
07.16

Personally I find Gnome’s `Recent documents` feature quit annoying. In earlier versions I always disabled it by doing this:

rm ~/.recently-used.xbel -Rf;
mkdir ~/.recently-used.xbel -p;

Unfortunately that didn’t work anymore… After reading how to Clear/Prevent Recent Documents under Files & Folders in Ubuntu Unity I thought I found a solution, but I didn’t. This piece of magic, on the contrary, did!

echo 'gtk-recent-files-max-age=0' >> ~/.gtkrc-2.0;
2011
07.12

Always wanted to make a tar file without using any local diskspace? This is the solution:

tar zcf - . | pv | ssh foo@bar.com "cat > /data/backup.tgz";

It even has got a progress bar:

163MB 0:00:19 [8,21MB/s] [     < =>     ]

Remember to install pv first:

sudo ap-get install pv

References:

2011
06.16

Today I ran into some Trac problems when trying to view a SVN changeset in the SVN browser. I read that these problems were caused by MySQL? so I tried `the suggested`. Because I had to do this for 3 Trac instances I created a little php (commandline) script to do the job.

< ?php
if ($argc != 2)
{
  echo $argv&#91;0&#93;." <DATABASE>\n";
  exit(1);
}

$db = trim($argv[1]);

if (!$link = mysql_connect('127.0.0.1', 'root', ''))
{
  die(mysql_error());
}

if (!$db_selected = mysql_select_db($db))
{
}

echo "ALTER DATABASE `$db` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;\n";

if (!($result = mysql_query("SHOW TABLES;")))
{
  die (mysql_error());
}

while ($row = mysql_fetch_assoc($result))
{
  $table = array_shift($row);
  echo "ALTER TABLE `$table` ENGINE = InnoDB;\n";
  echo "ALTER TABLE `$table` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;\n";
}
?>

Usage:

php convert_trac_db.php trac;

Output:

ALTER DATABASE `trac` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `attachment` ENGINE = InnoDB;
ALTER TABLE `attachment` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `auth_cookie` ENGINE = InnoDB;
ALTER TABLE `auth_cookie` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `component` ENGINE = InnoDB;
ALTER TABLE `component` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `enum` ENGINE = InnoDB;
ALTER TABLE `enum` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `fullblog_comments` ENGINE = InnoDB;
ALTER TABLE `fullblog_comments` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `fullblog_posts` ENGINE = InnoDB;
ALTER TABLE `fullblog_posts` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `mastertickets` ENGINE = InnoDB;
ALTER TABLE `mastertickets` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `milestone` ENGINE = InnoDB;
ALTER TABLE `milestone` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `node_change` ENGINE = InnoDB;
ALTER TABLE `node_change` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `permission` ENGINE = InnoDB;
ALTER TABLE `permission` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `report` ENGINE = InnoDB;
ALTER TABLE `report` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `revision` ENGINE = InnoDB;
ALTER TABLE `revision` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `session` ENGINE = InnoDB;
ALTER TABLE `session` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `session_attribute` ENGINE = InnoDB;
ALTER TABLE `session_attribute` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `system` ENGINE = InnoDB;
ALTER TABLE `system` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `tags` ENGINE = InnoDB;
ALTER TABLE `tags` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `team_availability` ENGINE = InnoDB;
ALTER TABLE `team_availability` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `ticket` ENGINE = InnoDB;
ALTER TABLE `ticket` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `ticket_change` ENGINE = InnoDB;
ALTER TABLE `ticket_change` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `ticket_completion` ENGINE = InnoDB;
ALTER TABLE `ticket_completion` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `ticket_custom` ENGINE = InnoDB;
ALTER TABLE `ticket_custom` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `version` ENGINE = InnoDB;
ALTER TABLE `version` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `wiki` ENGINE = InnoDB;
ALTER TABLE `wiki` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;

Run this SQL via phpMyAdmin or pipe it to MySql directly:

php convert_trac_db.php trac | mysql -uroot -p trac;