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

Last change on this file since 24829 was 24829, checked in by ak19, 12 years ago

Changes to bat files and perl code to deal with brackets in (Windows) filepath. Also checked winmake.bat files to see if changes were needed there. These changes go together with the commits 24826 to 24828 for gems.bat, and commit 24820 on makegs2.bat.

  • Property svn:executable set to *
File size: 18.0 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 if("$gsdl" =~ m/(\\\(|\\\)| )/ ) { # () brackets or spaces in path
212 &gsprintf($out, "\n\n{schedule.filepath_warning}\n\n\n", $gsdl);
213 }
214
215 my $service = "schedule";
216
217 #For this to work, we need to know if -gli exists
218
219 $numArgs=$#ARGV+1;
220 $i = 0;
221 while($i < $numArgs)
222 {
223 if($ARGV[$i] =~ /gli/) {
224 $gli = 1;
225 }
226 $i++;
227 }
228
229 #We are using two different parsers here, because the GLI in linux (and probably darwin) will not take
230 #an entire double-quoted string as an argument, while if schedule.pl is
231 #executed from the command line, the entire double-quoted string is taken
232 #as an argument. For Windows, it seems that it does.
233 my $hashParsingResult = {};
234 my $intArgLeftAfterParsing;
235 if($gli && ($os eq "linux" || $os eq "darwin")) {
236 $intArgLeftAfterParsing = parse3::parse(\@ARGV, $arguments, $hashParsingResult, "allow_extra_options");
237 } else {
238 $intArgLeftAfterParsing = parse2::parse(\@ARGV, $arguments, $hashParsingResult, "allow_extra_options");
239
240 }
241
242 #check for extra options
243 if ($intArgLeftAfterParsing == -1 || $intArgLeftAfterParsing > 0 || (@ARGV && $ARGV[0] =~ /^\-+h/))
244 {
245 &PrintUsage::print_txt_usage($options, "{schedule.params}");
246 die "\n";
247 }
248
249 foreach my $strVariable (keys %$hashParsingResult)
250 {
251 eval "\$$strVariable = \$hashParsingResult->{\"\$strVariable\"}";
252 }
253
254 if ($xml) {
255 &PrintUsage::print_xml_usage($options);
256 print "\n";
257 return;
258
259 }
260
261 if ($gli) { # the gli wants strings to be in UTF-8
262 &gsprintf::output_strings_in_UTF8;
263 }
264
265 if($action eq "add" || $action eq "update") {
266 if($email) {
267 if($smtp eq "" || $toaddr eq "" || $fromaddr eq "" || $smtp =~ /^-/ || $toaddr =~ /^-/ || $fromaddr =~ /^-/) {
268 &gsprintf($out, "{schedule.error.email} \n");
269 die "\n";
270 }
271
272
273 if($import eq "" || $build eq "") {
274 &gsprintf($out, "{schedule.error.importbuild} \n");
275 die "\n";
276 }
277 }
278 }
279 if($colname eq "") {
280 &gsprintf($out, "{schedule.error.colname} \n");
281 die "\n";
282 }
283
284 #not sure if this is always set?
285 #language may be passed in too
286 if($language eq "" && exists($ENV{'GSDLLANG'})) {
287 $language = $ENV{'GSDLLANG'};
288 }
289 elsif($language eq "") {
290 $language = "en";
291 }
292
293 $newpl = "cron.pl";
294
295 if($action eq "delete") {
296
297 print STDERR "<Delete>\n" if $gli;
298
299 if($os =~ /^linux$/ || $os =~ /^darwin$/) {
300 system("\\rm $gsdl/collect/$colname/$newpl 2>/dev/null");
301 system("\\rm $gsdl/collect/$colname/cronjob 2>/dev/null");
302 } else { #in windows
303
304 system("del $gsdl\\\\collect\\\\$colname\\\\$newpl 2>nul"); #nul is windows equivalent to /dev/null
305
306 }
307
308
309 &gsprintf($out, "{schedule.deleted}\n");
310 }
311 else {
312 #For the Scheduling monitor
313 print STDERR "<Schedule>\n" if $gli;
314
315 if ($os =~ /^linux$/ || $os =~ /^darwin$/) {
316
317 $import = $import." 2>$gsdl/collect/$colname/log/\$logfile";
318 $build = $build." 2>>$gsdl/collect/$colname/log/\$logfile";
319 $erase = "\\\\rm -r $gsdl/collect/$colname/index 2>>$gsdl/collect/$colname/log/\$logfile";
320 $erase2 = "mkdir $gsdl/collect/$colname/index 2>>$gsdl/collect/$colname/log/\$logfile";
321 $copy = "mv $gsdl/collect/$colname/building/* $gsdl/collect/$colname/index/ 2>>$gsdl/collect/$colname/log/\$logfile";
322 if($email) {
323 #first,we need to add backslashes before the 'at' symbol.
324 $toaddr =~ s/\@/\\\@/g;
325 $fromaddr =~ s/\@/\\\@/g;
326
327 $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";
328
329 $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";
330 }
331
332 } else { #in windows
333
334 $gsdl =~ s/\\/\\\\/g;
335 $path =~ s/\\/\\\\/g;
336
337 $import =~ s/\\/\\\\/g;
338 $build =~ s/\\/\\\\/g;
339
340 $import =~ s/exe/exe\\\"/g;
341 $import =~ s/pl/pl\\\"/g;
342 $build =~ s/exe/exe\\\"/g;
343 $build =~ s/pl/pl\\\"/g;
344
345
346 my $prompt = substr($gsdl,0,2);
347
348 $import =~ s/$prompt/\\\"$prompt/g;
349 $build =~ s/$prompt/\\\"$prompt/g;
350
351 #not the best solution - won't work if someone chooses something weird
352 $import =~ s/\\collect/\\collect\\\"/;
353 $build =~ s/\\collect/\\collect\\\"/;
354
355 $import = "$import 2>\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\\$logfile\\\" ";
356 $build = "$build 2>>\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\\$logfile\\\" ";
357
358
359 $erase = "rd \\\/S \\\/Q \\\"$gsdl\\\\collect\\\\$colname\\\\index\\\" 2>>\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\\$logfile\\\" ";
360 $erase2 = "md \\\"$gsdl\\\\collect\\\\$colname\\\\index\\\" 2>>\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\\$logfile\\\" ";
361 $copy = "xcopy \\\/E \\\/Y \\\"$gsdl\\\\collect\\\\$colname\\\\building\\\\*\\\" \\\"$gsdl\\\\collect\\\\$colname\\\\index\\\\\\\" >>\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\\$logfile\\\" ";
362 if($email) {
363 $toaddr =~ s/\@/\\\@/g;
364 $fromaddr =~ s/\@/\\\@/g;
365 $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\\\" ";
366
367 $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\\\" ";
368 }
369 }
370
371
372 $nf = new FileHandle() ||
373 (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
374
375 open($nf, ">$gsdl/collect/$colname/$newpl") ||
376 (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
377
378
379 print $nf "\#!/usr/bin/perl";
380 print $nf "\n\n";
381
382
383 #we need to set environment variables for import and build
384 print $nf "\$ENV{'GSDLHOME'}=\"$gsdl\"\;\n";
385 print $nf "\$ENV{'GSDLOS'}=\"$os\"\;\n";
386 print $nf "\$ENV{'GSDLLANG'}=\"$language\"\;\n";
387 print $nf "\$ENV{'PATH'}=\"$path\"\;\n";
388
389 print $nf "\$logfile = \"cron\".time\(\).\".txt\"\;\n";
390
391 if($os =~ /^windows$/) {
392 print $nf "if\(-e \\\"$gsdl\\\\collect\\\\$colname\\\\etc\\\\cron.lck\\\" \"\)\{ \n";
393 } else {
394 print $nf "if\(-e \"$gsdl/collect/$colname/etc/cron.lck\"\) \{ \n";
395 }
396 if($email) {
397 print $nf " system(\"$ecmd2\")\;\n";
398 }
399 else {
400 if($os eq "windows") {
401 print $nf " system(\"more \\\"$gsdl\\\\etc\\\\cronlock.txt\\\" >\\\"$gsdl\\\\collect\\\\$colname\\\\log\\\\\$logfile\\\"\"\)\;\n";
402 } else {
403 print $nf " system(\"more $gsdl/etc/cronlock/txt > $gsdl/collect/$colname/log/\$logfile \"\)\;\n";
404 }
405
406 }
407 print $nf "\} else \{\n";
408
409 if($os eq "linux" || $os eq "darwin") {
410 $import =~ s/\"//;
411 $import =~ s/\"//;
412 $build =~ s/\"//;
413 $build =~ s/\"//;
414 }
415
416 if($os =~ /^windows$/) {
417 print $nf "system(\"echo lock \>\\\"$gsdl\\\\collect\\\\$colname\\\\etc\\\\cron.lck\\\"\")\;\n";
418 } else {
419 print $nf "system(\"echo lock >$gsdl/collect/$colname/etc/cron.lck\")\;\n";
420 }
421
422 print $nf " system(\"$import\")\;\n";
423 print $nf " system(\"$build\")\;\n";
424
425 print $nf " system(\"$erase\")\;\n";
426 print $nf " system(\"$erase2\")\;\n";
427
428 print $nf " system(\"$copy\")\;\n";
429 if($email) {
430 print $nf " system(\"$ecmd\")\;\n";
431 }
432
433
434 #need to set permissions in linux
435 if($os =~ /^linux$/ || $os =~ /^darwin$/) {
436 print $nf "system(\"chmod -R 755 $gsdl/collect/$colname/index/*\")\;\n";
437 print $nf "system(\"\\\\rm $gsdl/collect/$colname/etc/cron.lck\")\;\n";
438 } else {
439 print $nf "system(\"del \\\"$gsdl\\\\collect\\\\$colname\\\\etc\\\\cron.lck\\\" \")\;\n";
440 }
441
442
443
444 print $nf "\}\n";
445
446 close($nf);
447 if($os =~ /^linux$/ || $os =~ /^darwin$/) {
448 system("chmod 755 $gsdl/collect/$colname/cron.pl");
449 }
450
451 &gsprintf($out, "{schedule.scheduled}\n");
452 }
453
454 #next, we need to create a crontab file. For now, a crontab will be set up
455 #to run at midnight either nightly or weekly.
456 $gsdl =~ s/\\\\/\\/g;
457 if ($os =~ /^linux$/ || $os =~ /^darwin$/)
458 {
459 $cronf="cronjob";
460 open($nf, ">$gsdl/collect/$colname/$cronf") ||
461 (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
462
463 #see if there is an existing crontab
464 system("crontab -l >$gsdl/collect/$colname/outfile 2>/dev/null");
465
466 $opf = new FileHandle();
467 open($opf, "$gsdl/collect/$colname/outfile") ||
468 (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
469 $record = <$opf>;
470
471 #if there is an existing crontab file
472 #preserve all records and change existing record for
473 #current collection
474 if ($record)
475 {
476 do
477 {
478 if($record !~ /$colname/)
479 {
480 print $nf $record;
481 }
482 } while($record = <$opf>);
483
484 close($opf);
485 }
486
487
488 if($action =~ /^add$/ || $action =~ /^update$/)
489 {
490 if($frequency eq "hourly") {
491 $cronrec = "50 * * * * $gsdl/collect/$colname/cron.pl";
492 }
493 elsif($frequency eq "daily") {
494 $cronrec = "00 0 * * * $gsdl/collect/$colname/cron.pl";
495 }
496 elsif($frequency eq "weekly") {
497 $cronrec = "59 11 * * 0 $gsdl/collect/$colname/cron.pl";
498 }
499
500 $cronrec = $cronrec." 2>/dev/null\n";
501
502 print $nf $cronrec;
503 }
504
505 close($nf);
506
507 #this makes the cronjob official
508 #still needs to be done for existing records
509 system("crontab $gsdl/collect/$colname/$cronf 2>/dev/null");
510
511 #cleanup
512 system("\\rm $gsdl/collect/$colname/outfile");
513 system("\\rm $gsdl/collect/$colname/$cronf");
514
515 if($action eq "add" || $action eq "update") {
516 &gsprintf($out, "{schedule.cron}\n");
517 }
518
519 } else {
520
521 #for windows, we will put crontab file in the same place. some limitations
522 #1) the absolute path to greenstone cannot have spaces if one is going to do this
523 #2) cron.exe needs to be started manually before doing this
524 #3) greenstone may have to be shut down completely to do this or lock problems occur
525
526 $cronf="crontab"; #pycron.exe expects this filename!
527 $ncronf="crontab.new";
528 #check to see if crontab file exists
529 if(-e "$gsdl/collect/$cronf")
530 {
531
532 open($of, "$gsdl/collect/$cronf") ||
533 (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
534
535
536 open($nf, ">$gsdl/collect/$ncronf") ||
537 (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
538
539 while($record = <$of>)
540 {
541 if($record !~ /$colname/)
542 {
543 print $nf $record;
544 }
545 }
546 close($of);
547 close($nf);
548
549 system("del \"$gsdl\\collect\\$cronf\"");
550 system("move \"$gsdl\\collect\\$ncronf\" \"$gsdl\\collect\\$cronf\"");
551
552
553 my $shortf = Win32::GetShortPathName($gsdl);
554
555 my $command = "$shortf\\bin\\windows\\silentstart $shortf\\bin\\windows\\perl\\bin\\perl $shortf\\collect\\$colname\\cron.pl\n";
556
557 if($action =~ /^add$/ || $action =~ /^update$/)
558 {
559 open($nf, ">>$gsdl/collect/$cronf") ||
560 (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
561
562 if($frequency eq "hourly") {
563 print $nf "50 * * * * $command";
564 }
565 elsif($frequency eq "daily") {
566 print $nf "00 0 * * * $command";
567 }
568 elsif($frequency eq "weekly") {
569 print $nf "59 11 * * 0 $command";
570 }
571 close($nf);
572 }
573
574 } else {
575
576 my $shortf = Win32::GetShortPathName($gsdl);
577
578 my $command = "$shortf\\bin\\windows\\silentstart $shortf\\bin\\windows\\perl\\bin\\perl $shortf\\collect\\$colname\\cron.pl\n";
579
580
581 if($action =~ /^add$/ || $action =~ /^update$/)
582 {
583 open($nf, ">$gsdl/collect/$cronf") ||
584 (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
585 if($frequency eq "hourly") {
586 print $nf "50 * * * * $command";
587 }
588 elsif($frequency eq "daily") {
589 print $nf "00 0 * * * $command";
590 }
591 elsif($frequency eq "weekly") {
592 print $nf "59 11 * * 0 $command";
593 }
594
595 close($nf);
596 }
597 }
598
599 if($action eq "update" || $action eq "add") {
600 &gsprintf($out, "{schedule.cron}\n");
601 }
602 }
603
604 #For the scheduling monitor
605 print STDERR "<Done>\n" if $gli;
606
607
608
609} #end sub main
Note: See TracBrowser for help on using the repository browser.