Friday, October 23, 2009

Real time log file watcher

Have you ever wanted to be notified - in real-time - of an event in a log file?

This is a very efficient and effective way to do it.. all you need is inotifywait (in inotify-tools package, and of course inotify enabled kernel which is pretty standard these days).

#!/bin/bash
LOGFILE=/var/log/smdr.log
while inotifywait -qq -e modify $LOGFILE; do
x=`tail -n1 $LOGFILE | grep "something"`
if [ "$x" != "" ]; then
  echo $x | mailx -s "Something happened!" you@abc.org
fi
done

Wednesday, October 21, 2009

Automatic Proxy Howto

For business laptops, moving from home to the office - proxy settings can be a pain. You can use browser plugins like "foxy proxy" - but the best solution - bar none - is automatic proxy configuration.

To get automatic proxy configuration working (at the office where proxy is required), you need a webserver (eg. apache2), a name server (eg. bind9), and a DHCP server (eg. dhcp3).

Apache2 config
* Put javascript into setProxy.pac in you webserver root directory (change it for your domains/proxy)


function FindProxyForURL(url, host)
{
if (isPlainHostName(host) ||
dnsDomainIs(host, ".yourdomain1.ca") ||
dnsDomainIs(host, ".yourdomain2.ca"))
return "DIRECT";
else return "PROXY yourproxy.yourdomain.ca:8080; DIRECT";
}


* Link wpad.dat to it (ln -s setProxy.pac wpad.dat)
* add the following to apache mime.types file (on ubuntu just /etc/mime.types):

 application/x-ns-proxy-autoconfig dat
 application/x-javascript-config pac

* restart apache  (/etc/init.d/apache2 restart)

Bind9 config
* add the following to /var/cache/bind/db.yourdomain.ca
wpad IN CNAME apachehost.yourdomain.ca.

* restart named (don't forget to change serial number) - /etc/init.d/bind9 restart


In other words, "wpad" has to resolve to your apache server... so client can "ping wpad"

DHCP config
* add the following to /etc/dhcp3/dhcpd.conf:
 option wpad code 252 = text;
 option wpad "http://apachehost.yourdomain.ca/setProxy.pac ";
 (last space is MANDATORY - IE strips last char)

* restart dhcp


That should do it!

This works with KDE 4 - w/ Google Chrome (set in KDE network settings).  And with Firefox 3.0.14 with "Automatic proxy" option selected.

KDE 4 - Network Manager and KDE Wallet

Quite annoyingly the KDE 4.x Network Manager *requires* the KDE Wallet to be enabled to store passwords for secure networks (WEP/WPA).

If KDE Wallet is enabled - then it requires a password... so you login, and are immediately prompted for KDE Wallet password.

The only way I found to get around this is to set the KDE wallet password to be blank.

Click on KDE Wallet in tray, click kdewallet, goto File -> Change Password, and leave both blank.

IF a system is set to autologin, then I can understand the whole KDE wallet idea - but for users explicitly logging in with a password, KDE Wallet should be accessed transparently.

Monday, October 19, 2009

Linux performance tuning - I/O wait

Have a 64-bit ubuntu linux (hardy) system running 30 KDE desktop sessions (using nomachine's NX) on an IBM bladeserver HS21 with 2 quad-core Xeon's and 16G of RAM.  Many times a day, users would experience "freezes" within either firefox or evolution that would last up to about 15 seconds.. window completely unresponsive - then would resume execution.  This using the stock 2.6.24-24-generic ubuntu kernel with voluntary prempting.

After much performance monitoring with sar, and associating the timing of the freezes to sar data, we determined that I/O wait seemed to be the culprit.  Real memory usage {used - (cached+buffered)} only ever peaked around 12G, and CPUs were largely idle.

Disk is 10k rpm 300GB SAS 2.5" drive.. in RAID 1 (mirrored) using HS21 onboard LSI controller.

I/O Wait is primarily disk I/O but could be network I/O as well, so we decided to tune disk and network.

Filesystems is using ext3 and mounted with noatime.

Finding this link , I tried adding the mount options: noatime,nobh,data=writeback,commit=90

NOTE:  If on root filesystem, you must add "rootflags=nobh,data=writeback,commit=90" in grub.

After a reboot, and once full load was back on system, I realized a substantial reduction in average IO wait time (from ~50ms to ~25ms), and overall average % disk utilization (from ~15% to ~8% - statistics from iostat).




This was great improvement but there were still slight 1-2s freezing incidents at this point, so I additionally tweaked the network...

For network performance tuning I ran across this link and added the following to /etc/sysctl.conf:

net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_fin_timeout=30
net.ipv4.tcp_keepalive_time=1800
net.core.wmem_max=8388608
net.core.rmem_max=8388608
net.ipv4.tcp_rmem="4096 87380 8388608"
net.ipv4.tcp_wmem="4096 87380 8388608"

Together, these have stopped the "freezing" altogether.  There are still periods of slowness due to load, but now they are few and far between.

Friday, October 9, 2009

Locking Firefox 3 preferences in Ubuntu


1. Create a file called loadcustom.js in /usr/lib/firefox-3.0.x/defaults/preferences/, where 3.0.x will be something like 3.0.11 or 3.0.14 depending on your current version.
Put the following in /usr/lib/firefox-3.0.x/defaults/preferences/loadcustom.js

// tell firefox to load customized config file
pref("general.config.obscure_value", 0);
pref("general.config.filename", "firefox.cfg");

2. Create a file called firefox.cfg in /usr/lib/firefox-3.0.x/ with the following content (the first line in both files must start with a comment):

// Lock specific preferences in Firefox so that users cannot edit them
lockPref("app.update.enabled", false);
lockPref("network.proxy.http", "127.0.0.1");
lockPref("network.proxy.http_port", 8080);
lockPref("network.proxy.type", 1);
lockPref("network.proxy.no_proxies_on", "localhost, 127.0.0.1, 192.168.1.0/24");
lockPref("network.proxy.share_proxy_settings", true);
lockPref("browser.startup.homepage", "http://www.desiredhomepage.com/");

3. Restart Firefox, and the preferences should be locked down. You should be able to use this to lock down any setting in about:config

Tuesday, October 6, 2009

32-bit firefox on 64-bit ubuntu hardy

Problem: External applet which requires Java 1.5 on 64-bit system.. no firefox plugin for Java 1.5 in 64-bit exists to date (Oct. 6, 2009 - and not likely to happen!)

Solution: Run 32-bit firefox in chroot environment

Following https://help.ubuntu.com/community/DebootstrapChroot

sudo apt-get install debootstrap schroot

Edit /etc/schroot/schroot.conf and add the following:

[hardy_i386]
description=Ubuntu 8.04 Hardy for i386
location=/srv/chroot/hardy_i386
personality=linux32
root-users=bob
run-setup-scripts=true
run-exec-scripts=true
type=directory
users=alice,bob,charlie

$ sudo mkdir -p /srv/chroot/hardy_i386
$ sudo debootstrap --variant=buildd --arch i386 hardy /srv/chroot/hardy_i386 http://archive.ubuntu.com/ubuntu/

Will take a while.. downloads base packages

$ schroot -c hardy_i386 -u root

apt-get install ubuntu-minimal

Edit /etc/apt/sources.list and add "universe multiverse" to end of the line

apt-get update
apt-get install firefox sun-java5-plugin

In order to get NIS working, I had to install nis package and edit /etc/nsswitch.conf accordingly.

IF you don't want your "real" /home mounted in chroot environment, then edit /etc/schroot/setup.d/10mount and comment out (#) line with /home.

You'll have to create /home/username (mkdir /home/username; chown username /home/username)

Now exit.. and start again as user:

$ schroot -c hardy_i386

firefox -no-remote

NOTE: -no-remote is need in case 64-bit firefox is running already

Goto "about:plugins" to see if Java plugin is available.

Wednesday, July 22, 2009

Manually removing ubuntu or debian package

Ran into an issue where a package was only partially removed from an ubuntu system - have no clue why.. but it was in a loop.. "apt-get -f install" would try to remove packagex and fail due to not existant post-remove script.

Thanks to this post you can manually remove an ubuntu/debian package doing the following:

First try:

dpkg -P packagex

Likely this will still fail so do:

dpkg -L packagex

this will give you a list of files to delete when the next step is done.

Then go to the directory:

/var/lib/dpkg/info

and delete the file:

packagex.postrm

and do:

apt-get remove --purge packagex
OR
apt-get -f install

to finish up, remove all files you found in the 'dpkg -L' step, and directories specific to packagex.

Then run apt-get update


Monday, July 6, 2009

rsync and directory renaming

rsync is an extremely useful tool - but its one shortcoming is when it comes to file and/or directory renaming. I am using it to mirror file systems using "rsync -xHau --delete /home remotesystem:/somedir".

If a file or directory gets renamed on the source host, the entire file or directory gets re-copied.

For files, there is the --fuzzy option, and there is a patch for "detect-renamed" - but files are less of a problem for me.

Directory renames are not addressed by any patch or option that I can find, and often results in a much higher transfer volume (especially if a high-level directory is renamed).

I've developed a strategy that works great in my scenario.. essentially, after every rsync of a file system, a .rsyncname file is created in every directory (to a configurable max depth) simply holding the name of the directory itself. Before each rsync, all the .rsyncname files are compared to the directory name - and if different, a rename is triggered on the remote system. This requires top-down processing so I opted for a breadth-first search algorithm (cannot rename a leaf node if higher node needs renaming).

There are 3 scripts involved, which I called rsyncstorename, rsyncbasename, and rsyncrename, all of which I put in /usr/local/bin on the "source" host. (not required on the mirror host)

rsyncstorename:

#!/bin/bash

dir=$*
x=`cat "$dir/.rsyncname"`
y=`basename "$dir"`
if [ "$x" != "$y" ]; then
echo $y > "$dir/.rsyncname"
fi
This is used by rsyncbasename, and not called directly. The comparison adds a little overhead, but it saves on rsync time overall. Originally it was just creating the file every run - but each rsync sent every .rsyncname file to remote host. With this method - its one-time cost.

rsyncbasename:

#!/bin/bash

#$1 = path
#$2 = max depth

find $1 -maxdepth $2 -mount -type d -exec /usr/local/bin/rsyncstorename {} \;

Very simple.. pass the file system path and the desired max depth (eg. "rsyncbasename /home 4"), but is called from rsyncrename script. Doesn't cross file-system boundaries.

rsyncrename:

#!/bin/bash

#$1 = path
#$2 = max depth
remotepath=/mnt/disk
remotehost=somehost

r ()
{
let level=$3+1
if [ $level -gt $4 ]; then return 0; fi
cd "$1"
for d in *; do
if [ -d "$d" ]; then
if [ -L "$d" ]; then
echo "skipping symbolic link"
else
if [ -f "$d/.rsyncname" ]; then
x=`cat "$d/.rsyncname"`
y=`basename "$d"`
if [ "$x" != "$y" ]; then
echo renaming $remotepath$2/$x to $remotepath$2/$d
ssh $remotehost mv "$remotepath$2/$x" "$remotepath$2/$d"
fi
fi
fi
fi;
done
for d in *; do
if [ -d "$d" ]; then
(r "$d" "$2/$d" $level $4)
fi;
done
}

r "$1" "$1" 0 "$2"
rsync -xHau --delete $1 $remotehost:$remotepath`dirname $1`
/usr/local/bin/rsyncbasename $1 $2

Arguments are again path and depth (eg. "rsyncrename /home 4"). Change remotehost and remotepath to whatever is required. NOTE: Script expects file system mirror on remotehost:remotepath - ie. if you wish to rsync a sub-directory, eg. /home/userA, then remotehost:remotepath/home must exist. This script combines the rsync and the renaming. Note the sequence, renaming, rsync, then rsyncbasename. Will only work on 2nd iteration, since first time no renaming will occur and .rsyncname files will be created.

BTW.. bash based breadth-first-search algorithm grabbed from here.

NOTE: This method does not handle if a directory branch is relocated (eg. "mv /home/userA/mail /home/userB/mail2") .. rsync will handle this, but everything in the branch will be copied.

Friday, June 26, 2009

4GL comma split function

not really.. but if you want to iterate over a delimited string via 4gl, you can do the following:

(parse_str function adapted from http://www.tek-tips.com/faqs.cfm?fid=2364 )


# This function searches string for an instance of char_delim
# starting at position cnt and returns the string ending at the next
# char_delim or the end of string
######################################################################
function parse_str(char_delim, cnt, string)
######################################################################
define
char_delim CHAR(1), # character delimiter
cnt SMALLINT, # postion in string to start counting
string CHAR(300), # string to search
ret_string CHAR(40), # string returned
i, # index
x, # counter
string_len SMALLINT # string length

LET string_len = LENGTH(string)

IF string_len = 0 # got a null string
THEN
RETURN "",0
END IF

IF string[cnt] = char_delim
THEN
LET cnt = cnt + 1 # get off the delimiter
END IF
IF cnt > string_len
THEN # return when the end of the string is reached
RETURN "",0
END IF

LET x = 1
FOR i = cnt TO string_len
IF string[i] = char_delim
THEN
EXIT FOR
END IF
LET ret_string[x] = string[i] # save a character
LET x = x + 1
END FOR

return ret_string, i # return the positon ended
end function

function split(f_orig)
define f_orig,f_str char(100), x, f_pos smallint
let x = length(f_orig)
let f_pos = 1
while (f_pos > 0 and f_pos < x)
call parse_str(",",f_pos,f_orig) returning f_str, f_pos
display f_str, f_pos
end while
end function

main
call split("some,comma,delimited,string")
end main

Aubit4GL: connecting to mysql and informix concurrently

Since database connections seems to be compile time, and you have to set A4GL_SQLTYPE in order to compile against database X - I wonder how you can open concurrent connections.. I cannot find any documentation on how to do this - but according to http://aubit4gl.sourceforge.net/aubit4gldoc/manual/html/features_summary.html it maybe that you have to use ODBC connections to each instead of native??

It seems that "open session" and "use session" can be used to dynamically switch at runtime. But compile time seems to be the kicker.. especially if you use "define x like table.column" in 4gl, unless it allows "define x like db.table.column" or searches both databases.

Thursday, June 25, 2009

Aubit4GL: mysql connection specification

Since this is not well documented on Aubit4gl site, posting here:

To connect to mysql database:

  1. Make sure your mysql server is not bound to localhost - even local connections are via hostname
  2. Make sure you can connect to mysql server.. grant at least select privs using "grant select on db.* to 'test'@'hostname' identified by 'test';" NOTE: localhost privs are not enough - connection thru hostname.
  3. Do "export MYSQL_SERVER=hostname"
  4. Set/export the following environment variables:
A4GL_SQLUID=test #whatever connection user is
A4GL_SQLPWD=test #whatever connection password is
A4GL_LEXDIALECT=INFORMIX
A4GL_LEXTYPE=C
A4GL_SQLTYPE=mysql

And now take the simple.4gl program:

database test # of whatever your database name is

main
display "Hello World"
end main

Compile with : aubit 4glpc simple.4gl -o simple.4ae

If it compiles - database connection is ok!

Thanks to Mike's comment below - using .aubit4gl.acl to store database:user:pw DOES work.. just be sure to "unset A4GL_SQLUID" and "unset A4GL_SQLPWD".

Logitech Quickcam Pro 9000 on ubuntu hardy - no go

On initial plugin:

[ 102.851571] usb 3-1: new full speed USB device using uhci_hcd and address 2
[ 44.040462] usb 3-1: device descriptor read/64, error -71
[ 102.933128] usb 3-1: device descriptor read/64, error -71
[ 102.939599] usb 3-1: new full speed USB device using uhci_hcd and address 3
[ 102.945009] usb 3-1: device descriptor read/64, error -71
[ 102.970417] usb 3-1: device descriptor read/64, error -71
[ 102.983105] usb 3-1: new full speed USB device using uhci_hcd and address 4
[ 103.020497] usb 3-1: device not accepting address 4, error -71
[ 103.025529] usb 3-1: new full speed USB device using uhci_hcd and address 5
[ 103.060941] usb 3-1: device not accepting address 5, error -71
[ 116.499098] usb 5-5: new high speed USB device using ehci_hcd and address 5
[ 116.627482] usb 5-5: configuration #1 chosen from 1 choice

and

lsusb -d 046d:0990 -v | grep bcdDevice
bcdDevice 0.08
which according to http://www.quickcamteam.net/documentation/faq/how-many-versions-of-the-quickcam-pro-9000-are-there says its third generation with buggy firmware.

If I launch cheese - system hangs completely.

According to http://linux-uvc.berlios.de/, linux 2.6.26 includes linux uvc driver natively.. but hardy is 2.6.24.

Downloaded the driver from http://linuxtv.org/hg/~pinchartl/uvcvideo/ (gz link) and then..

tar zxvf uvcvideo-bff77ec33116.tar.gz
cd uvcvideo-bff77ec33116/
make # and go have a coffee
sudo make install
reboot
dmesg now shows:

[ 105.937744] usb 5-5: new high speed USB device using ehci_hcd and address 3
[ 106.197507] usb 5-5: configuration #1 chosen from 1 choice
[ 107.127908] Linux video capture interface: v2.00
[ 107.135021] usbcore: registered new interface driver snd-usb-audio
[ 45.915452] uvcvideo: Found UVC 1.00 device (046d:0990)
[ 45.932166] input: UVC Camera (046d:0990) as /devices/pci0000:00/0000:00:1d.7/usb5/5-5/5-5:1.0/input/input10
[ 45.962220] usbcore: registered new interface driver uvcvideo
[ 45.962226] USB Video Class driver (v0.1.0)

cheese shows no output
skype neither
dmesg now shows

[ 177.592621] uvcvideo: Failed to set UVC probe control : -110 (exp. 26).
[ 177.976920] uvcvideo: Failed to set UVC probe control : -110 (exp. 26).
[ 178.401788] uvcvideo: Failed to set UVC probe control : -110 (exp. 26).
[ 178.807251] uvcvideo: Failed to set UVC probe control : -110 (exp. 26).
[ 179.193500] uvcvideo: Failed to set UVC probe control : -110 (exp. 26).
[ 179.743456] uvcvideo: Failed to set UVC probe control : -110 (exp. 26).
[ 180.154183] uvcvideo: Failed to set UVC probe control : -110 (exp. 26).
[ 180.655020] uvcvideo: Failed to set UVC probe control : -110 (exp. 26).

skype reports

Skype V4L2: Could not find a suitable capture format
Skype V4L2: Could not find a suitable capture format

Aborting effort for now..

Tuesday, June 23, 2009

mysqldump to informix DS

Problem: Need to access mysql 5.0 data from 4js BDL (I4gl)

Solution attempts:
  1. generate 4js dynamic VM with mysql support.. no mysql 5.0 support (only 4.x) and not forward compatible
  2. try aubit4gl with mysql support.. no go.. see this
  3. call script to unload mysql table and then load into informix
On solution attempt 3 - this proved more difficult than I first imagined.

I've been spoiled with Informix's very easy "unload to". Mysql simply has no equivalent. There is the "SELECT INTO OUTFILE", but (1) you need to "grant file on *.* to 'user'@'whateverhost'" (besides select permission of course), and (2) can be run from a remote host, but the output file is local to the mysql server instance.. and while you can use NFS, its a pain.

Also there is mysqldump - which I thought might do it.. but alas, if you use the --tab option it uses "SELECT INTO OUTFILE" internally anyway - plus you need to "grant lock tables on db.* to 'user'@'whateverhost'".

Ok - so had to revise my strategy - since I am running this script on remote host... this generates ansi "insert" statements that I will try to execute against informix:

mysqldump -h mysqlhost -usomeuser -psomepassword --compatible=ansi --no-create-info --compact dbname tablename > x.sql

Kinda works.. doesn't like text fields (clob datatype in informix).. and date formating could be an issue (easily fixed with informix DBDATE environment variable).. but certainly not as easy as I imagined.

BladeCenter S vitals via SNMP - installing MIBs

Thanks to this post:

http://blog.barfoo.org/2009/02/10/monitoring-the-ibm-bladecenter-chassis-with-nagios/

I was able to use SNMP to get all kinds of info from my BladeCenter S - and specifically have it monitored with nagios. The original poster stated that the OIDs weren't documented anywhere.. but that is what the mib file is.. you just need to install it..

Here is how to install the MIBs from the IBM firmware (mmblade.mib) on ubunutu (requires snmp package):

copy mmblade.mib (contained in the firmware download) to /usr/share/snmp/mibs/BLADE-MIB.txt

(if you want alerts.. copy mmalerts.mib to /usr/share/snmp/mibs/BLADESPPALT-MIB.txt)

You now have access to over 10,000 settings.. you can get a complete list by doing:

snmpwalk -v1 -c public -Of ipaddress-of-bladecenterS -m BLADE-MID enterprises.ibm


and then for example, to find the front panel temperature:

snmpwalk -v1 -c public -Of ipaddress-of-bladecenterS -m BLADE-MIB enterprises.ibm.ibmAgents.netfinitySupportProcessorAgent.
bladeCenterSnmpMIB.monitors.temperature.ambientTemp.
frontPanelTemp.0


which, although quite verbose.. is more human readable than
snmpwalk -v1 -c public -Of ipaddress-of-bladecenterS
.1.3.6.1.4.1.2.3.51.2.2.1.5.1.0



Monday, June 22, 2009

Aubit4GL and libmysqld

Had a frustrating time trying to build aubit4gl on ubuntu with mysql support.

/usr/bin/ld: /usr/lib/mysql/libmysqld.a(net_serv.o): relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
/usr/lib/mysql/libmysqld.a: could not read symbols: Bad value


This is from libmysqlclient15-dev package. Turns out its not even an ubuntu issue.. its actual mysql bug:

http://bugs.mysql.com/bug.php?id=39288

I did see somewhere that it was fixed in libmysqlclient16-dev - which is not available in hardy (8.04) which I need.

I stumbled upon this link and was able to build a relocatable libmysqld.. but then I ran it this:

gcc -shared -L/lib -o /opt/aubit4gl/src/plugins-1.10RC_62/libSQL_mysqldb.so db-mysql.o -L/usr/local/lib -L/usr/local/mysql -L/usr/lib/mysql -L/usr/lib -L/opt/aubit4gl/src/lib -lmysqld -laubit4gl-1.10RC_62 -Wl,-Bsymbolic-functions -L/usr/lib/mysql -lmysqld -lwrap -lrt
/usr/bin/ld: cannot find -lwrap
even though libwrap is in /lib .. arrrg ok.. so I did the following:

cd lib/libsql/mysql
gcc -shared -L/lib -o /opt/aubit4gl/src/plugins-1.10RC_62/libSQL_mysqldb.so db-mysql.o -L/usr/local/lib -L/usr/local/mysql -L/usr/lib/mysql -L/usr/lib -L/opt/aubit4gl/src/lib -lmysqld -laubit4gl-1.10RC_62 -Wl,-Bsymbolic-functions -L/usr/lib/mysql -lmysqld
cd ../../..
make
(ie. I just removed -lwrap and -lrt and it went ok) and proceeded to compile the remainder of aubit4gl. Now to test against mysql