File Coverage

blib/lib/WE/Util/AtJobManager.pm
Criterion Covered Total %
statement 12 104 11.5
branch 0 42 0.0
condition 0 5 0.0
subroutine 4 14 28.5
pod 1 7 14.2
total 17 172 9.8


line stmt bran cond sub pod time code
1             # -*- perl -*-
2              
3             #
4             # $Id: AtJobManager.pm,v 1.4 2004/06/09 06:11:44 eserte Exp $
5             # Author: Slaven Rezic
6             #
7             # Copyright (C) 2004 Slaven Rezic. All rights reserved.
8             # This package is free software; you can redistribute it and/or
9             # modify it under the same terms as Perl itself.
10             #
11             # Mail: slaven@rezic.de
12             # WWW: http://www.rezic.de/eserte/
13             #
14              
15             package WE::Util::AtJobManager;
16              
17 1     1   930 use strict;
  1         2  
  1         30  
18 1     1   5 use vars qw($VERSION);
  1         2  
  1         63  
19             $VERSION = sprintf("%d.%02d", q$Revision: 1.4 $ =~ /(\d+)\.(\d+)/);
20              
21 1     1   5 use base qw(Class::Accessor);
  1         2  
  1         70  
22              
23 1     1   6 use WE::Util::Functions qw(is_in_path);
  1         2  
  1         1146  
24              
25             __PACKAGE__->mk_accessors(qw(at_path at_queue));
26              
27             sub new {
28 0     0 1   my($class, @args) = @_;
29 0           my $self = bless {}, $class;
30 0           $self->init(@args);
31 0           $self;
32             }
33              
34             sub init {
35 0     0 0   my($self, %args) = @_;
36 0 0         if (!$self->at_path) {
37 0           my $path = is_in_path("at");
38 0 0         if (!$path) {
39 0           $path = "/usr/bin/at";
40 0 0         undef $path if (!-x $path);
41             }
42 0 0         die "Can't find `at' command" if !$path;
43 0           $self->at_path("at");
44             }
45              
46 0   0       my $queue = $args{queue} || "c";
47 0           $self->at_queue($queue);
48             }
49              
50             sub start_job {
51 0     0 0   my($self, $time, $command, $args) = @_;
52 0           my @cmd = $command;
53 0 0         if ($args) {
54 0           push @cmd, @$args;
55             }
56 0 0         if (!@cmd) {
57 0           die "No command supplied";
58             }
59              
60 0           $time = $self->_epoch_to_crontime($time);
61              
62 0           my @at_cmd = $self->at_path;
63 0 0         if ($self->at_queue) {
64 0           push @at_cmd, "-q" => $self->at_queue;
65             }
66 0           push @at_cmd, $time;
67 0           my $pid_status;
68 0     0     local $SIG{CHLD} = sub { $pid_status = $? }; # linux reaps by default
  0            
69 0           local $SIG{PIPE} = "IGNORE";
70 0 0         my $pid = open(AT, "|-") or do {
71 0           warn "@at_cmd\n";
72 0           exec @at_cmd;
73 0           die "Can't run @at_cmd: $!";
74             };
75 0           warn "@cmd\n";
76 0           print AT "@cmd\n";
77 0           close AT;
78 0           waitpid($pid, 0);
79 0 0         if ($pid_status != 0) {
80 0           die "at job failed to start and returned exit code $pid_status";
81             }
82             }
83              
84             sub list_jobs {
85 0     0 0   my $self = shift;
86              
87 0           require Time::Local;
88              
89 0           my @jobs;
90 0           my $queue = $self->at_queue;
91 0 0         open(ATQ, $self->at_path . " -l -q $queue |")
92             or die "Can't call at -l";
93 0           while() {
94 0           chomp;
95 0           my($jobnr, $date, $time, $queue, $user) = split /\s+/;
96 0           my($Y,$M,$D) = split /-/, $date;
97 0           my($h,$m) = split /:/, $time;
98 0           my $epoch = Time::Local::timelocal(0, $m, $h, $D, $M-1, $Y-1900);
99 0           push @jobs, {jobnumber => $jobnr,
100             date => $date,
101             time => $time,
102             queue => $queue,
103             user => $user,
104             epoch => $epoch,
105             };
106             }
107 0           close ATQ;
108 0           @jobs;
109             }
110              
111             sub delete_job {
112 0     0 0   my($self, $jobnr) = @_;
113 0           system($self->at_path, "-d", $jobnr);
114             }
115              
116             sub check_daemon {
117 0     0 0   my $self = shift;
118 0           my $atd_running = $self->_check_process("atd");
119 0 0         return 1 if $atd_running;
120              
121 0 0         if ($^O =~ /bsd/i) {
122 0           my $cron_running = $self->_check_process("cron");
123 0 0         return 0 if !$cron_running;
124              
125 0           my $found_atrun;
126 0 0         open(CRONTAB, "/etc/crontab") or die "Can't open crontab: $!";
127 0           while() {
128 0 0         m{/usr/libexec/atrun} and do {
129 0           $found_atrun = 1;
130 0           last;
131             }
132             }
133 0           close CRONTAB;
134 0 0         return 1 if $found_atrun;
135              
136 0           die "Can't find atrun entry in /etc/crontab";
137             }
138              
139 0           0;
140             }
141              
142             sub restart_daemon {
143 0 0   0 0   if (-x "/etc/init.d/atd") {
144 0           system "/etc/init.d/atd", "start";
145 0           return $? == 0;
146             }
147              
148 0 0         if ($^O =~ /bsd/i) {
149 0           system "/usr/sbin/cron";
150 0           return $? == 0;
151             }
152              
153 0           die "Don't know how to restart the atd/crond daemon";
154             }
155              
156             sub _check_process {
157 0     0     my($self, $procname) = @_;
158 0 0         if (open(PID, "/var/run/$procname.pid")) {
159 0           chomp(my $pid = );
160 0           close PID;
161 0 0         if (defined $pid) {
162 0 0 0       if (kill 0 => $pid or $!{EPERM}) {
163 0           return 1;
164             } else {
165 0           return 0;
166             }
167             }
168             }
169 0           return 0;
170             }
171              
172             sub _epoch_to_crontime {
173 0     0     my($self, $time) = @_;
174              
175 0           my @l = localtime $time;
176 0           $l[4]++;
177 0           $l[5]+=1900;
178 0           sprintf "%02d:%02d %02d.%02d.%04d", @l[2,1,3,4,5];
179             }
180              
181             return 1 if caller;
182              
183             my $ajm = __PACKAGE__->new;
184             my $method = shift;
185             if ($method eq 'start_job') {
186             $ARGV[2] = [ splice @ARGV, 2 ];
187             }
188             my @res = $ajm->$method(@ARGV);
189             require Data::Dumper;
190             print "The result is:\n" . Data::Dumper::Dumper(@res) . "\n";
191              
192             __END__