CTKlib/lib/CTK/Skel/Daemon.pm
package CTK::Skel::Daemon;
use strict;
use utf8;
=encoding utf8
=head1 NAME
CTK::Skel::Daemon - Daemon project skeleton for CTK::Helper
=head1 VIRSION
Version 1.01
=head1 SYNOPSIS
none
=head1 DESCRIPTION
Daemon project skeleton for CTK::Helper
no public methods
=head2 build, dirs, pool
Main methods. For internal use only
=head1 SEE ALSO
L<CTK::Skel>, L<CTK::Helper>
=head1 AUTHOR
Serż Minus (Sergey Lepenkov) L<https://www.serzik.com> E<lt>abalama@cpan.orgE<gt>
=head1 COPYRIGHT
Copyright (C) 1998-2022 D&D Corporation. All Rights Reserved
=head1 LICENSE
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
See C<LICENSE> file and L<https://dev.perl.org/licenses/>
=cut
use constant SIGNATURE => "daemon";
use vars qw($VERSION);
$VERSION = '1.01';
sub build {
my $self = shift;
my $rplc = $self->{rplc};
$self->maybe::next::method();
return 1;
}
sub dirs {
my $self = shift;
$self->{subdirs}{(SIGNATURE)} = [
{
path => 'bin',
mode => 0755,
},
{
path => 'lib',
mode => 0755,
},
];
$self->maybe::next::method();
return 1;
}
sub pool {
my $self = shift;
my $pos = tell DATA;
my $data = scalar(do { local $/; <DATA> });
seek DATA, $pos, 0;
$self->{pools}{(SIGNATURE)} = $data;
$self->maybe::next::method();
return 1;
}
1;
__DATA__
-----BEGIN FILE-----
Name: %PROJECT_NAMEL%
File: bin/%PROJECT_NAMEL%
Mode: 711
#!/usr/bin/perl -w
use strict;
%PODSIG%head1 NAME
%PROJECT_NAMEL% - blah-blah-blah
%PODSIG%head1 SYNOPSIS
%PROJECT_NAMEL% [options] command [args]
%PROJECT_NAMEL% [-dvty] [-c /path/to/%PROJECT_NAMEL%.conf]
[-f 1] [-i 6] command [args]
%PROJECT_NAMEL% start
%PROJECT_NAMEL% stop
%PROJECT_NAMEL% status
%PROJECT_NAMEL% restart
%PROJECT_NAMEL% reload
%PODSIG%head1 OPTIONS
%PODSIG%over
%PODSIG%item B<-c /path/to/file.conf, --config=/path/to/file.conf>
Sets config file
Default: /etc/%PROJECT_NAMEL%/%PROJECT_NAMEL%.conf
%PODSIG%item B<-d, --debug>
Print debug information on STDOUT
%PODSIG%item B<-f N, --forks=N>
How many forks create on the one process. Default for agent: 1
Default: 1
%PODSIG%item B<-h, --help>
Show short help information and quit
%PODSIG%item B<-H, --longhelp>
Show long help information and quit
%PODSIG%item B<-i VALUE, --interval=VALUE>
Set the interval value between runs of the current and next operations.
For example, "6" i.e. one iteration per 6 seconds in one minute.
Default: 6
%PODSIG%item B<-t, --test>
Enable test mode
%PODSIG%item B<-v, --verbose>
Verbose option. Include Verbose debug data in the STDOUT and to error-log output
%PODSIG%item B<-V, --version>
Print the version number of the program and quit
%PODSIG%back
%PODSIG%head1 COMMANDS
%PODSIG%over
%PODSIG%item B<reload>
%PROJECT_NAMEL% reload
Reload daemon
%PODSIG%item B<restart>
%PROJECT_NAMEL% restart
Restart daemon
%PODSIG%item B<start>
%PROJECT_NAMEL% start
Start daemon
%PODSIG%item B<status>
%PROJECT_NAMEL% status
Get status of daemon
%PODSIG%item B<stop>
%PROJECT_NAMEL% stop
Stop daemon
%PODSIG%back
%PODSIG%head1 DESCRIPTION
blah-blah-blah
See C<README> file
%PODSIG%head1 HISTORY
See C<Changes> file
%PODSIG%head1 TO DO
See C<TODO> file
%PODSIG%head1 SEE ALSO
L<CTK>
%PODSIG%head1 AUTHOR
%AUTHOR% L<%HOMEPAGE%> E<lt>%ADMIN%E<gt>
%PODSIG%head1 COPYRIGHT
Copyright (C) %YEAR% %AUTHOR%. All Rights Reserved
%PODSIG%head1 LICENSE
This program is distributed under the GNU GPL v3.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
See C<LICENSE> file
%PODSIG%cut
use Getopt::Long;
use Pod::Usage;
use Sys::Syslog qw//;
use CTK::App;
use CTK::Daemon;
use %PROJECT_NAME%;
my %options;
Getopt::Long::Configure("bundling");
GetOptions(\%options,
# NoUsed keys map:
#
# a A b B C D e E
# F g G I j J
# k K l L m M n N o O
# p P q Q r R s S T
# u U w W x X y Y
# z Z
"help|usage|h", # Show help page
"longhelp|H", # Show long help page
"version|ver|V", # Show version
"debug|d", # Debug mode
"verbose|v", # Verbose mode
"test|testmode|t", # Test mode
"config|c=s", # Config file
"interval|i=i", # Operation interval (5, 10, 20, 30 secs)
"forks|f=i", # Forks
) || pod2usage(-exitval => 1, -verbose => 0, -output => \*STDERR);
pod2usage(-exitval => 0, -verbose => 1) if $options{help};
pod2usage(-exitval => 0, -verbose => 2) if $options{longhelp};
printf("Version: %s\n", %PROJECT_NAME%->VERSION) && exit(0) if $options{version};
my $command = shift(@ARGV);
my @arguments = @ARGV ? @ARGV : ();
pod2usage(-exitval => 1, -verbose => 99, -sections => 'SYNOPSIS|OPTIONS|COMMANDS', -output => \*STDERR)
unless $command && grep {$_ eq $command} @{(CTK::Daemon::LSB_COMMANDS())};
# CTK Singleton instance
my $ctk = CTK::App->new(
project => '%PROJECT_NAME%',
#ident => '%PROJECT_NAMEL%',
options => {%options},
debug => $options{debug},
verbose => $options{verbose},
log => 1,
test => $options{test},
logfacility => Sys::Syslog::LOG_DAEMON,
$options{config} ? (configfile => $options{config}) : (),
);
# Daemon
my $daemon = %PROJECT_NAME%->new('%PROJECT_NAMEL%',
ctk => $ctk,
forks => $options{forks},
interval=> $options{interval},
);
# Run
my $exitval = $daemon->ctrl($command);
exit $exitval;
-----END FILE-----
-----BEGIN FILE-----
Name: %PROJECT_NAME%.pm
File: lib/%PROJECT_NAME%.pm
Mode: 644
package %PROJECT_NAME%;
use strict;
%PODSIG%head1 NAME
%PROJECT_NAME% - %PROJECT_NAME% daemon
%PODSIG%head1 VERSION
Version %PROJECT_VERSION%
%PODSIG%head1 SYNOPSIS
use %PROJECT_NAME%;
%PODSIG%head1 DESCRIPTION
%PROJECT_NAME% daemon
%PODSIG%head2 new
See L<CTK::Daemon/"new">
%PODSIG%head2 init
See L<CTK::Daemon/"init">
%PODSIG%head2 run
See L<CTK::Daemon/"run">
%PODSIG%head2 down
See L<CTK::Daemon/"down">
%PODSIG%head1 HISTORY
%PODSIG%over
%PODSIG%item B<%PROJECT_VERSION% %GMT%>
Init version
%PODSIG%back
See C<Changes> file
%PODSIG%head1 SEE ALSO
L<CTK>, L<CTK::Daemon>
%PODSIG%head1 AUTHOR
%AUTHOR% E<lt>%ADMIN%E<gt>
%PODSIG%head1 COPYRIGHT
Copyright (C) %YEAR% %AUTHOR%. All Rights Reserved
%PODSIG%head1 LICENSE
This program is distributed under the GNU GPL v3.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
See C<LICENSE> file
%PODSIG%cut
use vars qw($VERSION);
$VERSION = '%PROJECT_VERSION%';
use base qw/CTK::Daemon/;
use constant {
FORKS => 1,
INTERVAL=> 1,
MAXITER => 10, # 10 iterations max
};
sub new {
my $class = shift;
my $name = shift;
my %daemon_options = @_;
$daemon_options{forks} //= FORKS;
my $self = $class->SUPER::new($name, %daemon_options);
$self->{interval} = $daemon_options{interval} || INTERVAL;
$self->logger->log_info("Daemon object created");
return $self;
}
# Before running
sub init {
my $self = shift; # Daemon object
$self->logger->log_info("Init here!");
}
sub run {
my $self = shift; # Daemon object
my $ctk = $self->get_ctk; # CTK object
my $logger = $self->logger; # Logger from daemon object for internal only (in Daemon context)
return 1 unless $self->ok; # Return with true status while any error occurred
my $iteration = 0; # Iteration number
my $interval = abs($self->{interval}) || INTERVAL; # Time interval. 1 op per n sec
$logger->log_info("Runned (ID=%d; PID=%d; Interval=%d)",
$self->{workerident},
$self->{workerpid},
$interval,
);
# Cycle
while ($self->ok) { # Check it every time
$iteration++;
last if $iteration > MAXITER;
$logger->log_info("=> iteration (ID=%d; PID=%d; Iteration=%d/%d)",
$self->{workerident},
$self->{workerpid},
$iteration, MAXITER
);
# If occurred usual error:
# $logger->log_error("...");
# next;
# If occurred exception error
# $logger->log_crit("...");
# $self->exception(1);
# last;
# For skip this loop
# $self->skip(1);
# next;
if ($ctk->testmode && $iteration == 3) {
$ctk->error("Test error, go to next iteration");
next;
}
if ($ctk->testmode && $iteration == 6) {
$ctk->error("Test fatal error");
$self->exception(1);
next;
}
last unless $self->ok; # Check it every time (after loop too)
} continue {
CTK::Daemon::mysleep $interval; # Delay!
}
return 1; # 0 if fatal errors occurred
}
sub down { # After process
my $self = shift;
my $logger = $self->logger;
my $ctk = $self->get_ctk;
$logger->log_info("Cleanup here!");
if ($self->exception) {
$logger->log_error("Exception error: %s", $ctk->error || "unknown error");
}
elsif ($self->interrupt) {
$logger->log_error("Aborted");
}
elsif ($self->skip) {
$logger->log_info("Skipped process");
}
else {
$logger->log_info("Normal finished");
}
return 1;
}
1;
-----END FILE-----
-----BEGIN FILE-----
Name: Makefile.PL
File: Makefile.PL
Mode: 755
#!/usr/bin/perl -w
use strict;
use lib qw/inc/;
use ExtUtils::MakeMaker;
use CTK;
use MY;
my $ctk = CTK->new( project => '%PROJECT_NAME%' );
WriteMakefile(
'NAME' => '%PROJECT_NAME%',
'DISTNAME' => '%PROJECT_NAME%',
'MIN_PERL_VERSION' => 5.016001,
'VERSION_FROM' => 'lib/%PROJECT_NAME%.pm',
'ABSTRACT_FROM' => 'lib/%PROJECT_NAME%.pm',
'PREREQ_PM' => {
'CTK' => %CTKVERSION%,
},
'EXE_FILES' => [qw(
bin/%PROJECT_NAMEL%
)],
'AUTHOR' => '%AUTHOR%, <%HOMEPAGE%>, <%ADMIN%>',
'LICENSE' => 'gpl',
'META_MERGE' => {
resources => {
homepage => '%HOMEPAGE%',
repository => 'https://my.git.com/%PROJECT_NAMEL%.git',
license => 'http://opensource.org/licenses/gpl-license.php',
},
},
macro => {
PROJECT_NAME => '%PROJECT_NAME%',
PROJECT_NAMEL => '%PROJECT_NAMEL%',
PROJECT_CONFDIR => $ctk->root,
},
clean => {
FILES => '$(INST_CONF) *.tmp',
},
);
1;
-----END FILE-----
-----BEGIN FILE-----
Name: MANIFEST
File: MANIFEST
Mode: 644
# Generated by CTKlib %CTKVERSION%
# General files
Changes Changes list
INSTALL Installation instructions
LICENSE License file
Makefile.PL Makefile builder
MANIFEST This file
README !!! README FIRST !!!
TODO TO DO
# Scripts
bin/%PROJECT_NAMEL%
# Libraries
lib/%PROJECT_NAME%.pm
# Includes
inc/README
inc/MY.pm
inc/PostConf.pm
# Configs
conf/%PROJECT_NAMEL%.conf
conf/conf.d/README
conf/conf.d/extra-log.conf
conf/conf.d/extra-sendmail.conf
# Tests
t/01-use.t
-----END FILE-----