File Coverage

blib/lib/Cron/RunJob.pm
Criterion Covered Total %
statement 33 106 31.1
branch 0 36 0.0
condition 0 8 0.0
subroutine 11 18 61.1
pod 2 6 33.3
total 46 174 26.4


line stmt bran cond sub pod time code
1             package Cron::RunJob;
2              
3 1     1   31950 use 5.014002;
  1         4  
  1         39  
4 1     1   5 use strict;
  1         3  
  1         44  
5 1     1   5 use warnings;
  1         6  
  1         46  
6 1     1   10 use vars qw($AUTOLOAD);
  1         2  
  1         64  
7 1     1   6 use Scalar::Util 'refaddr';
  1         1  
  1         132  
8 1     1   1006 use Mail::Mailer;
  1         19883  
  1         6  
9 1     1   1020 use IO::Select;
  1         1566  
  1         42  
10 1     1   825 use IO::File;
  1         1959  
  1         128  
11 1     1   894 use IPC::Open3;
  1         2826  
  1         47  
12 1     1   6 use POSIX ":sys_wait_h";
  1         2  
  1         7  
13 1     1   1149 use Data::Dumper;
  1         14979  
  1         1322  
14              
15             require Exporter;
16              
17             our @ISA = qw(Exporter);
18             our %EXPORT_TAGS = ( 'all' => [ qw() ] );
19             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
20             our @EXPORT = qw();
21             our $VERSION = '0.06';
22              
23             my ($job_pid, %_data);
24             $SIG{TERM} = $SIG{INT} = sub {
25             kill 9, $job_pid if $job_pid;
26             exit;
27             };
28              
29             sub new {
30 0     0 1   my ($self, %opt) = @_;
31 0           $self = bless {}, $self;
32             $_data{refaddr $self}{uc $_} = $opt{$_}
33 0           for keys %opt;
34 0           return $self;
35             }
36              
37             sub runfile_name {
38 0     0 0   my ($self, $cmd) = @_;
39 0           $cmd =~ s/.*\///;
40 0   0       my $dir = $self->runfile_dir || '/var/run';
41 0           return $dir .'/'. $cmd . ".pid";
42             }
43              
44             sub create_runfile {
45 0     0 0   my ($self, $runfile) = @_;
46 0           my $fh = new IO::File;
47 0           $fh->open("> $runfile");
48 0 0         die $! unless defined $fh;
49 0           print $fh $self->pid;
50 0           $fh->close;
51             }
52              
53             sub unlink_runfile {
54 0     0 0   my ($self, $runfile) = @_;
55 0 0         if (-e $runfile) {
56 0 0         unlink $runfile or die $!;
57             }
58             }
59              
60             sub is_running {
61 0     0 0   my ($self, $runfile) = @_;
62 0 0         if (-e $runfile) {
63 0           my $fh = new IO::File;
64 0 0         die $! unless defined $fh;
65 0 0         $fh->open($runfile) or die "Open run file $runfile $!\n";
66 0           my $pid = <$fh>;
67 0           $fh->close;
68 0 0         return if $pid == $$;
69 0           $self->pid($pid);
70 0           return kill 0, $pid;
71             }
72 0           return 0;
73             }
74              
75             sub run {
76 0     0 1   my ($self, $cmd, @argv) = @_;
77            
78 0 0 0       if ($self->only_me and $self->is_running($self->runfile_name($cmd))) {
79 0           $self->stderr("Proccess is already running");
80 0           $self->failed(1);
81 0           return 0;
82             }
83            
84 0           my $select = IO::Select->new();
85 0           my $chld_stderr = new IO::File;
86 0           my $chld_stdin = new IO::File;
87 0           my $chld_stdout = new IO::File;
88              
89 0           $job_pid = open3($chld_stdin, $chld_stdout, $chld_stderr, $cmd, @argv);
90 0           $self->pid($job_pid);
91 0 0         $self->create_runfile($self->runfile_name($cmd))
92             if $self->only_me;
93            
94 0           $select->add($chld_stderr);
95 0           $select->add($chld_stdout);
96              
97 0           my ($buff, $std_error, $std_out);
98 0           foreach my $fh ($select->can_read) {
99 0           while (my $buff = <$fh>) {
100 0 0         if ($fh == $chld_stderr) {
    0          
101 0           $std_error .= $buff;
102             } elsif ($fh == $chld_stdout) {
103 0           $std_out .= $buff;
104             }
105             }
106             }
107              
108 0           $chld_stderr->close;
109 0           $chld_stdout->close;
110 0           $chld_stdin->close;
111            
112 0           waitpid($job_pid, 0);
113            
114 0 0         if ($std_error) {
115 0           $self->stderr($std_error);
116 0 0         if ($self->mail_stderr) {
117 0           my $mailer = new Mail::Mailer 'sendmail';
118 0           $mailer->open({
119             To => $self->mail_to,
120             From => $self->mail_from,
121             Subject => 'STDERR: '. $self->mail_subject,
122             });
123              
124 0 0         print $mailer "Error: $cmd failed with error(s): ".($std_error ? $std_error:'unknown errors')."\n";
125 0           $mailer->close;
126             }
127 0           $self->failed(1);
128             } else {
129 0           $self->failed(0);
130 0           $self->stdout($std_out);
131 0 0         if ($self->mail_stdout) {
132 0           my $mailer = new Mail::Mailer 'sendmail';
133 0           $mailer->open({
134             From => $self->mail_from,
135             To => $self->mail_to,
136             Subject => 'STDOUT: '. $self->mail_subject,
137             });
138            
139 0           print $mailer $self->stdout;
140             }
141             }
142              
143 0 0         $self->unlink_runfile($self->runfile_name($cmd))
144             if $self->only_me;
145             }
146              
147             sub AUTOLOAD {
148 0     0     my $self = shift;
149 0           (my $attr = $AUTOLOAD) =~ s/^.*:://;
150 0 0 0       if (exists $_data{refaddr $self}->{uc $attr} and $_data{refaddr $self}->{uc $attr}) {
151 0           return $_data{refaddr $self}->{uc $attr};
152             } else {
153 0           my $value = shift;
154 0 0         $_data{refaddr $self}->{uc $attr} = $value if $value;
155             }
156             }
157              
158             1;
159             __END__