File Coverage

blib/lib/Logic/Tools.pm
Criterion Covered Total %
statement 79 144 54.8
branch 10 54 18.5
condition 4 25 16.0
subroutine 12 14 85.7
pod 6 7 85.7
total 111 244 45.4


line stmt bran cond sub pod time code
1             package Logic::Tools;
2              
3 4     4   14470 use 5.10.1;
  4         9  
  4         130  
4 4     4   12 use strict;
  4         4  
  4         92  
5 4     4   15 use warnings;
  4         25  
  4         90  
6 4     4   2322 use Config::IniFiles;
  4         107821  
  4         117  
7 4     4   1878 use File::stat;
  4         16517  
  4         24  
8 4     4   2504 use Archive::Tar;
  4         250466  
  4         238  
9             #use Time::localtime;
10              
11 4     4   1874 use POSIX;
  4         15318  
  4         18  
12              
13             =head1 NAME
14            
15             Voiecng::Tools - The great new Logic::Tools!
16            
17             =head1 VERSION
18            
19             Version 0.4.5
20            
21             =cut
22              
23             my @ISA = qw(Logic);
24             our $VERSION = '0.4.5';
25              
26              
27             =head1 SYNOPSIS
28            
29             Quick summary of what the module does.
30            
31             Perhaps a little code snippet.
32            
33             use Logic::Tools;
34            
35             my $foo = Logic::Tools->new();
36             ...
37            
38             =head1 EXPORT
39            
40             A list of functions that can be exported. You can delete this section
41             if you don't export anything, such as for a purely object-oriented module.
42            
43             =head1 SUBROUTINES/METHODS
44             =cut
45              
46             =head1 constructor
47             =cut
48              
49             sub new
50             {
51 12     12 1 1350     $SIG{INT} = \&close_prog;
52 12         46     $SIG{QUIT} = \&close_prog;
53 12         30     $SIG{TERM} = \&close_prog;
54              
55 12         39     $SIG{CHLD} = 'IGNORE';
56              
57 12         23     my $invocant = shift; # первый параметр - ссылка на объект или имя класса
58 12   66     61     my $class = ref($invocant) || $invocant; # получение имени класса
59 12         80     my $self = { @_ }; # ссылка на анонимный хеш - это и будет нашим новым объектом, инициализация объекта
60 12         14     my $log_level;
61              
62 12         14     $self->{NAME}=$invocant;
63 12         17     $self->{VERSION}=$VERSION;
64            
65 12         40     bless($self, $class); # освящаем ссылку в объект
66 12         23     return $self; # возвращаем объект
67             }
68              
69             =head1 METHODS
70             =cut
71              
72             sub read_config
73             {
74 3     3 1 1422 my $model=shift;
75 3         18     my $self=$model->new(%$model,@_);
76              
77 3         3     my $config_file = $self->{'config_file'};
78 3   50     6 my $section = shift || die "[FAILED] Не задана секция для чтения конфига";
79 3   50     12 my $param = shift || die "[FAILED] Не задан параметр для чтения конфига";
80              
81 3 50       15     my $cfg=new Config::IniFiles( -file => $config_file ) or die "[FAILED]] Не найден конфигурационный файл $config_file";
82              
83 3         1818 my $value = $cfg->val( $section, $param);
84              
85 3 50       48 die "[FAILED] Не найден параметр ".$param." в секции ".$section unless(defined($value));
86              
87 3         39 return $value;
88             }
89              
90              
91             sub check_proc
92             {
93 3     3 1 3     my $model=shift;
94 3         9     my $self=$model->new(%$model,@_);
95              
96 3         6     my $pid_f = $self->{'lock_file'};
97                 
98             # Проверяем запущен ли уже процесс
99 3 50       39     if( -e $pid_f )
100                 {
101              
102 0 0       0         open(my $pid_file,'<',$pid_f) || die "[FAILED] can't open $pid_f";
103 0         0         my $pid=<$pid_file>;
104 0         0         close $pid_file;
105 0         0         chomp $pid;
106                     
107             # Процесс запущен, но активного процесса с указанным PID нет
108 0 0       0         unless( -e "/proc/$pid" )
109                     {
110             #print STDERR "Файл блокировки уже существует, но демон с pid=$pid не существует\n";
111 0 0       0             die "[FAILED] can't delete file $pid_f\n" if ( !unlink $pid_f );
112             #print STDERR "Файл блокировки удален\n";
113                     }
114                     else
115                     {
116 0         0             die "process alredy run pid=$pid\n";
117                     }
118                 }
119 3         15     return 1;
120             } 
121              
122              
123             sub logprint
124             {
125 1     1 1 8     my $model=shift;
126 1         13     my $self=$model->new(%$model,@_);
127              
128 1         1     my $loglevel=shift;
129 1         33     my $message=shift;
130              
131 1         97     my ($sec, $min, $hour, $day, $mon, $year) = ( localtime(time) )[0,1,2,3,4,5];
132                 
133             #высчитывае максимальный размер лога в байтах
134 1 50       6     if(defined($self->{'logsize'}))
135                 {
136 0         0         my $logsize=$self->{'logsize'};
137 0         0         my $lognum;
138              
139 0 0       0         if(!defined($self->{'log_num'}))
140                     {
141 0         0             $lognum=1;
142                     }
143                     else
144                     {
145 0         0             $lognum=$self->{'log_num'};
146                     }
147                     
148            
149 0 0       0         if($self->{'logsize'}=~/^(\d+)(.{2})$/)
150                     {
151 0 0 0     0             if(($2 eq "Kb")||($2 eq "KB")||($2 eq "kb"))
    0 0        
    0 0        
      0        
      0        
      0        
152                         {
153 0         0                 $logsize=$1*1024;
154                         }
155                         elsif(($2 eq "Mb")||($2 eq "MB")||($2 eq "mb"))
156                         {
157 0         0                 $logsize=$1*1024*1024;
158                         }
159                         elsif(($2 eq "Gb")||($2 eq "GB")||($2 eq "gb"))
160                         {
161 0         0                 $logsize=$1*1024*1024*1024;
162                         }
163                     }
164              
165              
166 0         0         my $statfile = stat($self->{'logfile'});
167 0 0       0         if(defined($statfile))
168                     {
169 0         0             my $size = $statfile->size;
170                 
171 0 0       0             if($size>$logsize)
172                         {
173            
174 0         0                 my $filename;
175                             my $log_path;
176             #/home/jenkins_publish/deploy/11/deploy.log
177 0 0       0                 if($self->{'logfile'}=~/^(.+)\/(.+)\.log$/)
178                             {
179 0         0                     $log_path=$1;
180 0         0                     $filename=$2;
181                             }
182              
183             #проверяем количество файлов которые уже есть в логах
184 0         0                 my @gz_files_list = glob($log_path.'/'.$filename.'*.gz');
185              
186 0         0                 my $log_file_exist=scalar(@gz_files_list);
187              
188             #количество лишних файлов
189 0         0                 my $num_of_redundant_files;
190              
191 0 0       0                 if($log_file_exist>=$lognum)
192                             {
193 0         0                     $num_of_redundant_files=$log_file_exist-$lognum;
194 0         0                     for(my $i=0;$i<=$num_of_redundant_files;$i++)
195                                 {
196 0         0                         unlink($gz_files_list[$i]);
197                                 }
198                             }
199              
200                             
201              
202              
203 0         0                 my $tar = Archive::Tar->new;
204 0         0                 $tar->add_files($self->{'logfile'});
205            
206             #формируем суффикс чтобы
207 0         0                 my $suffix=sprintf("%04d%02d%02d%02d%02d%02d",$year+1900,$mon+1,$day,$hour,$min,$sec);
208              
209 0 0       0                 $tar->write($log_path."/".$filename.'-'.$suffix.'.gz', COMPRESS_GZIP) or die "error";
210             #удаляем лог
211 0         0                 unlink($self->{'logfile'});
212                         }
213                     }
214                     
215              
216              
217                     
218                 }
219                 
220 1 50       102     open my $logfile,">>",$self->{'logfile'} or die "ERROR: can't open file\n";
221              
222 1         19     printf $logfile ("%04d/%02d/%02d %02d:%02d:%02d [%d] %s: %s\n",$year+1900,$mon+1,$day,$hour,$min,$sec,$$,$loglevel,$message);
223              
224 1         34     close($logfile);
225              
226 1         9     return 1;
227             }
228              
229             sub start_daemon
230             {
231 2     2 1 1998     my $model=shift;
232 2         154     my $self=$model->new(%$model,@_);
233              
234 2         18     my $runas_user=$self->{'runas_user'};
235 2         18     my $lock_file=$self->{'lock_file'};
236              
237 2 50       726     my ($name, $passwd, $uid, $gid) = getpwnam($runas_user) or die "[FAILED] Невозможно запуститься под $runas_user";
238                 
239 2         2245     my $pid = fork();
240                 
241 2 50       67     die "[FAILED] Не удается создать форк: $!" unless(defined($pid));
242                 
243                  
244 2 100       41     if($pid)
245                 {
246             # Запись файле блокировки
247 1 50       184         open(my $pid_file, ">" ,$lock_file) || die "[FAILED] Не удалось создать файл блокировки $lock_file\n";
248 1         26         print $pid_file "$pid";
249 1         50         close $pid_file;
250 1         39         chown $uid, $gid, $lock_file;
251 1         160         exit;
252                 }
253                 else
254                 {
255             # daemon
256 1         31         setpgrp();
257 1         34         select(STDERR); $| = 1;
  1         21  
258 1         9         select(STDOUT); $| = 1;
  1         9  
259             #syslog(LOG_INFO, "---------------------------------------");
260             #syslog(LOG_INFO, "Скрипт запущен");
261                 }
262              
263             # Сброс привилегий
264 1         45     setuid($uid);
265 1         26     $< = $uid;
266 1         16     $> = $uid;
267              
268 1         84     return 1;
269             }
270              
271              
272             #старт демона супервизором
273             #первый порожденный пид
274             my $first_child_pid=0;
275             sub supervisor_start_daemon
276             {
277 0     0 1       my $model=shift;
278 0               my $self=$model->new(%$model,@_);
279              
280 0               my $runas_user=$self->{'runas_user'};
281 0               my $lock_file=$self->{'lock_file'};
282              
283 0 0             my ($name, $passwd, $uid, $gid) = getpwnam($runas_user) or die "[FAILED] can't start under the $runas_user";
284                 
285 0               $first_child_pid = fork();
286                 
287 0 0             die "[FAILED] can't create fork: $!" unless(defined($first_child_pid));
288                 
289                  
290 0 0             if($first_child_pid)
291                 {
292             # Запись файле блокировки
293 0 0                 open(my $pid_file, ">" ,$lock_file) || die "[FAILED] can't create block file $lock_file\n";
294 0                   print $pid_file "$first_child_pid";
295 0                   close $pid_file;
296 0                   chown $uid, $gid, $lock_file;
297 0                   while(1)
298                     {
299             # Процесс запущен, но активного процесса с указанным PID нет
300              
301 0 0                     unless( -e "/proc/$first_child_pid" )
302                         {
303 0                           die "child $first_child_pid dead, exit\n";
304 0                           exit;
305                         }
306 0                       sleep(1);
307                     }
308                 }
309                 else
310                 {
311             # daemon
312 0                   setpgrp();
313 0                   select(STDERR); $| = 1;
  0            
314 0                   select(STDOUT); $| = 1;
  0            
315                 }
316              
317             # Сброс привилегий
318 0               setuid($uid);
319 0               $< = $uid;
320 0               $> = $uid;
321             }
322              
323             sub close_prog
324             {   
325             #отправка сигнала завершения дочернему процессу
326 0     0 0   kill("TERM",$first_child_pid);
327 0           die "TERM signal recieved\n";
328 0               exit;
329             }
330              
331             =head1 AUTHOR
332            
333             lagutas, C<< <lagutas at gmail.com> >>
334            
335             =head1 BUGS
336            
337             Please report any bugs or feature requests to C<bug-logic-tools at rt.cpan.org>, or through
338             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Logic-Tools>. I will be notified, and then you'll
339             automatically be notified of progress on your bug as I make changes.
340            
341            
342            
343            
344             =head1 SUPPORT
345            
346             You can find documentation for this module with the perldoc command.
347            
348             perldoc Logic::Tools
349            
350            
351             You can also look for information at:
352            
353             =over 4
354            
355             =item * RT: CPAN's request tracker (report bugs here)
356            
357             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Logic-Tools>
358            
359             =item * AnnoCPAN: Annotated CPAN documentation
360            
361             L<http://annocpan.org/dist/Logic-Tools>
362            
363             =item * CPAN Ratings
364            
365             L<http://cpanratings.perl.org/d/Logic-Tools>
366            
367             =item * Search CPAN
368            
369             L<http://search.cpan.org/dist/Logic-Tools/>
370            
371             =back
372            
373            
374             =head1 ACKNOWLEDGEMENTS
375            
376            
377             =head1 LICENSE AND COPYRIGHT
378            
379             Copyright 2013 lagutas.
380            
381             This program is free software; you can redistribute it and/or modify it
382             under the terms of either: the GNU General Public License as published
383             by the Free Software Foundation; or the Artistic License.
384            
385             See http://dev.perl.org/licenses/ for more information.
386            
387            
388             =cut
389              
390             1; # End of Logic::Tools
391