source: gsdl/trunk/bin/script/schedule.pl@ 18590

Last change on this file since 18590 was 18590, checked in by kjdon, 15 years ago

GLI three modes change: changed modegli for some script arguments. 3 becomes 2 or 3, 4 becomes 3

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