Demo day in work Thursday. All working and stable, a half hour in morning of no light getting back to one Transponder but that's fixed quickly. Demo runs very easily. Back to work automating tests Thur + Fri. Fix labview + socket things, move desk Fri and fix misc test things.
Fri morning Maeve gets up a bit earlier. She can't rouse anyone so crys (because she wants to get up in time to get the bus). Bus rescheduled for next week. We're all ready 8:10. Cycling is mooted for all, but in the end I cycle and kids + Fionn take car.
Whew! I've not cycled to work in a month or more. Hard work.
Hungry Fri evening.
Sat I do motorbike jobs and miscellaneous other things. For motorbike I take off seat (stuck! now oiled) and raise back box and fix left indicator (back box pressed down on it, fixed with bamboo + duct tape). finished desoldering old switch, disconnect messy cables and put switch back on, put in new battery. It's fit to go to garage and not completely confuse a proper bike mechanic now. When warm she's revving high. Carburettor needs cleaning? Also a small hole in exhaust and service should be due.
Motorbike job starts in morning and goes on piecemeal all day interrupted by other things, food, collecting kids. Luckily no rain, cover bike and tools when job left from showers though.
Builder Dermot calls morning. Dominic's brother. Gutter problems pointed out.
With motorbike battery put an old flying insect of Daire's on charge. Flew it a bit with Daire just before light faded.
Collected Kate from gym by bike + trailgator. I thought Kate would be tired but no, loads of energy. I could really feel her pedalling from behind.
In afternoon I go down to Dundrum, look at white shirts - see one in M&S 35 euros, Hmm. no sure. Also the park bike, tramp through half shopping centre and tramp back is ... interesting in a way but ... not a place I like to be. Out and down to Noel Reid's who are back in old Dundrum Shopping Centre. (because now it's not going to be redeveloped so they were allowed to open up again). Measured for suits for My Fair Lady and buy white shirt there. 45 euros. But I couldn't bring myself to park and trail through the Dundrum shopping centre again. Get newspaper on way home.
Evening TV (British family on holiday France, seems normal for a long while though with ominous music. ... scary things do happen!). Some perl for manipulating rubik's cube while doing this (and printing in curses colours).
Sunday up and breakfasted, cappuchinos and hot chocolates for us again, last of milk used. Dominic calls fix radiator leak by tightening valve (valve needs replacing). Water off, fiddling in attic. Gutter pipes and fiddling out back. Wooden floor buckling problem discussions.
We all go see the new Chipmunk movie in Dundrum. That's two movies in a real cinema in about 3 weeks. A phenomenal record for us! It's quite a good and funny one. Maeve really is absorbed and rocks along with the songs.
After this we need quick food. Carvery in Dundrum shopping centre food mall was introduced to me before by theatre crowd. We head there and get good and fast food. Fionn and Kate kids portions of pasta + fish and pasta + chicken. Daire and James and Maeve burger and Lamb and chicken(kids portion) respectively.
I have about 2 main meals each day with lots of food in between. Definately well fed and snacked this weekend!
Grab car from car park, to scout den to drop me for rehersal. We go from start to servants song (and a bit more, probably almost all act 1. We repeat Ascot Gavotte a few times. Both for performace tonight and for show. I'm a butler already for Poor Prof Higgins song but also get a line and bring in Doolittle. Might have to chop off my long hair to be a butler!
Fionn and kids visit Eoghan and Mary and family and collect black shoes and a bow tie for me. Then to GAA for presentations. I walk over to there then to home. Food then I cycle down to Mill. Rehearse Ascot a bit after 7. Then waiting and perform a bit before 9. Whew! Fun. Cycle back up home. Chat and tea, Daire and Fionn. Caoime puts up some photos of the Ascot Gavotte costumes - fellas white shirt and black bow tie with black trousers. Girls dresses and hats all shades of black and white.
My neck is quite sore/stiff. Partly all body sore after cycle Friday.
Oh! That reminds me. I got rear ended at end of Sandyford in the morning on way to work. Me on pedal bike. Rearended by black SUV. I passed a black suv pulling out before getting to traffic lights at bottom end of sandyford village. Way back from lights they went orange and then red so I pulled up in orange box. Stopped and put foot down and stood. Then whang! Rear tyre of bike bounces forwards. Jeezus! The black SUV has driven all the way into the orange box to the front and hit me. I'm surprised! Surprised I'm still standing (and holding bike handlebars with left hand). And looks like me and bike are okay. Looks like plastic of front bumper of SUV hit rubber of my back tyre. I'd say she just barely caught me a glance. I act indignant and lady comes out to say sorry. I'm fine and bike seems fine, she says she turned round behind to look at the kids. Anyway. I run bike across road at end of green light. Can feel shaky then - adrenaline in system.
Later in evening I feel I have a bruise alright - saddle hit my arse. Right cheek.
I have about 2 main meals each day with lots of food in between. Definately well fed and snacked this weekend!
That's it. ach jaysus 12:54 am! Past bedtime. Silly blog/diary compulsion!
Sunday, 28 February 2010
bow tie: origin as shirt fastening
My first time ever wearing a bow tie today :)
http://www.facebook.com/photo.php?pid=3562358&id=694917871
We did the Ascot Gavotte for Mill Theatre Gala night.
http://en.wikipedia.org/wiki/Bow_tie
http://en.wikipedia.org/wiki/Necktie
1650ish Croatian merceneries use neckerchief to hold together their shirts and this caught on among French upper classes as a fashion "cravat".
http://www.facebook.com/photo.php?pid=3562358&id=694917871
We did the Ascot Gavotte for Mill Theatre Gala night.
http://en.wikipedia.org/wiki/Bow_tie
http://en.wikipedia.org/wiki/Necktie
1650ish Croatian merceneries use neckerchief to hold together their shirts and this caught on among French upper classes as a fashion "cravat".
Wednesday, 24 February 2010
log2csv.pl - grep data from any logfile format
Some people here were using LiveGraph, it looks a little grotty but works very very well. I had a quick look at using other things, custom graph generation in perl or perl + gnuplot. But LiveGraph gives a very neat solution with:
* GUI and immediate display of data by just pointing at .dat or .csv file
* immediate and easy tweaking of graph
* LIVE graph plotting
* Export graph to image using GUI
* Very nice generic automatic figure-format-out LiveGraph .csv/.dat file format
And hopefully, I think I did it before: * multiple sources of data on one plot
This script, log2csv.pl allows any textual log file with data in it to be fed to LiveGraph. So maybe I never have to write another data parsing + plotting script ever again! :)
log2csv takes:
* output .csv file name
* input log file name
* pairs of data name and regexp to grep out data value from log
Run it on windows using cygwin (tail -f needed).
Here is the script:
#!/usr/bin/perl -w
=head1 NAME
log2csv.pl - process test log files, generate .csv file for LiveGraph
=head1 USAGE
=cut
my $usage = <
log2csv.pl [ ..]
e.g.
log2csv.pl testdata_22Feb_xx.csv /cygdrive/m/TclTestManager/Logs/TestRun_22Feb_*/*.log \\
D0 'WSS.*D00,PORT.*=\\s*(\\d+)\\b' D1 'WSS.*D01,PORT.*=\\s*(\\d+)\\b' \\
PD_A 'PD:pd_a power:([-]*\\d+[\\.]*\\d*)\\b' \\
PD_O 'PD:pd_o1a power:([-]*\\d+[\\.]*\\d*)\\b' \\
PD_D1 'PD_D1:([-]*\\d+[\\.]*\\d*)\\b' \\
PD_D2 'PD_D2:([-]*\\d+[\\.]*\\d*)\\b'
END
=head1 SYNOPSIS
e.g. parse this:
$ bash ./monitor_log.sh
log::logarray:aWSSinfo0(D00,ATTN) = 7.0
log::logarray:aWSSinfo0(D00,PORT) = 0
log::logarray:aWSSinfo0(D01,ATTN) = 7.0
log::logarray:aWSSinfo0(D01,PORT) = 1
MONITOR: WSS configured and check okay. D00 att:7.0 port:0 D01 att:7.0 port:1
MONITOR loop state:lock PD:pd_a power:-15.99 target:-16.00
TESTSTEP: FAIL fPDVal:-1.26 check PD_D1:-1.26 is about 7dBm, thresh:3 target:7 delta:8.26 thresh:3
TESTSTEP: FAIL fPDVal:-1.26 check PD_D2:-1.90 is about 7dBm, thresh:3 target:7 delta:8.26 thresh:3
MONITOR: OFSM processes check PASS
MONITOR PING test TX:1 RX:1 result:PASS
TODO: parse this:
TESTSTEP: FAIL waitForOlcControlState bResult=FAIL iTestTime=213 match(1,2):(0,0) check1:state:\s+lock\y
MONITOR: WSS init try:1
TODO: get time at every monitor loop, plot that, then can see when disconnected/waiting.
Test Start Thu Feb 18 13:17:32 GMT Standard Time 2010
=head1 DESCRIPTION
=head1 DESIGN/NOTES
Started with testreport.pl
tail /cygdrive/m/TclTestManager/Demo/DemoFeb2010/ofso_demo.log
tail /cygdrive/m/TclTestManager/Demo/DemoFeb2010/monitor_log.sh
=cut
sub openCSV {
my $outfile=shift;
my $refDetails=shift;
# open file, create and write header
# overwrite or append to outfile? overwrite.
( open( OUTFILE, ">$outfile" )) || die "file err: Can't open $outfile for write: $!";
# write header
my $bWriteComma = 0;
for my $ds ( @$refDetails ) {
#print "write var $ds->{var} val $ds->{val} regexp $ds->{regexp}\n";
($bWriteComma == 1) && print OUTFILE ", ";
if (defined($ds->{var})) { print OUTFILE "$ds->{var}"; }
$bWriteComma = 1;
}
print OUTFILE "\n";
close OUTFILE;
}
sub writeCSV {
my $outfile=shift;
my $refDetails=shift;
# open file, append
( open( OUTFILE, ">>$outfile" )) || die "file err: Can't open $outfile for append: $!";
# write data
my $bWriteComma = 0;
for my $ds ( @$refDetails ) {
#print "write var $ds->{var} val $ds->{val} regexp $ds->{regexp}\n";
($bWriteComma == 1) && print OUTFILE ", ";
if (defined($ds->{val})) { print OUTFILE "$ds->{val}"; }
$bWriteComma = 1;
}
print OUTFILE "\n";
close OUTFILE;
}
# TODO user passes in filename [optional outfile] [optional regexp/list of famille to take]
my $c = $#ARGV + 1;
print "ARGC=$c\n";
foreach my $i (0 .. $#ARGV) {
print "arg ARGV[$i]=$ARGV[$i]\n";
}
(defined $ARGV[0]) || die "args err: no outfile specified. \n$usage";
my $outfile = shift;
(defined $ARGV[0]) || die "args err: no infile specified. \n$usage";
my @infiles;
my $infilecount = 0;
while (defined($ARGV[0]) && -e $ARGV[0]) {
$infiles[$infilecount++] = shift;
print "args infile $infilecount is $infiles[$infilecount-1]\n";
}
($infilecount>0) || die "args err: no infile found. \n$usage";
my @data_spec;
my $data_spec_count = 0;
while (defined $ARGV[0]) {
# TODO: if match ^- option parse
# pair of data and regexp
(defined $ARGV[1]) || die "err: pair of data and regexp expected. \n$usage";
my $ds = {};
$ds->{var} = shift;
$ds->{regexp} = shift;
# mark first regexp as the one to trigger a write of values (e.g. 1st regexp is timestamp)
if ($data_spec_count == 0) { $ds->{write} = 1; }
push @data_spec, $ds;
$data_spec_count++;
print "data spec $data_spec_count is $data_spec[$data_spec_count-1]->{var} and $data_spec[$data_spec_count-1]->{regexp}\n";
#print "data spec 0 is $data_spec[0]->{var} and $data_spec[0]->{regexp}\n";
}
&openCSV ($outfile,\@data_spec);
#use File::Tail;
#my $file=File::Tail->new($infiles[0]);
#while (defined(my $line=$file->read)) {
# print "$line";
#}
open(INFILE, '-|', "tail -f $infiles[0]") or die "file err: Can't open $infiles[0]: $!";
my $lastline = "";
while () {
my $line=$_;
while (defined($_) && $line ne $lastline) {
#print "line: $_";
$lastline = $line;
for my $ds ( @data_spec ) {
#print "grep var $ds->{var} regexp $ds->{regexp}\n";
$_ = $line;
if (my ($val) = ($line =~ m/$ds->{regexp}/ ) ) {
print "GROPPED var $ds->{var} regexp $ds->{regexp} val $val\n";
# store value
$ds->{val} = $val;
# write out values when we get match on first regexp ...
if (defined($ds->{write})) {
print "GRO write\n";
&writeCSV ($outfile,\@data_spec);
}
last; # next; #break; continue;
}
}
}
}
return;
* GUI and immediate display of data by just pointing at .dat or .csv file
* immediate and easy tweaking of graph
* LIVE graph plotting
* Export graph to image using GUI
* Very nice generic automatic figure-format-out LiveGraph .csv/.dat file format
And hopefully, I think I did it before: * multiple sources of data on one plot
This script, log2csv.pl allows any textual log file with data in it to be fed to LiveGraph. So maybe I never have to write another data parsing + plotting script ever again! :)
log2csv takes:
* output .csv file name
* input log file name
* pairs of data name and regexp to grep out data value from log
#e.g.
log2csv.pl testdata.csv some.log \
D0 'WSS.*D00,PORT.*=\s*(\d+)\b' D1 'WSS.*D01,PORT.*=\s*(\d+)\b' \
PD_A 'PD:pd_a power:([-]*\d+[\.]*\d*)\b' \
PD_O 'PD:pd_o1a power:([-]*\d+[\.]*\d*)\b' \
PD_D1 'PD_D1:([-]*\d+[\.]*\d*)\b' \
PD_D2 'PD_D2:([-]*\d+[\.]*\d*)\b'
log2csv.pl testdata.csv some.log \
D0 'WSS.*D00,PORT.*=\s*(\d+)\b' D1 'WSS.*D01,PORT.*=\s*(\d+)\b' \
PD_A 'PD:pd_a power:([-]*\d+[\.]*\d*)\b' \
PD_O 'PD:pd_o1a power:([-]*\d+[\.]*\d*)\b' \
PD_D1 'PD_D1:([-]*\d+[\.]*\d*)\b' \
PD_D2 'PD_D2:([-]*\d+[\.]*\d*)\b'
Run it on windows using cygwin (tail -f needed).
Here is the script:
#!/usr/bin/perl -w
=head1 NAME
log2csv.pl - process test log files, generate .csv file for LiveGraph
=head1 USAGE
=cut
my $usage = <
log2csv.pl [ ..]
e.g.
log2csv.pl testdata_22Feb_xx.csv /cygdrive/m/TclTestManager/Logs/TestRun_22Feb_*/*.log \\
D0 'WSS.*D00,PORT.*=\\s*(\\d+)\\b' D1 'WSS.*D01,PORT.*=\\s*(\\d+)\\b' \\
PD_A 'PD:pd_a power:([-]*\\d+[\\.]*\\d*)\\b' \\
PD_O 'PD:pd_o1a power:([-]*\\d+[\\.]*\\d*)\\b' \\
PD_D1 'PD_D1:([-]*\\d+[\\.]*\\d*)\\b' \\
PD_D2 'PD_D2:([-]*\\d+[\\.]*\\d*)\\b'
END
=head1 SYNOPSIS
e.g. parse this:
$ bash ./monitor_log.sh
log::logarray:aWSSinfo0(D00,ATTN) = 7.0
log::logarray:aWSSinfo0(D00,PORT) = 0
log::logarray:aWSSinfo0(D01,ATTN) = 7.0
log::logarray:aWSSinfo0(D01,PORT) = 1
MONITOR: WSS configured and check okay. D00 att:7.0 port:0 D01 att:7.0 port:1
MONITOR loop state:lock PD:pd_a power:-15.99 target:-16.00
TESTSTEP: FAIL fPDVal:-1.26 check PD_D1:-1.26 is about 7dBm, thresh:3 target:7 delta:8.26 thresh:3
TESTSTEP: FAIL fPDVal:-1.26 check PD_D2:-1.90 is about 7dBm, thresh:3 target:7 delta:8.26 thresh:3
MONITOR: OFSM processes check PASS
MONITOR PING test TX:1 RX:1 result:PASS
TODO: parse this:
TESTSTEP: FAIL waitForOlcControlState bResult=FAIL iTestTime=213 match(1,2):(0,0) check1:state:\s+lock\y
MONITOR: WSS init try:1
TODO: get time at every monitor loop, plot that, then can see when disconnected/waiting.
Test Start Thu Feb 18 13:17:32 GMT Standard Time 2010
=head1 DESCRIPTION
=head1 DESIGN/NOTES
Started with testreport.pl
tail /cygdrive/m/TclTestManager/Demo/DemoFeb2010/ofso_demo.log
tail /cygdrive/m/TclTestManager/Demo/DemoFeb2010/monitor_log.sh
=cut
sub openCSV {
my $outfile=shift;
my $refDetails=shift;
# open file, create and write header
# overwrite or append to outfile? overwrite.
( open( OUTFILE, ">$outfile" )) || die "file err: Can't open $outfile for write: $!";
# write header
my $bWriteComma = 0;
for my $ds ( @$refDetails ) {
#print "write var $ds->{var} val $ds->{val} regexp $ds->{regexp}\n";
($bWriteComma == 1) && print OUTFILE ", ";
if (defined($ds->{var})) { print OUTFILE "$ds->{var}"; }
$bWriteComma = 1;
}
print OUTFILE "\n";
close OUTFILE;
}
sub writeCSV {
my $outfile=shift;
my $refDetails=shift;
# open file, append
( open( OUTFILE, ">>$outfile" )) || die "file err: Can't open $outfile for append: $!";
# write data
my $bWriteComma = 0;
for my $ds ( @$refDetails ) {
#print "write var $ds->{var} val $ds->{val} regexp $ds->{regexp}\n";
($bWriteComma == 1) && print OUTFILE ", ";
if (defined($ds->{val})) { print OUTFILE "$ds->{val}"; }
$bWriteComma = 1;
}
print OUTFILE "\n";
close OUTFILE;
}
# TODO user passes in filename [optional outfile] [optional regexp/list of famille to take]
my $c = $#ARGV + 1;
print "ARGC=$c\n";
foreach my $i (0 .. $#ARGV) {
print "arg ARGV[$i]=$ARGV[$i]\n";
}
(defined $ARGV[0]) || die "args err: no outfile specified. \n$usage";
my $outfile = shift;
(defined $ARGV[0]) || die "args err: no infile specified. \n$usage";
my @infiles;
my $infilecount = 0;
while (defined($ARGV[0]) && -e $ARGV[0]) {
$infiles[$infilecount++] = shift;
print "args infile $infilecount is $infiles[$infilecount-1]\n";
}
($infilecount>0) || die "args err: no infile found. \n$usage";
my @data_spec;
my $data_spec_count = 0;
while (defined $ARGV[0]) {
# TODO: if match ^- option parse
# pair of data and regexp
(defined $ARGV[1]) || die "err: pair of data and regexp expected. \n$usage";
my $ds = {};
$ds->{var} = shift;
$ds->{regexp} = shift;
# mark first regexp as the one to trigger a write of values (e.g. 1st regexp is timestamp)
if ($data_spec_count == 0) { $ds->{write} = 1; }
push @data_spec, $ds;
$data_spec_count++;
print "data spec $data_spec_count is $data_spec[$data_spec_count-1]->{var} and $data_spec[$data_spec_count-1]->{regexp}\n";
#print "data spec 0 is $data_spec[0]->{var} and $data_spec[0]->{regexp}\n";
}
&openCSV ($outfile,\@data_spec);
#use File::Tail;
#my $file=File::Tail->new($infiles[0]);
#while (defined(my $line=$file->read)) {
# print "$line";
#}
open(INFILE, '-|', "tail -f $infiles[0]") or die "file err: Can't open $infiles[0]: $!";
my $lastline = "";
while () {
my $line=$_;
while (defined($_) && $line ne $lastline) {
#print "line: $_";
$lastline = $line;
for my $ds ( @data_spec ) {
#print "grep var $ds->{var} regexp $ds->{regexp}\n";
$_ = $line;
if (my ($val) = ($line =~ m/$ds->{regexp}/ ) ) {
print "GROPPED var $ds->{var} regexp $ds->{regexp} val $val\n";
# store value
$ds->{val} = $val;
# write out values when we get match on first regexp ...
if (defined($ds->{write})) {
print "GRO write\n";
&writeCSV ($outfile,\@data_spec);
}
last; # next; #break; continue;
}
}
}
}
return;
Tuesday, 23 February 2010
Questions about tcl for job interviews, thoughts on tcl quirks
Tricky question. "What is a simple question and answer that would give us confidence that they knew TCL?"
Try and set up interview so your candidate can write code. You can’t determine it with one question I think but you can if you get them to write a function. Incidentally The Gureilla Guide to Interviewing by Joel Spolsky FogCreek is very good on technical/software interviews.
One question might be what kinds of different data types are available by default in tcl?
Answer1: in tcl, “everything is a string” (but lots of people who know tcl mightn’t get this!)
Answer2: There is default support for list and array. And normal var types would be considered integers/floats/strings.
“everything is a string” means there is no type protection
Data types are supported by the way they are treated in procedures.
Write a procedure (that would require a while or for loop) to calculate something.
Show how this can be called and print the answer.
e.g. calculate the sum of a list
# my answer
proc calc_sum_of_list { list } {
set sum 0
foreach a $list {
# OR if you're a real tcler here use: incr sum $a
set sum [expr $sum + $a]
}
return $sum
}
# how this is called
set mList [list 1 2 3 4]
puts “sum of list result: [calc_sum_of_list $mList]”
# OR
set mList [list 1 2 3 4]
set result [calc_sum_of_list $mList]
puts “sum of list result: $result”
Simpler questions:
How do you set a variable?
Answer: set a 40
How do you increment an integer variable?
Answer: incr a
How do you decrement?
Answer: incr a -1
How to you print a variable?
Answer: puts $a
OR puts “a is $a”
OR puts [format “a is %d = 0x%08x, string %s” $a $a “string”]
OR ...
A fundamental tcl question: Are spaces needed in tcl in for/while/if loops?
Answer: YES tcl has a couple of really awkward quirks.
e.g. valid tcl:
set a 20
if {$a > 4} {
puts “$a is bigger than 4”
}
Invalid:
set a 20
if{$a > 4} {
puts “$a is bigger than 4”
}
invalid command name "if{20"
Invalid:
set a 20
if {$a > 4}
{
puts “$a is bigger than 4”
}
wrong # args: no script following "{$a > 4}" argument
invalid command name "
puts "$a is bigger than 4"
"
Another fundamental question: In tcl what brackets in comments might cause problems (especially if they’re not balanced in comments)?
Answer: Curley brackets {} cause problems. parenthesis () or square [] or anything else don’t cause problems in comments.
Pure and even very impure software people who haven't encountered tcl before have probably already WTFed several times and swooned away by now. Must be because tcl syntax was defined by one of those hardware people! :-P i.e. Possibly a very practical person who has made a very gluey language with a few glaring hairy things remaining in the syntax (possibly on purpose to scare/annoy computer science philosophers).
Please excuse me hardware and software people alike :)
Tcl language syntax overview
Why is tcl syntax so weird?on wiki.tcl.tk
syntax related pages on wiki.tcl.tk
Ousterhout
John Ousterhout on tcl history
wikipedia.org:Tcl
Try and set up interview so your candidate can write code. You can’t determine it with one question I think but you can if you get them to write a function. Incidentally The Gureilla Guide to Interviewing by Joel Spolsky FogCreek is very good on technical/software interviews.
One question might be what kinds of different data types are available by default in tcl?
Answer1: in tcl, “everything is a string” (but lots of people who know tcl mightn’t get this!)
Answer2: There is default support for list and array. And normal var types would be considered integers/floats/strings.
“everything is a string” means there is no type protection
Data types are supported by the way they are treated in procedures.
Write a procedure (that would require a while or for loop) to calculate something.
Show how this can be called and print the answer.
e.g. calculate the sum of a list
# my answer
proc calc_sum_of_list { list } {
set sum 0
foreach a $list {
# OR if you're a real tcler here use: incr sum $a
set sum [expr $sum + $a]
}
return $sum
}
# how this is called
set mList [list 1 2 3 4]
puts “sum of list result: [calc_sum_of_list $mList]”
# OR
set mList [list 1 2 3 4]
set result [calc_sum_of_list $mList]
puts “sum of list result: $result”
Simpler questions:
How do you set a variable?
Answer: set a 40
How do you increment an integer variable?
Answer: incr a
How do you decrement?
Answer: incr a -1
How to you print a variable?
Answer: puts $a
OR puts “a is $a”
OR puts [format “a is %d = 0x%08x, string %s” $a $a “string”]
OR ...
A fundamental tcl question: Are spaces needed in tcl in for/while/if loops?
Answer: YES tcl has a couple of really awkward quirks.
e.g. valid tcl:
set a 20
if {$a > 4} {
puts “$a is bigger than 4”
}
Invalid:
set a 20
if{$a > 4} {
puts “$a is bigger than 4”
}
invalid command name "if{20"
Invalid:
set a 20
if {$a > 4}
{
puts “$a is bigger than 4”
}
wrong # args: no script following "{$a > 4}" argument
invalid command name "
puts "$a is bigger than 4"
"
Another fundamental question: In tcl what brackets in comments might cause problems (especially if they’re not balanced in comments)?
Answer: Curley brackets {} cause problems. parenthesis () or square [] or anything else don’t cause problems in comments.
Pure and even very impure software people who haven't encountered tcl before have probably already WTFed several times and swooned away by now. Must be because tcl syntax was defined by one of those hardware people! :-P i.e. Possibly a very practical person who has made a very gluey language with a few glaring hairy things remaining in the syntax (possibly on purpose to scare/annoy computer science philosophers).
Please excuse me hardware and software people alike :)
Tcl language syntax overview
Why is tcl syntax so weird?on wiki.tcl.tk
syntax related pages on wiki.tcl.tk
Ousterhout
John Ousterhout on tcl history
wikipedia.org:Tcl
Labels:
computer science,
interview,
job,
scripting,
software,
syntax,
tcl,
tcl quirks
Wednesday, 17 February 2010
bash shell logrotate function
# Yet Another installation in the Yet Another script to do whatever series
# I have done logrotate in bash in at least two other flavours before. :-7
# bash shell logrotate function
function logroti () {
for f in $* ; do
echo logroti for f
if [ -e "$f" ] ; then
ROTFILES=$(find $f.[0-9] 2>/dev/null| sort -r )
for rf in $ROTFILES; do
BASE=${rf%.*}
NUM=${rf##$BASE.}
((NUM++))
echo logroti for rf=$rf BASE=$BASE NUM=$NUM new file $BASE.$NUM
mv -f $rf $BASE.$NUM
done
cp -f $f $f.0
cat /dev/null > $f
fi
done
}
# e.g. usage
logroti run_demo.log
while [ 1 ]; do
logrotate demo.log 2>&1 |tee -a run_demo.log
date |tee -a run_demo.log
echo "DEMO script start" |tee -a run_demo.log
tclsh RunDemo.tcl 2>&1 |tee demo.log
date |tee -a run_demo.log
echo "DEMO script exited" |tee -a run_demo.log
done
# the tcl script internally at top level has a catch {...} sError
# but some errors get past this! :)
# So am catching everything and can see how long things run for and what errors cause any problems
# I have done logrotate in bash in at least two other flavours before. :-7
# bash shell logrotate function
function logroti () {
for f in $* ; do
echo logroti for f
if [ -e "$f" ] ; then
ROTFILES=$(find $f.[0-9] 2>/dev/null| sort -r )
for rf in $ROTFILES; do
BASE=${rf%.*}
NUM=${rf##$BASE.}
((NUM++))
echo logroti for rf=$rf BASE=$BASE NUM=$NUM new file $BASE.$NUM
mv -f $rf $BASE.$NUM
done
cp -f $f $f.0
cat /dev/null > $f
fi
done
}
# e.g. usage
logroti run_demo.log
while [ 1 ]; do
logrotate demo.log 2>&1 |tee -a run_demo.log
date |tee -a run_demo.log
echo "DEMO script start" |tee -a run_demo.log
tclsh RunDemo.tcl 2>&1 |tee demo.log
date |tee -a run_demo.log
echo "DEMO script exited" |tee -a run_demo.log
done
# the tcl script internally at top level has a catch {...} sError
# but some errors get past this! :)
# So am catching everything and can see how long things run for and what errors cause any problems
Subscribe to:
Posts (Atom)