From jhannah at omnihotels.com Mon Oct 8 13:37:13 2007 From: jhannah at omnihotels.com (Jay Hannah) Date: Mon, 8 Oct 2007 15:37:13 -0500 Subject: [Omaha.pm] Whacking Makefile's Message-ID: Task: mod_perl has 27 Makefile's in its source tree. Remove -mtune=i686 from all of them. Solution: find ./ -name "Makefile" | xargs perl -pi -e 's/ -mtune=i686//' I'm sure there's a more elegant solution to catch that optimizer argument upstream, but my first stab didn't work so I punted. Alternate (untested): perl -pi -e 's/ -mtune=i686//' `find ./ -name "Makefile"` j -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.pm.org/pipermail/omaha-pm/attachments/20071008/1db48542/attachment.html From jay at jays.net Tue Oct 9 13:58:43 2007 From: jay at jays.net (Jay Hannah) Date: Tue, 09 Oct 2007 15:58:43 -0500 Subject: [Omaha.pm] /^\s+(.*)/ && do { } Message-ID: <470BEB83.60702@jays.net> Huh. I'm not sure if I like this or not, but it sure is tight. The basic idea is given a file format like this where there are an unknown number of ACCESSION entries on an unknown number of lines: LOCUS BA000036 3309401 bp DNA circular BCT 19-MAY-2007 DEFINITION Corynebacterium glutamicum ATCC 13032 DNA, complete genome. ACCESSION BA000036 AP005274 AP005275 AP005276 AP005277 AP005278 AP005279 AP005280 AP005281 AP005282 AP005283 VERSION BA000036.3 GI:42602314 PROJECT GenomeProject:307 While reading through the file keep pushing only your array until /^\s+(.*)/ fails. At that point 'last'. if( /^ACCESSION\s+(\S.*\S)/ ) { push(@acc, split(/\s+/,$1)); while( defined($_ = $self->_readline) ) { /^\s+(.*)/ && do { push (@acc, split(/\s+/,$1)); next }; last; } $buffer = $_; next; } I don't remember seeing a ' && do {} ' construct before... And I'm confused by $buffer, but that's a different battle. :) j Full source: http://code.open-bio.org/cgi/viewcvs.cgi/bioperl-live/Bio/SeqIO/genbank.pm?rev=1.167&cvsroot=bioperl&content-type=text/vnd.viewcvs-markup From jay at jays.net Tue Oct 9 14:01:52 2007 From: jay at jays.net (Jay Hannah) Date: Tue, 09 Oct 2007 16:01:52 -0500 Subject: [Omaha.pm] /^\s+(.*)/ && do { } In-Reply-To: <470BEB83.60702@jays.net> References: <470BEB83.60702@jays.net> Message-ID: <470BEC40.5080302@jays.net> Jay Hannah wrote: > While reading through the file keep pushing only your array until > Oops. I meant "onto your array". Sorry, j From jay at jays.net Thu Oct 11 15:24:58 2007 From: jay at jays.net (Jay Hannah) Date: Thu, 11 Oct 2007 17:24:58 -0500 Subject: [Omaha.pm] Fwd: [Kc] Need second look at this... References: Message-ID: <9A8BA470-BFD8-4092-A3FE-BA5110CF10E0@jays.net> Sweet. Garrett whipped out the zero width negative look behind assertion. That's my favorite. Yes, seriously. :) j Begin forwarded message: > From: Garrett Goebel > Date: October 11, 2007 3:40:17 PM CDT > To: Emmanuel Mejias > Cc: kcpm > Subject: Re: [Kc] Need second look at this... > > In order to fix your regex you'll need to tell us the difference > between somehostpm1 and dr-somehostpm1. > > Will a "good" somehostpm1 never be preceeded by 'dr-'? If so... > > # Shot at adhering to Perl Best Practices > open my($file), '<', '/etc/hosts'; > while (my $line = <$file>) { > if ($line =~ /(? print $line; > } > } > > # Quick'n Dirty > open FILE, ' map { print if /(?; > > I haven't tested it... perhaps it'll work. > > (? it'll match anything that isn't preceeded by the pattern without > including it in the match. > > Garrett > > On Oct 11, 2007, at 2:44 PM, Emmanuel Mejias wrote: > >> trying to grep out some info from my /etc/hosts file...just to get >> more practice with Perl and well for my personal pleasure, too. >> >> #!/usr/bin/perl >> >> open (FILE, "/etc/hosts"); >> @lines = ; >> close (FILE); >> >> foreach $line (@lines){ >> if ($line =~ /pm1/){ >> print $line; >> } >> } >> >> the problem with this is that it's printing out some hosts that i >> don't want that also have pm1 at the end. >> >> somehostpm1 but it also gets my dr hosts (dr-somehostpm1) >> >> thoughts? >> >> by the way, i had to jump the wifes car so i ended up missing out >> on the meeting. gonna try to make the next one for sure, though. >> >> _______________________________________________ >> kc mailing list >> kc at pm.org >> http://mail.pm.org/mailman/listinfo/kc > > _______________________________________________ > kc mailing list > kc at pm.org > http://mail.pm.org/mailman/listinfo/kc From jay at jays.net Mon Oct 15 17:58:52 2007 From: jay at jays.net (Jay Hannah) Date: Mon, 15 Oct 2007 20:58:52 -0400 (EDT) Subject: [Omaha.pm] CGI.pm is your friend Message-ID: Another quick code refactor... Before: print "\n\n\n"; After: use CGI; my $q = new CGI; print $q->popup_menu(-name=>'month', -values=>[undef, 1..12]); print $q->popup_menu(-name=>'day', -values=>[undef, 1..31]); print $q->popup_menu(-name=>'year', -values=>[undef, $year-1, $year, $year+1, $year+2 ]); Or that last one using map: print $q->popup_menu(-name=>'year', -values=>[undef, map { $year + $_ } -1..2 ]); Plus when you use CGI your form fields are automatically sticky, which can save your users lots of "Back button" frustration. :) j ...gonna be the only poster in Oct? -fingers crossed- -laugh- From jay at jays.net Mon Oct 15 18:14:59 2007 From: jay at jays.net (Jay Hannah) Date: Mon, 15 Oct 2007 21:14:59 -0400 (EDT) Subject: [Omaha.pm] CGI.pm is your friend In-Reply-To: References: Message-ID: On Mon, 15 Oct 2007, Jay Hannah wrote: > print $q->popup_menu(-name=>'month', -values=>[undef, 1..12]); > print $q->popup_menu(-name=>'day', -values=>[undef, 1..31]); > print $q->popup_menu(-name=>'year', -values=>[undef, $year-1, $year, $year+1, $year+2 ]); Oops! I dropped the tabindex's from the original. Should have been: print $q->popup_menu(-name=>'month', -tabindex=>1, -values=>[undef, 1..12]); print $q->popup_menu(-name=>'day', -tabindex=>2, -values=>[undef, 1..31]); print $q->popup_menu(-name=>'year', -tabindex=>3, -values=>[undef, $year-1, $year, $year+1, $year+2 ]); Apologies. :) j From dan at linder.org Mon Oct 15 19:05:02 2007 From: dan at linder.org (Daniel Linder) Date: Mon, 15 Oct 2007 21:05:02 -0500 (CDT) Subject: [Omaha.pm] CGI.pm is your friend In-Reply-To: References: Message-ID: <4839.70.165.110.36.1192500302.squirrel@webmail.linder.org> On Mon, October 15, 2007 20:14, Jay Hannah wrote: > print $q->popup_menu(-name=>'month', -tabindex=>1, -values=>[undef, 1..12]); So, if I read this right, the 'magic' happens because of the []'s, right? Does this end up calling the "popup_menu" function 13 times (undef, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, and 12)? Or does the [] do other stuff when called inside that function? Dan (Just an old functional programmer trying to wrap his head around the object-oriented programming paradigm...) - - - - "There are four boxes to be used in defense of liberty: soap, ballot, jury, and ammo. Please use in that order." -- Ed Howdershelt (Author) "I do not fear computers, I fear the lack of them." -- Isaac Asimov (Author) ** *** ***** ******* *********** ************* USCG, Information Warfare, Competitor, IDEA, NTT, USP, VHF SLI, RSA, Spoke, 1080H, LUK, SSL, SDI S.A.I.C., FINCEN, Police, Event Security, TDR, CIDA, Mayfly From jay at jays.net Mon Oct 15 19:26:40 2007 From: jay at jays.net (Jay Hannah) Date: Mon, 15 Oct 2007 21:26:40 -0500 Subject: [Omaha.pm] CGI.pm is your friend In-Reply-To: <4839.70.165.110.36.1192500302.squirrel@webmail.linder.org> References: <4839.70.165.110.36.1192500302.squirrel@webmail.linder.org> Message-ID: On Oct 15, 2007, at 9:05 PM, Daniel Linder wrote: >> print $q->popup_menu(-name=>'month', -values=>[undef, 1..12]); > > So, if I read this right, the 'magic' happens because of the []'s, > right? Not sure if any of it's magic, it's just tighter code than writing your own loops to generate HTML. > Does this end up calling the "popup_menu" function 13 times (undef, > 1, 2, > 3, 4, 5, 6, 7, 8, 9, 10, 11, and 12)? Or does the [] do other > stuff when > called inside that function? popup_menu() is only called one time. It is handed an anonymous hash with two keys ("name" and "values"). The value of the "values" key is an anonymous array with the elements you listed in it. Did that answer your question? Nothing magical, just a hash with an array in it. If you don't do any web programming, this web stuff is pretty obtuse. But when generating gobs of HTML it's nice to call popup_menu() instead of having to do your own ugly looping. http://search.cpan.org/~lds/CGI.pm-3.29/CGI.pm#CREATING_A_POPUP_MENU $ cat j.pl use CGI; my $q = new CGI; print $q->popup_menu(-name=>'month', -values=>[undef, 1..12]); $ perl j.pl > Dan > > (Just an old functional programmer trying to wrap his head around the > object-oriented programming paradigm...) Join the club. I'll print up some t-shirts. :) j From dan at linder.org Tue Oct 16 10:03:27 2007 From: dan at linder.org (Daniel Linder) Date: Tue, 16 Oct 2007 12:03:27 -0500 (CDT) Subject: [Omaha.pm] CGI.pm is your friend In-Reply-To: References: <4839.70.165.110.36.1192500302.squirrel@webmail.linder.org> Message-ID: <59831.63.230.40.25.1192554207.squirrel@webmail.linder.org> On Mon, October 15, 2007 21:26, Jay Hannah wrote: > popup_menu() is only called one time. It is handed an anonymous hash > with two keys ("name" and "values"). The value of the "values" key is > an anonymous array with the elements you listed in it. > > Did that answer your question? Nothing magical, just a hash with an > array in it. Gotcha. The actual popup_menu() function expands the hash itself. I was thinking this was some sort of "OO-magic" being performed by the Perl interpreter auto-magically calling the function multiple times with the new values. Dan - - - - "There are four boxes to be used in defense of liberty: soap, ballot, jury, and ammo. Please use in that order." -- Ed Howdershelt (Author) "I do not fear computers, I fear the lack of them." -- Isaac Asimov (Author) ** *** ***** ******* *********** ************* Clandestine, Glock, Scully, Artichoke, SHF, virus, POCSAG orthodox, SABC, MSNBC, Rapid Reaction, DITSA, CCS, AVN BITNET, Secure, Compsec 97, Fax, EADA, B.D.M.,Sphinx, TRW From jay at jays.net Tue Oct 16 11:21:48 2007 From: jay at jays.net (Jay Hannah) Date: Tue, 16 Oct 2007 13:21:48 -0500 Subject: [Omaha.pm] CGI.pm is your friend In-Reply-To: <59831.63.230.40.25.1192554207.squirrel@webmail.linder.org> References: <4839.70.165.110.36.1192500302.squirrel@webmail.linder.org> <59831.63.230.40.25.1192554207.squirrel@webmail.linder.org> Message-ID: <4715013C.9040906@jays.net> Daniel Linder wrote: > Gotcha. The actual popup_menu() function expands the hash itself. I think that's almost right. Subroutines always receive and return "a single, flat list of scalars." So the sub doesn't receive a hash. The hash I pass in is flattened into a list of scalars. Inside your sub you often shove that list into a different, local hash. In our example the sub receives 4 scalars. The fourth (or second, randomly) happens to be an array reference. $ cat j.pl #!/usr/bin/perl use Data::Dumper; do_something(-arg1 => 'val1', -arg2 => [ 5,6,7 ]); sub do_something { my (%args) = @_; print Dumper(%args); } $ perl j.pl $VAR1 = '-arg2'; $VAR2 = [ 5, 6, 7 ]; $VAR3 = '-arg1'; $VAR4 = 'val1'; Or, we can look at it in the debugger (which I strongly prefer): $ perl -d j.pl ... DB<2> x %args 0 '-arg2' 1 ARRAY(0x99faa00) 0 5 1 6 2 7 2 '-arg1' 3 'val1' Hopefully that helps. Perhaps the idea of throwing a hash into a list and then putting that list into a new hash is confusing... The key/value pairs always stay together, which is the only important thing in hashes. > I was thinking this was some sort of "OO-magic" being performed by the Perl > interpreter auto-magically calling the function multiple times with the > new values. Nope. Definitely not that. :) j From jay at jays.net Tue Oct 16 14:00:24 2007 From: jay at jays.net (Jay Hannah) Date: Tue, 16 Oct 2007 17:00:24 -0400 (EDT) Subject: [Omaha.pm] print "%hash"; Message-ID: I hit this code today $body .= "Email Address: ".$$results{email}."%0D%0A" if ($$results{email}); and thought "What? Isn't Perl going to try to interpret "%0D" as a hash? Nope. "%hash" is not interpreted at all. It's just a string. Fun with hashes below... j $ cat j.pl my %j = ( a => 1, b => 2 ); print %j, "\n"; print %j . "\n"; print "%j\n"; $ perl j.pl a1b2 2/8 %j perldoc perldata If you evaluate a hash in scalar context, it returns false if the hash is empty. If there are any key/value pairs, it returns true; more precisely, the value returned is a string consisting of the number of used buckets and the number of allocated buckets, separated by a slash. This is pretty much useful only to find out whether Perl's internal hashing algorithm is performing poorly on your data set. For example, you stick 10,000 things in a hash, but evaluating %HASH in scalar context reveals "1/16", which means only one out of sixteen buckets has been touched, and presumably contains all 10,000 of your items. This isn't supposed to happen. From travis at travisbsd.org Tue Oct 16 15:55:26 2007 From: travis at travisbsd.org (Travis McArthur) Date: Tue, 16 Oct 2007 17:55:26 -0500 Subject: [Omaha.pm] print "%hash"; In-Reply-To: References: Message-ID: <4715415E.3030006@travisbsd.org> Jay Hannah wrote: > I hit this code today > > $body .= "Email Address: ".$$results{email}."%0D%0A" if ($$results{email}); > > and thought "What? Isn't Perl going to try to interpret "%0D" as a hash? > > Nope. > > "%hash" is not interpreted at all. It's just a string. > > Fun with hashes below... > > j > > > $ cat j.pl > my %j = ( a => 1, b => 2 ); > print %j, "\n"; > print %j . "\n"; > print "%j\n"; > > $ perl j.pl > a1b2 > 2/8 > %j > > > perldoc perldata > If you evaluate a hash in scalar context, it returns false > if the hash is empty. If there are any key/value pairs, > it returns true; more precisely, the value returned is a > string consisting of the number of used buckets and the > number of allocated buckets, separated by a slash. This > is pretty much useful only to find out whether Perl's > internal hashing algorithm is performing poorly on your > data set. For example, you stick 10,000 things in a hash, > but evaluating %HASH in scalar context reveals "1/16", > which means only one out of sixteen buckets has been > touched, and presumably contains all 10,000 of your items. > This isn't supposed to happen. > > _______________________________________________ > Omaha-pm mailing list > Omaha-pm at pm.org > http://mail.pm.org/mailman/listinfo/omaha-pm > > That's rather unusual but very useful, I don't know any other language that has built in hashing functionality to have that sort of instrumentation (regarding allocated buckets versus full buckets). I never knew that! Awesome stuff, I like how Perl pretty intelligently guesses what you want to know, which is nice. Thanks for bringing this up Jay. Best Regards, Travis From andy at petdance.com Tue Oct 16 15:59:24 2007 From: andy at petdance.com (Andy Lester) Date: Tue, 16 Oct 2007 17:59:24 -0500 Subject: [Omaha.pm] print "%hash"; In-Reply-To: <4715415E.3030006@travisbsd.org> References: <4715415E.3030006@travisbsd.org> Message-ID: <533B403B-2F33-453A-854F-CC31E9F2E8A4@petdance.com> On Oct 16, 2007, at 5:55 PM, Travis McArthur wrote: > That's rather unusual but very useful, I don't know any other language > that has built in hashing functionality to have that sort of > instrumentation (regarding allocated buckets versus full buckets). I > never knew that! Awesome stuff, I like how Perl pretty intelligently > guesses what you want to know, which is nice. Thanks for bringing > this > up Jay. It also comes back as a plain zero if no buckets are used, because the hash is empty, so you can check to see if the hash is empty just by looking at it in scalar context. Got some keys: alester:~ $ perl -le'print scalar %ENV' 26/64 This hash has no keys: alester:~ $ perl -le'print scalar %nonexistenthash' 0 We've deleted all the keys that used to be there: alester:~ $ perl -le'delete @ENV{keys %ENV};print scalar %ENV' 0 -- Andy Lester => andy at petdance.com => www.petdance.com => AIM:petdance From jay at jays.net Thu Oct 18 12:09:10 2007 From: jay at jays.net (Jay Hannah) Date: Thu, 18 Oct 2007 14:09:10 -0500 Subject: [Omaha.pm] [Fwd: Newsletter from O'Reilly UG Program, October 18] Message-ID: <4717AF56.1080203@jays.net> Trimmed for Perl content. The whole newsletter is here: http://www.oreilly.com/emails/ug-oct.html *Perl Foundation Board of Directors election, New people, New Positions* The Perl Foundation is pleased to announce new appointments to several board positions: Bill Odom, previously President, becomes Chairman; Richard Dice becomes President; and Jim Brandt becomes Vice President. The board elected these new members in an August 2007 vote by the board members as mandated by the charter. Kurt DeMaagd will continue to serve as Treasurer, and Nat Torkington and Allison Randal will continue to serve as directors. From jay at jays.net Fri Oct 19 11:50:36 2007 From: jay at jays.net (Jay Hannah) Date: Fri, 19 Oct 2007 13:50:36 -0500 Subject: [Omaha.pm] auto-increment magic Message-ID: <4718FC7C.1080004@jays.net> I'll buy you a beer if you've ever used this, or seen it used usefully in a real-life program... j (... and what is \z?) perldoc perlop The auto-increment operator has a little extra builtin magic to it. If you increment a variable that is numeric, or that has ever been used in a numeric context, you get a normal increment. If, however, the variable has been used in only string contexts since it was set, and has a value that is not the empty string and matches the pattern "/^[a-zA-Z]*[0-9]*\z/", the increment is done as a string, preserving each character within its range, with carry: print ++($foo = '99'); # prints '100' print ++($foo = 'a0'); # prints 'a1' print ++($foo = 'Az'); # prints 'Ba' print ++($foo = 'zz'); # prints 'aaa' From jay at jays.net Fri Oct 19 11:58:32 2007 From: jay at jays.net (Jay Hannah) Date: Fri, 19 Oct 2007 13:58:32 -0500 Subject: [Omaha.pm] $ids[$i++] Message-ID: <4718FE58.9050800@jays.net> I've been doing this for years: my $i = 0; foreach my $single_reason (split /\|/, $reason) { my $id = $ids[$i]; $i++; ... But now my C++ mid-term I just took last night has me thinking like this: my $i = 0; foreach my $single_reason (split /\|/, $reason) { my $id = $ids[$i++]; ... Survey: Is the potential confusion between ++$i and $i++ worth saving 1 line of code? So far I'm voting "no"...? Ponder, j perldoc perlop Auto-increment and Auto-decrement "++" and "--" work as in C. That is, if placed before a variable, they increment or decrement the variable by one before returning the value, and if placed after, increment or decrement after returning the value. $i = 0; $j = 0; print $i++; # prints 0 print ++$j; # prints 1 From andy at petdance.com Fri Oct 19 12:07:42 2007 From: andy at petdance.com (Andy Lester) Date: Fri, 19 Oct 2007 14:07:42 -0500 Subject: [Omaha.pm] $ids[$i++] In-Reply-To: <4718FE58.9050800@jays.net> References: <4718FE58.9050800@jays.net> Message-ID: <20071019190742.GA31859@petdance.com> > But now my C++ mid-term I just took last night has me thinking like this: > > my $i = 0; > foreach my $single_reason (split /\|/, $reason) { > my $id = $ids[$i++]; Why do you want to know where in the array you are? Should you be avoiding the loop index entirely? -- Andy Lester => andy at petdance.com => www.petdance.com => AIM:petdance From andy at petdance.com Fri Oct 19 12:08:22 2007 From: andy at petdance.com (Andy Lester) Date: Fri, 19 Oct 2007 14:08:22 -0500 Subject: [Omaha.pm] auto-increment magic In-Reply-To: <4718FC7C.1080004@jays.net> References: <4718FC7C.1080004@jays.net> Message-ID: <20071019190822.GB31859@petdance.com> On Fri, Oct 19, 2007 at 01:50:36PM -0500, Jay Hannah (jay at jays.net) wrote: > I'll buy you a beer if you've ever used this, or seen it used usefully > in a real-life program... > > j > (... and what is \z?) It means end of string, not end of line like $ means. -- Andy Lester => andy at petdance.com => www.petdance.com => AIM:petdance From jay at jays.net Fri Oct 19 13:04:49 2007 From: jay at jays.net (Jay Hannah) Date: Fri, 19 Oct 2007 15:04:49 -0500 Subject: [Omaha.pm] $ids[$i++] In-Reply-To: <20071019190742.GA31859@petdance.com> References: <4718FE58.9050800@jays.net> <20071019190742.GA31859@petdance.com> Message-ID: <47190DE1.4090807@jays.net> Andy Lester wrote: >> But now my C++ mid-term I just took last night has me thinking like this: >> >> my $i = 0; >> foreach my $single_reason (split /\|/, $reason) { >> my $id = $ids[$i++]; >> > > Why do you want to know where in the array you are? Should you be > avoiding the loop index entirely? Here is more context. (80% of the real but irrelevant code has been removed) # We need the list of all IDs first so we can set related_uniform_ids # to all IDs on each ticket. my @ids = (get_id($dbh)); foreach (split /\|/, $reason) { push @ids, ($ids[-1] + 1); } pop @ids; my $i = 0; foreach my $single_reason (split /\|/, $reason) { my $id = $ids[$i++]; my $uniform = Model::MySQL::Simple::uniform->new(Globals=>$Globals); $uniform->set_id($id); $uniform->set_related_uniform_ids(join "|", @ids); $uniform->commit(filter=>"id = '$id'"); } my $url = $q->url(); $url.="?dowhat=success&id=" . (join "|", @ids); print $q->redirect("$url"); I'm creating a set of entries in the "uniform" table of our database. I don't know how many I'm creating -- that depends on how many reasons there are in the pipe-delimited list stored in $reason. Each row in the table needs a unique ID, but I also want a pipe delimited list of all of the IDs I'm creating set into the related_uniform_ids attribute of every row. So, first I create @ids. Then I loop again. $i grabs the individual ID for each ticket. I 'spose I could re-write it to be more readable, but it's probably not bad enough to invest the time and re-test it. j guilty as charged :) From jay at jays.net Fri Oct 19 13:25:49 2007 From: jay at jays.net (Jay Hannah) Date: Fri, 19 Oct 2007 15:25:49 -0500 Subject: [Omaha.pm] [olug] Character Removal In-Reply-To: <200710191516.KAA21465@stork.inebraska.com> References: <200710191516.KAA21465@stork.inebraska.com> Message-ID: <471912CD.1040707@jays.net> Carl Lundstedt wrote: > 1...2...3...4...I smell a scripting war!!! Guilty! Obi-Wan wrote: > Perl has its uses, but is overly bloated for such a simple operation. > Sed(1) does a wonderful job of this sort of thing. Assuming you want > to keep the first and last parentheses: > > # echo "abc (asdf) asdf (asdf) 1234 (xyz) 67" | sed -e 's/([^)]*)[^)]*)/()/' > abc () 1234 (xyz) 67 > Overly bloated? Instead of sed -e use perl -ple and escape any parens outside of []'s. Now sed and perl do the exact same thing in your examples. So when specifically hunting parens I concede sed is less line-noisy. But "overly bloated"? Really? -poke- -laugh- j Omaha Perl Mongers: http://omaha.pm.org From dan at linder.org Thu Oct 25 09:08:16 2007 From: dan at linder.org (Daniel Linder) Date: Thu, 25 Oct 2007 11:08:16 -0500 (CDT) Subject: [Omaha.pm] Alarms in Perl. Message-ID: <59610.70.165.110.36.1193328496.squirrel@webmail.linder.org> [No, it's DeJaVu, I accidentally posted this to the Omaha Local Users Group instead of PM when I meant to post it here. Sorry if you get this twice. --Dan] I have a handful of scripts that are run periodically 24x7. Nearly all the time, they run fine and report their status back when they exit correctly. On the odd occasion (about once every 1-2 weeks), a script will hang at some point in the code and never exit - most likely a call to an external program that didn't complete or hung itself. (The reason for the hanging is not the point of this e-mail.) What I would like to setup is a simple alarm based action that would exit the script -- no matter what -- if it was still running after an extended period of time. (I.e. if a script that should only take ten seconds to run has been running for five minutes, exit with a value of 99.) >From perl.com I found this code: URL:http://www.perl.com/pub/a/2007/06/07/better-code-through-destruction.html?page=2 Code: 1: eval{ 2: local $SIG{ALRM} = sub { die "Timed out\n" }; 3: alarm(5); 4: my $sentry = Object::Destroyer->new( sub {alarm(0)} ); 5: long_running_code(); 6: }; Dissection: Line 1: Wrapper the whole thing in an "eval" to make the "my $sentry" work. Line 2: Setup what to do when the alarm triggers. Line 3: Set the alarm to go off in 5 seconds. Line 4: Setup a new variable that only exists within the "eval" block. When the eval block exits, the $sentry variable object invokes the Destroyer function. (In this case it resets the alarm to 0, effectively resetting the alarm on a good exit of the eval block.) Line 5: Run the (possibly bad) code. If it runs to completion within the allotted time, the eval block exits, the alarm is reset, and the die never gets called. If the code takes too long, the die *is* called and the whole script exits. Questions: 1: Will (should) this work even if the "long_running_code()" uses system() and or back-ticks to call out to external programs? (I realize those programs could be left running - I'm ok with having the admin clean them up once they are alerted to the code not returning at all...) 2: Are the alarm() and Object::Destroyer calls part of the base Perl modules, or will I be visiting CPAN to get this working? (How do I check what's included out of the box vs. what has been installed over time?) 3: Is there any command-line magic that perl can be invoked with that will cause Perl to call a specific function if it is left running for a long period of time? (i.e. perl --timeout 300 --timeout-sub 'MyExitSubroutine()' ./MyBigPerlScript.pl) Thanks, Dan - - - - "There are four boxes to be used in defense of liberty: soap, ballot, jury, and ammo. Please use in that order." -- Ed Howdershelt (Author) "I do not fear computers, I fear the lack of them." -- Isaac Asimov (Author) ** *** ***** ******* *********** ************* NRL, Shayet-13, NCCS, IRS, Reno, gorilla, anarchy package, domestic disruption, UDT, Tie-fighter, Menwith, Masuda, c Duress, Bubba the Love Sponge, HIC, BATF, package, TELINT, HPCC From jay at jays.net Tue Oct 30 15:30:10 2007 From: jay at jays.net (Jay Hannah) Date: Tue, 30 Oct 2007 17:30:10 -0500 Subject: [Omaha.pm] Alarms in Perl. In-Reply-To: <59610.70.165.110.36.1193328496.squirrel@webmail.linder.org> References: <59610.70.165.110.36.1193328496.squirrel@webmail.linder.org> Message-ID: <9DF9A824-EF89-433E-9FAB-E74CEC6B6F5F@jays.net> On Oct 25, 2007, at 11:08 AM, Daniel Linder wrote: > What I would like to setup is a simple alarm based action that > would exit > the script -- no matter what -- if it was still running after an > extended > period of time. Your example seems overly complicated to me. I think all you need is $SIG{ALRM} and alarm(). $ cat j.pl local $SIG{ALRM} = \&timeout; alarm(5); sleep 10; # My "long_running_code()" print "I did not time out. \n"; exit; sub timeout { print "Timed out\n"; exit; } $ perl j.pl Timed out That said, I'll take a stab at your questions... > 1: Will (should) this work even if the "long_running_code()" uses > system() > and or back-ticks to call out to external programs? (I realize those > programs could be left running - I'm ok with having the admin clean > them > up once they are alerted to the code not returning at all...) ... I haven't studied Object::Destroyer, but it's probably a safe bet that all children process will terminate when your parent process (your Perl program) does. > 2: Are the alarm() and Object::Destroyer calls part of the base Perl > modules, or will I be visiting CPAN to get this working? (How do I > check > what's included out of the box vs. what has been installed over time?) You should be able to see what has been installed after Perl via: perldoc perllocal > 3: Is there any command-line magic that perl can be invoked with > that will > cause Perl to call a specific function if it is left running for a > long > period of time? (i.e. perl --timeout 300 --timeout-sub > 'MyExitSubroutine()' ./MyBigPerlScript.pl) Whatever you set $SIG{ALRM} to is what will get called if the kernel sends the ALRM signal. I wouldn't think you would want that to be based on a command-line argument, but if you did maybe you could try something like: $SIG{ALRM} = eval{ "\&$ARGV[0]" }; My favorite way of handling --timeout-sub args is via Getopt::Long. It's groovy. HTH, j