source: main/trunk/greenstone2/bin/script/schedule.pl@ 22642

Last change on this file since 22642 was 21292, checked in by kjdon, 14 years ago

extended extensions mechanism to include gs3 extensions

  • Property svn:executable set to *
File size: 17.9 KB
Line 
1#!/usr/bin/perl -w
2
3###########################################################################
4#
5# schedule.pl --
6# A component of the Greenstone digital library software
7# from the New Zealand Digital Library Project at the
8# University of Waikato, New Zealand.
9#
10# Copyright (C) 1999 New Zealand Digital Library Project
11#
12# This program is free software; you can redistribute it and/or modify
13# it under the terms of the GNU General Public License as published by
14# the Free Software Foundation; either version 2 of the License, or
15# (at your option) any later version.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20# GNU General Public License for more details.
21#
22# You should have received a copy of the GNU General Public License
23# along with this program; if not, write to the Free Software
24# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25#
26###########################################################################
27
28package schedule;
29
30BEGIN {
31 die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
32 die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
33 unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
34 unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan");
35 unshift (@INC, "$ENV{'GSDLHOME'}/perllib/plugins");
36 unshift (@INC, "$ENV{'GSDLHOME'}/perllib/plugouts");
37 unshift (@INC, "$ENV{'GSDLHOME'}/perllib/classify");
38
39 if (defined $ENV{'GSDLEXTS'}) {
40 my @extensions = split(/:/,$ENV{'GSDLEXTS'});
41 foreach my $e (@extensions) {
42 my $ext_prefix = "$ENV{'GSDLHOME'}/ext/$e";
43
44 unshift (@INC, "$ext_prefix/perllib");
45 unshift (@INC, "$ext_prefix/perllib/cpan");
46 }
47 }
48 if (defined $ENV{'GSDL3EXTS'}) {
49 my @extensions = split(/:/,$ENV{'GSDL3EXTS'});
50 foreach my $e (@extensions) {
51 my $ext_prefix = "$ENV{'GSDL3SRCHOME'}/ext/$e";
52
53 unshift (@INC, "$ext_prefix/perllib");
54 unshift (@INC, "$ext_prefix/perllib/cpan");
55 }
56 }
57
58}
59
60use strict;
61no strict 'refs';
62no strict 'subs';
63
64use FileHandle;
65use Fcntl;
66use printusage;
67use parse2;
68use parse3;
69use gsprintf 'gsprintf';
70if($ENV{'GSDLOS'} eq "windows") {
71 eval("require \"Win32.pm\" ");
72}
73
74my $frequency_list =
75 [ { 'name' => "hourly",
76 'desc' => "{schedule.frequency.hourly}" },
77 { 'name' => "daily",
78 'desc' => "{schedule.frequency.daily}" },
79 { 'name' => "weekly",
80 'desc' => "{schedule.frequency.weekly}" }
81 ];
82
83my $action_list =
84 [ { 'name' => "add",
85 'desc' => "{schedule.action.add}" },
86 { 'name' => "update",
87 'desc' => "{schedule.action.update}" },
88 { 'name' => "delete",
89 'desc' => "{schedule.action.delete}" }
90 ];
91
92my $arguments =
93 [
94 { 'name' => "schedule",
95 'desc' => "{schedule.schedule}",
96 'type' => "flag",
97 'reqd' => "no",
98 'modegli' => "3" },
99 { 'name' => "frequency",
100 'desc' => "{schedule.frequency}",
101 'type' => "enum",
102 'list' => $frequency_list,
103 'deft' => "daily",
104 'reqd' => "no",
105 'modegli' => "3" },
106 { 'name' => "action",
107 'desc' => "{schedule.action}",
108 'type' => "enum",
109 'list' => $action_list,
110 'deft' => "add",
111 'reqd' => "no",
112 'modegli' => "3" },
113 { 'name' => "import",
114 'desc' => "{schedule.import}",
115 'type' => "quotestr",
116 'deft' => "",
117 'reqd' => "yes",
118 'hiddengli' => "yes" },
119 { 'name' => "build",
120 'desc' => "{schedule.build}",
121 'type' => "quotestr",
122 'deft' => "",
123 'reqd' => "yes",
124 'hiddengli' => "yes" },
125 { 'name' => "colname",
126 'desc' => "{schedule.colname}",
127 'type' => "string",
128 'deft' => "",
129 'reqd' => "no",
130 'hiddengli' => "yes" },
131 { 'name' => "xml",
132 'desc' => "{scripts.xml}",
133 'type' => "flag",
134 'reqd' => "no",
135 'hiddengli' => "yes" },
136 { 'name' => "language",
137 'desc' => "{scripts.language}",
138 'type' => "string",
139 'reqd' => "no",
140 'hiddengli' => "yes" },
141 { 'name' => "email",
142 'desc' => "{schedule.email}",
143 'type' => "flag",
144 'reqd' => "no",
145 'modegli' => "3" },
146 { 'name' => "toaddr",
147 'desc' => "{schedule.toaddr}",
148 'type' => "string",
149 'reqd' => "no",
150 'deft' => "",
151 'modegli' => "3" },
152 { 'name' => "fromaddr",
153 'desc' => "{schedule.fromaddr}",
154 'type' => "string",
155 'deft' => "",
156 'reqd' => "no",
157 'modegli' => "3" },
158 { 'name' => "smtp",
159 'desc' => "{schedule.smtp}",
160 'type' => "string",
161 'deft' => "",
162 'reqd' => "no",
163 'modegli' => "3" },
164 { 'name' => "out",
165 'desc' => "{schedule.out}",
166 'type' => "string",
167 'deft' => "STDERR",
168 'reqd' => "no",
169 'hiddengli' => "yes" },
170 { 'name' => "gli",
171 'desc' => "{schedule.gli}",
172 'type' => "flag",
173 'reqd' => "no",
174 'hiddengli' => "yes" }
175 ];
176
177
178my $options = { 'name' => "schedule.pl",
179 'desc' => "Interaction with Cron",
180 'args' => $arguments };
181
182&main();
183
184sub main {
185
186 #params
187 my ($action, $frequency, $import, $build, $colname, $xml, $language,
188 $email, $toaddr, $fromaddr, $smtp, $gli, $out);
189
190 #other vars
191 my ($i,$numArgs,$os,$erase,$erase2,$copy,$newpl,$gsdl,$path,$cronf,
192 $nf,$of,$opf, $cronstr, $ecmd,$ecmd2, $record, $cronrec,$ncronf);
193
194 #some defaults
195 $action = "add";
196 $frequency = "hourly";
197 $import = "";
198 $build = "";
199 $colname = "";
200 $xml = 0;
201 $email = 0;
202 $gli = 0;
203 $language = "";
204 $out = "STDERR";
205
206
207 $gsdl = $ENV{'GSDLHOME'};
208 $os = $ENV{'GSDLOS'};
209 $path = $ENV{'PATH'};
210
211 my $service = "schedule";
212
213 #For this to work, we need to know if -gli exists
214
215 $numArgs=$#ARGV+1;
216 $i = 0;
217 while($i < $numArgs)
218 {
219 if($ARGV[$i] =~ /gli/) {
220 $gli = 1;
221 }
222 $i++;
223 }
224
225 #We are using two different parsers here, because the GLI in linux (and probably darwin) will not take
226 #an entire double-quoted string as an argument, while if schedule.pl is
227 #executed from the command line, the entire double-quoted string is taken
228 #as an argument. For Windows, it seems that it does.
229 my $hashParsingResult = {};
230 my $intArgLeftAfterParsing;
231 if($gli && ($os eq "linux" || $os eq "darwin")) {
232 $intArgLeftAfterParsing = parse3::parse(\@ARGV, $arguments, $hashParsingResult, "allow_extra_options");
233 } else {
234 $intArgLeftAfterParsing = parse2::parse(\@ARGV, $arguments, $hashParsingResult, "allow_extra_options");
235
236 }
237
238 #check for extra options
239 if ($intArgLeftAfterParsing == -1 || $intArgLeftAfterParsing > 0 || (@ARGV && $ARGV[0] =~ /^\-+h/))
240 {
241 &PrintUsage::print_txt_usage($options, "{schedule.params}");
242 die "\n";
243 }
244
245 foreach my $strVariable (keys %$hashParsingResult)
246 {
247 eval "\$$strVariable = \$hashParsingResult->{\"\$strVariable\"}";
248 }
249
250 if ($xml) {
251 &PrintUsage::print_xml_usage($options);
252 print "\n";
253 return;
254
255 }
256
257 if ($gli) { # the gli wants strings to be in UTF-8
258 &gsprintf::output_strings_in_UTF8;
259 }
260
261 if($action eq "add" || $action eq "update") {
262 if($email) {
263 if($smtp eq "" || $toaddr eq "" || $fromaddr eq "" || $smtp =~ /^-/ || $toaddr =~ /^-/ || $fromaddr =~ /^-/) {
264 &gsprintf($out, "{schedule.error.email} \n");
265 die "\n";
266 }
267
268
269 if($import eq "" || $build eq "") {
270 &gsprintf($out, "{schedule.error.importbuild} \n");
271 die "\n";
272 }
273 }
274 }
275 if($colname eq "") {
276 &gsprintf($out, "{schedule.error.colname} \n");
277 die "\n";
278 }
279
280 #not sure if this is always set?
281 #language may be passed in too
282 if($language eq "" && exists($ENV{'GSDLLANG'})) {
283 $language = $ENV{'GSDLLANG'};
284 }
285 elsif($language eq "") {
286 $language = "en";
287 }
288
289 $newpl = "cron.pl";
290
291 if($action eq "delete") {
292
293 print STDERR "<Delete>\n" if $gli;
294
295 if($os =~ /^linux$/ || $os =~ /^darwin$/) {
296 system("\\rm $gsdl/collect/$colname/$newpl 2>/dev/null");
297 system("\\rm $gsdl/collect/$colname/cronjob 2>/dev/null");
298 } else { #in windows
299
300 system("del $gsdl\\\\collect\\\\$colname\\\\$newpl 2>nul"); #nul is windows equivalent to /dev/null
301
302 }
303
304
305 &gsprintf($out, "{schedule.deleted}\n");
306 }
307 else {
308 #For the Scheduling monitor
309 print STDERR "<Schedule>\n" if $gli;
310
311 if ($os =~ /^linux$/ || $os =~ /^darwin$/) {
312
313 $import = $import." 2>$gsdl/collect/$colname/log/\$logfile";
314 $build = $build." 2>>$gsdl/collect/$colname/log/\$logfile";
315 $erase = "\\\\rm -r $gsdl/collect/$colname/index 2>>$gsdl/collect/$colname/log/\$logfile";
316 $erase2 = "mkdir $gsdl/collect/$colname/index 2>>$gsdl/collect/$colname/log/\$logfile";
317 $copy = "mv $gsdl/collect/$colname/building/* $gsdl/collect/$colname/index/ 2>>$gsdl/collect/$colname/log/\$logfile";
318 if($email) {
319 #first,we need to add backslashes before the 'at' symbol.
320 $toaddr =~ s/\@/\\\@/g;
321 $fromaddr =~ s/\@/\\\@/g;
322
323 $ecmd = "$gsdl/bin/script/sendmail.pl -to $toaddr -from $fromaddr -smtp $smtp -msgfile $gsdl/collect/$colname/log/\$logfile -subject \\\"Results of build for collection $colname\\\" 2>>$gsdl/collect/$colname/log/\$logfile";
324
325 $ecmd2 = "$gsdl/bin/script/sendmail.pl -to $toaddr -from $fromaddr -smtp $smtp -msgfile $gsdl/etc/cronlock.txt -subject \\\"Results of build for collection $colname\\\" 2>>$gsdl/collect/$colname/log/\$logfile";
326 }
327
328 } else { #in windows
329
330 $gsdl =~ s/\\/\\\\/g;
331 $path =~ s/\\/\\\\/g;
332
333 $import =~ s/\\/\\\\/g;
334 $build =~ s/\\/\\\\/g;
335
336 $import =~ s/exe/exe\\\"/g;
337 $import =~ s/pl/pl\\\"/g;
338 $build =~ s/exe/exe\\\"/g;
339 $build =~ s/pl/pl\\\"/g;
340
341
342 my $prompt = substr($gsdl,0,2);
343
344 $import =~ s/$prompt/\\\"$prompt/g;
345 $build =~ s/$prompt/\\\"$prompt/g;
346
347 #not the best solution - won't work if someone chooses something weird
348 $import =~ s/\\collect/\\collect\\\"/;
349 $build =~ s/\\collect/\\collect\\\"/;
350
351 $import = "$import 2>\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\\$logfile\\\" ";
352 $build = "$build 2>>\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\\$logfile\\\" ";
353
354
355 $erase = "rd \\\/S \\\/Q \\\"$gsdl\\\\collect\\\\$colname\\\\index\\\" 2>>\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\\$logfile\\\" ";
356 $erase2 = "md \\\"$gsdl\\\\collect\\\\$colname\\\\index\\\" 2>>\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\\$logfile\\\" ";
357 $copy = "xcopy \\\/E \\\/Y \\\"$gsdl\\\\collect\\\\$colname\\\\building\\\\*\\\" \\\"$gsdl\\\\collect\\\\$colname\\\\index\\\\\\\" >>\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\\$logfile\\\" ";
358 if($email) {
359 $toaddr =~ s/\@/\\\@/g;
360 $fromaddr =~ s/\@/\\\@/g;
361 $ecmd = "\\\"$gsdl\\\\bin\\\\windows\\\\perl\\\\bin\\\\perl.exe\\\" -S \\\"$gsdl\\\\bin\\\\script\\\\sendmail.pl\\\" -to $toaddr -from $fromaddr -smtp $smtp -msgfile \\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\\$logfile\\\" -subject \\\"Results of build for collection $colname\\\" >>\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\\$logfile\\\" ";
362
363 $ecmd2 = "\\\"$gsdl\\\\bin\\\\windows\\\\perl\\\\bin\\\\perl.exe\\\" -S \\\"$gsdl\\\\bin\\\\script\\\\sendmail.pl\\\" -to $toaddr -from $fromaddr -smtp $smtp -msgfile \\\"$gsdl\\\\etc\\\\cronlock.txt\\\" -subject \\\"Results of build for collection $colname\\\" >>\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\\$logfile\\\" ";
364 }
365 }
366
367
368 $nf = new FileHandle() ||
369 (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
370
371 open($nf, ">$gsdl/collect/$colname/$newpl") ||
372 (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
373
374
375 print $nf "\#!/usr/bin/perl";
376 print $nf "\n\n";
377
378
379 #we need to set environment variables for import and build
380 print $nf "\$ENV{'GSDLHOME'}=\"$gsdl\"\;\n";
381 print $nf "\$ENV{'GSDLOS'}=\"$os\"\;\n";
382 print $nf "\$ENV{'GSDLLANG'}=\"$language\"\;\n";
383 print $nf "\$ENV{'PATH'}=\"$path\"\;\n";
384
385 print $nf "\$logfile = \"cron\".time\(\).\".txt\"\;\n";
386
387 if($os =~ /^windows$/) {
388 print $nf "if\(-e \\\"$gsdl\\\\collect\\\\$colname\\\\etc\\\\cron.lck\\\" \"\)\{ \n";
389 } else {
390 print $nf "if\(-e \"$gsdl/collect/$colname/etc/cron.lck\"\) \{ \n";
391 }
392 if($email) {
393 print $nf " system(\"$ecmd2\")\;\n";
394 }
395 else {
396 if($os eq "windows") {
397 print $nf " system(\"more \\\"$gsdl\\\\etc\\\\cronlock.txt\\\" >\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\\$logfile\\\"\"\)\;\n";
398 } else {
399 print $nf " system(\"more $gsdl/etc/cronlock/txt > $gsdl/collect/$colname/log/\$logfile \"\)\;\n";
400 }
401
402 }
403 print $nf "\} else \{\n";
404
405 if($os eq "linux" || $os eq "darwin") {
406 $import =~ s/\"//;
407 $import =~ s/\"//;
408 $build =~ s/\"//;
409 $build =~ s/\"//;
410 }
411
412 if($os =~ /^windows$/) {
413 print $nf "system(\"echo lock \>\\\"$gsdl\\\\collect\\\\$colname\\\\etc\\\\cron.lck\\\"\")\;\n";
414 } else {
415 print $nf "system(\"echo lock >$gsdl/collect/$colname/etc/cron.lck\")\;\n";
416 }
417
418 print $nf " system(\"$import\")\;\n";
419 print $nf " system(\"$build\")\;\n";
420
421 print $nf " system(\"$erase\")\;\n";
422 print $nf " system(\"$erase2\")\;\n";
423
424 print $nf " system(\"$copy\")\;\n";
425 if($email) {
426 print $nf " system(\"$ecmd\")\;\n";
427 }
428
429
430 #need to set permissions in linux
431 if($os =~ /^linux$/ || $os =~ /^darwin$/) {
432 print $nf "system(\"chmod -R 755 $gsdl/collect/$colname/index/*\")\;\n";
433 print $nf "system(\"\\\\rm $gsdl/collect/$colname/etc/cron.lck\")\;\n";
434 } else {
435 print $nf "system(\"del \\\"$gsdl\\\\collect\\\\$colname\\\\etc\\\\cron.lck\\\" \")\;\n";
436 }
437
438
439
440 print $nf "\}\n";
441
442 close($nf);
443 if($os =~ /^linux$/ || $os =~ /^darwin$/) {
444 system("chmod 755 $gsdl/collect/$colname/cron.pl");
445 }
446
447 &gsprintf($out, "{schedule.scheduled}\n");
448 }
449
450 #next, we need to create a crontab file. For now, a crontab will be set up
451 #to run at midnight either nightly or weekly.
452 $gsdl =~ s/\\\\/\\/g;
453 if ($os =~ /^linux$/ || $os =~ /^darwin$/)
454 {
455 $cronf="cronjob";
456 open($nf, ">$gsdl/collect/$colname/$cronf") ||
457 (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
458
459 #see if there is an existing crontab
460 system("crontab -l >$gsdl/collect/$colname/outfile 2>/dev/null");
461
462 $opf = new FileHandle();
463 open($opf, "$gsdl/collect/$colname/outfile") ||
464 (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
465 $record = <$opf>;
466
467 #if there is an existing crontab file
468 #preserve all records and change existing record for
469 #current collection
470 if ($record)
471 {
472 do
473 {
474 if($record !~ /$colname/)
475 {
476 print $nf $record;
477 }
478 } while($record = <$opf>);
479
480 close($opf);
481 }
482
483
484 if($action =~ /^add$/ || $action =~ /^update$/)
485 {
486 if($frequency eq "hourly") {
487 $cronrec = "50 * * * * $gsdl/collect/$colname/cron.pl";
488 }
489 elsif($frequency eq "daily") {
490 $cronrec = "00 0 * * * $gsdl/collect/$colname/cron.pl";
491 }
492 elsif($frequency eq "weekly") {
493 $cronrec = "59 11 * * 0 $gsdl/collect/$colname/cron.pl";
494 }
495
496 $cronrec = $cronrec." 2>/dev/null\n";
497
498 print $nf $cronrec;
499 }
500
501 close($nf);
502
503 #this makes the cronjob official
504 #still needs to be done for existing records
505 system("crontab $gsdl/collect/$colname/$cronf 2>/dev/null");
506
507 #cleanup
508 system("\\rm $gsdl/collect/$colname/outfile");
509 system("\\rm $gsdl/collect/$colname/$cronf");
510
511 if($action eq "add" || $action eq "update") {
512 &gsprintf($out, "{schedule.cron}\n");
513 }
514
515 } else {
516
517 #for windows, we will put crontab file in the same place. some limitations
518 #1) the absolute path to greenstone cannot have spaces if one is going to do this
519 #2) cron.exe needs to be started manually before doing this
520 #3) greenstone may have to be shut down completely to do this or lock problems occur
521
522 $cronf="crontab"; #pycron.exe expects this filename!
523 $ncronf="crontab.new";
524 #check to see if crontab file exists
525 if(-e "$gsdl/collect/$cronf")
526 {
527
528 open($of, "$gsdl/collect/$cronf") ||
529 (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
530
531
532 open($nf, ">$gsdl/collect/$ncronf") ||
533 (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
534
535 while($record = <$of>)
536 {
537 if($record !~ /$colname/)
538 {
539 print $nf $record;
540 }
541 }
542 close($of);
543 close($nf);
544
545 system("del \"$gsdl\\collect\\$cronf\"");
546 system("move \"$gsdl\\collect\\$ncronf\" \"$gsdl\\collect\\$cronf\"");
547
548
549 my $shortf = Win32::GetShortPathName($gsdl);
550
551 my $command = "$shortf\\bin\\windows\\silentstart $shortf\\bin\\windows\\perl\\bin\\perl $shortf\\collect\\$colname\\cron.pl\n";
552
553 if($action =~ /^add$/ || $action =~ /^update$/)
554 {
555 open($nf, ">>$gsdl/collect/$cronf") ||
556 (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
557
558 if($frequency eq "hourly") {
559 print $nf "50 * * * * $command";
560 }
561 elsif($frequency eq "daily") {
562 print $nf "00 0 * * * $command";
563 }
564 elsif($frequency eq "weekly") {
565 print $nf "59 11 * * 0 $command";
566 }
567 close($nf);
568 }
569
570 } else {
571
572 my $shortf = Win32::GetShortPathName($gsdl);
573
574 my $command = "$shortf\\bin\\windows\\silentstart $shortf\\bin\\windows\\perl\\bin\\perl $shortf\\collect\\$colname\\cron.pl\n";
575
576
577 if($action =~ /^add$/ || $action =~ /^update$/)
578 {
579 open($nf, ">$gsdl/collect/$cronf") ||
580 (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
581 if($frequency eq "hourly") {
582 print $nf "50 * * * * $command";
583 }
584 elsif($frequency eq "daily") {
585 print $nf "00 0 * * * $command";
586 }
587 elsif($frequency eq "weekly") {
588 print $nf "59 11 * * 0 $command";
589 }
590
591 close($nf);
592 }
593 }
594
595 if($action eq "update" || $action eq "add") {
596 &gsprintf($out, "{schedule.cron}\n");
597 }
598 }
599
600 #For the scheduling monitor
601 print STDERR "<Done>\n" if $gli;
602
603
604
605} #end sub main
Note: See TracBrowser for help on using the repository browser.