App-CLI-Plugin-Proc-PID-File
view release on metacpan or search on metacpan
lib/App/CLI/Plugin/Proc/PID/File.pm view on Meta::CPAN
package App::CLI::Plugin::Proc::PID::File;
=pod
=head1 NAME
App::CLI::Plugin::Proc::PID::File - for App::CLI::Extension pidfile plugin module
=head1 VERSION
1.3
=head1 SYNOPSIS
# MyApp.pm
package MyApp;
use strict;
use base qw(App::CLI::Extension);
# extension method
__PACKAGE__->load_plugins(qw(Proc::PID::File));
# extension method
__PACKAGE__->config( proc_pid_file => { verify => 1, dir => "/var/run", name => "myapp" } );
1;
# MyApp/Hello.pm
package MyApp::Hello;
use strict;
use feature ":5.10.0";
use base qw(App::CLI::Command);
sub run {
my($self, @args) = @_;
# make pid file (/var/run/myapp.pid)
# /var/run/myapp.pid is automatically deleted (by Proc::PID::File::DESTROY)
$self->pf->touch;
}
=head1 DESCRIPTION
App::CLI::Extension pidfile plugin module
pf method setting
__PACKAGE__->config( proc_pid_file => {%proc_pid_file_option} );
Proc::PID::File option is L<Proc::PID::File> please refer to
=cut
use strict;
use warnings;
use base qw(Class::Accessor::Grouped);
use Fcntl qw(:DEFAULT :flock);
use File::Basename;
use File::Path;
use Proc::PID::File;
__PACKAGE__->mk_group_accessors(inherited => "pf");
our $VERSION = '1.3';
our $PROC_PID_FILE_RECOMENDED_VERSION = '1.37';
=pod
=head1 EXTENDED METHOD
=head2 Proc::PID::File::path
return pidfile path
Example:
# MyApp::Hello(App::CLI::Command base package)
sub run {
my($self, @args) = @_;
say $self->pf->path;
}
=cut
lib/App/CLI/Plugin/Proc/PID/File.pm view on Meta::CPAN
# name => "myapp"
}
);
Example2. pidfile option
myapp --pidfile=/tmp/myapp.pid
=cut
sub setup {
my($self, @argv) = @_;
my $pidfile;
my %option = (exists $self->config->{proc_pid_file}) ? %{$self->config->{proc_pid_file}} : ();
if (exists $option{pidfile} && defined $option{pidfile}) {
$pidfile = $option{pidfile};
}
if (exists $self->{pidfile} && defined $self->{pidfile}) {
$pidfile = $self->{pidfile};
}
if (defined $pidfile) {
# get name and path. fileparse is File::Basename function
my($name, $path) = fileparse($pidfile, qr/\.[^.]*$/);
$option{name} = $name;
$option{dir} = $path;
}
# make directory. mkpath is File::Path function
if (exists $option{dir} && !-d $option{dir}) {
mkpath($option{dir});
}
$self->pf(Proc::PID::File->new(%option));
$self->maybe::next::method(@argv);
}
####################################
# Proc::PID::File extended method
####################################
sub _path {
my $self = shift;
return $self->{path};
}
sub _alive {
my $self = shift;
$self->debug("alive(): for A::C::P::Proc::PID::File compat method");
my $pid = $self->read;
if (defined $pid) {
$self->debug("alive(): $pid");
} else {
$self->debug("alive(): not living my process");
return 0;
}
if ($pid != $$ && kill(0, $pid)) {
return $self->verify($pid) ? 1 : 0;
}
return 0;
}
sub _read {
my $self = shift;
$self->debug("read(): for A::C::P::Proc::PID::File compat method");
if (!-e $self->path) {
return;
}
open my $fh, "<", $self->path or die "can not open file ". $self->path . ": $!";
flock $fh, LOCK_EX | LOCK_NB or die "can not flock file " . $self->path . ": $!";
my($pid) = <$fh> =~ /^(\d{1,})$/;
close $fh or die "can not close file " . $self->path . ": $!";
$self->debug(sprintf "read(%s) = $pid", $self->path);
return $pid;
}
sub _touch {
my $self = shift;
$self->debug("touch(): for A::C::P::Proc::PID::File compat method");
$self->debug("write($$)");
open my $fh, ">", $self->path or die "can not open file ". $self->path . ": $!";
flock $fh, LOCK_EX | LOCK_NB or die "can not flock file " . $self->path . ": $!";
print $fh "$$\n";
close $fh or die "can not close file " . $self->path . ": $!";
}
1;
__END__
=head1 TIPS
=head2 Multi Launcher Lock Plugin
1. Make MultiBoot Lock Plugin
Example
package MyApp::Plugin::MultiLauncherLock;
use strict;
use feature ":5.10.0";
sub prerun {
my($self, @argv) = @_;
if ($self->pf->alive) {
my $pid = $self->pf->read;
die "already " . $self->argv0 . "[$pid] is running";
}
$self->pf->touch;
$self->maybe::next::method(@argv);
}
( run in 1.851 second using v1.01-cache-2.11-cpan-39bf76dae61 )