Acme-Ghost

 view release on metacpan or  search on metacpan

eg/ghost_acme.pl  view on Meta::CPAN

    logfile => 'daemon.log',
    pidfile => 'daemon.pid',
);

exit $g->ctrl(shift(@ARGV) // 'start'); # start, stop, restart, reload, status

1;

package MyGhost;

use parent 'Acme::Ghost';

sub init {
    my $self = shift;
    $SIG{HUP} = sub { $self->hangup }; # Listen USR2 (reload)
}
sub hangup {
    my $self = shift;
    $self->log->debug("Hang up!");
}
sub startup {

eg/ghost_ae.pl  view on Meta::CPAN

    logfile => 'daemon.log',
    pidfile => 'daemon.pid',
);

exit $g->ctrl(shift(@ARGV) // 'start', 0); # start, stop, restart, reload, status

1;

package MyGhost;

use parent 'Acme::Ghost';
use AnyEvent;

sub startup {
    my $self = shift;
    my $quit = AnyEvent->condvar;
    my $i = 0;

    # Create watcher timer
    my $watcher = AnyEvent->timer (after => 1, interval => 1, cb => sub {
        $quit->send unless $self->ok;

eg/ghost_ioloop.pl  view on Meta::CPAN

    logfile => 'daemon.log',
    pidfile => 'daemon.pid',
);

exit $g->ctrl(shift(@ARGV) // 'start', 0); # start, stop, restart, reload, status

1;

package MyGhost;

use parent 'Acme::Ghost';
use Mojo::IOLoop;

sub init {
    my $self = shift;
    $self->{loop} = Mojo::IOLoop->new;
}
sub startup {
    my $self = shift;
    my $loop = $self->{loop};
    my $i = 0;

eg/ghost_nobody.pl  view on Meta::CPAN

    user    => 'nobody',
    group   => 'nogroup',
);

exit $g->ctrl(shift(@ARGV) // 'start', 0); # start, stop, restart, status

1;

package MyGhost;

use parent 'Acme::Ghost';

sub startup {
    my $self = shift;
    my $max = 100;
    my $i = 0;
    while ($self->ok) {
        $i++;
        sleep 3;
        $self->log->debug(sprintf("> %d/%d", $i, $max));
        last if $i >= $max;

eg/prefork_acme.pl  view on Meta::CPAN

my $g = MyGhost->new(
    logfile => 'daemon.log',
    pidfile => 'daemon.pid',
);
exit $g->ctrl(shift(@ARGV) // 'start');

1;

package MyGhost;

use parent 'Acme::Ghost::Prefork';
use Data::Dumper qw/Dumper/;

sub init {
    my $self = shift;
    $SIG{HUP} = sub { $self->hangup };
}
sub hangup {
    my $self = shift;
    $self->log->debug(Dumper($self->{pool}));
}

eg/prefork_ioloop.pl  view on Meta::CPAN

my $g = MyGhost->new(
    logfile => 'daemon.log',
    pidfile => 'daemon.pid',
);
exit $g->ctrl(shift(@ARGV) // 'start');

1;

package MyGhost;

use parent 'Acme::Ghost::Prefork';
use Mojo::IOLoop;

sub init {
    my $self = shift;
    $self->{loop} = Mojo::IOLoop->new;
}
sub spirit {
    my $self = shift;
    my $loop = $self->{loop};
    my $max = 10;

lib/Acme/Ghost.pm  view on Meta::CPAN

        logfile => 'daemon.log',
        pidfile => 'daemon.pid',
    );

    exit $g->ctrl(shift(@ARGV) // 'start'); # start, stop, restart, reload, status

    1;

    package MyGhost;

    use parent 'Acme::Ghost';

    sub init {
        my $self = shift;
        $SIG{HUP} = sub { $self->hangup }; # Listen USR2 (reload)
    }
    sub hangup {
        my $self = shift;
        $self->log->debug("Hang up!");
    }
    sub startup {

lib/Acme/Ghost.pm  view on Meta::CPAN

        logfile => 'daemon.log',
        pidfile => 'daemon.pid',
    );

    exit $g->ctrl(shift(@ARGV) // 'start', 0); # start, stop, restart, reload, status

    1;

    package MyGhost;

    use parent 'Acme::Ghost';
    use Mojo::IOLoop;

    sub init {
        my $self = shift;
        $self->{loop} = Mojo::IOLoop->new;
    }
    sub startup {
        my $self = shift;
        my $loop = $self->{loop};
        my $i = 0;

lib/Acme/Ghost.pm  view on Meta::CPAN

        logfile => 'daemon.log',
        pidfile => 'daemon.pid',
    );

    exit $g->ctrl(shift(@ARGV) // 'start', 0); # start, stop, restart, reload, status

    1;

    package MyGhost;

    use parent 'Acme::Ghost';
    use AnyEvent;

    sub startup {
        my $self = shift;
        my $quit = AnyEvent->condvar;
        my $i = 0;

        # Create watcher timer
        my $watcher = AnyEvent->timer (after => 1, interval => 1, cb => sub {
            $quit->send unless $self->ok;

lib/Acme/Ghost.pm  view on Meta::CPAN

        user    => 'nobody',
        group   => 'nogroup',
    );

    exit $g->ctrl(shift(@ARGV) // 'start', 0); # start, stop, restart, status

    1;

    package MyGhost;

    use parent 'Acme::Ghost';

    sub startup {
        my $self = shift;
        my $max = 100;
        my $i = 0;
        while ($self->ok) {
            $i++;
            sleep 3;
            $self->log->debug(sprintf("> %d/%d", $i, $max));
            last if $i >= $max;

lib/Acme/Ghost.pm  view on Meta::CPAN

    $self->{_log} = undef; # Close log handlers before spawn

    # Spawn
    my $pid = _fork();
    if ($pid) {
        _debug("!! Spawned (PID=%s)", $pid);
        if ($safe) { # For internal use only
            $self->{pid} = $pid; # Store child PID to instance
            return $self;
        }
        exit 0; # exit parent process
    }

    # Child
    $self->{daemonized} = 1; # Set daemonized flag
    $self->filepid->pid($$)->save; # Set new PID and Write PID file
    chown($uid, $gid, $pid_file) if IS_ROOT && -e $pid_file;

    # Set GID and UID
    $self->set_gid->set_uid;

lib/Acme/Ghost.pm  view on Meta::CPAN

# Process
sub flush { # Flush process counters
    my $self = shift;
    $self->{interrupt} = 0;
    $self->{signo} = 0;
    $self->{ok} = 1;
    return $self;
}
sub ok {
    my $self = shift;
    return 0 unless defined $self->{ppid}; # No parent pid found (it is not a daemon?)
    return $self->{ok} ? 1 : 0;
}

# LSB Daemon Control Methods
# These methods can be used to control the daemon behavior.
# Every effort has been made to have these methods DWIM (Do What I Mean),
# so that you can focus on just writing the code for your daemon
sub _term {
    my $self = shift;
    my $signo = shift || 0;

lib/Acme/Ghost.pm  view on Meta::CPAN

        $self->cleanup(1);
        $self->log->fatal(sprintf("Ghost process %s forcefully terminated on signal %s", $self->pid, $signo));
        $self->filepid->remove;
        POSIX::_exit(1);
    }
    $self->{interrupt}++;
}
sub start {
    my $self = shift;
    $self->daemonize(1); # First daemonize and switch to child process
    return 0 unless $self->is_daemonized; # Exit from parent process

    # Signals Trapping for interruption
    local $SIG{INT}  = sub { $self->_term(SIGINT) };  # 2
    local $SIG{TERM} = sub { $self->_term(SIGTERM) }; # 15
    local $SIG{QUIT} = sub { $self->_term(SIGQUIT) }; # 3

    $self->flush; # Flush process counters
    $self->log->info(sprintf("Ghost process %s started", $self->pid));
    $self->startup(); # Master hook
    $self->log->info(sprintf("Ghost process %s stopped", $self->pid));

lib/Acme/Ghost/Prefork.pm  view on Meta::CPAN

    my $g = MyGhost->new(
        logfile => 'daemon.log',
        pidfile => 'daemon.pid',
    );
    exit $g->ctrl(shift(@ARGV) // 'start');

    1;

    package MyGhost;

    use parent 'Acme::Ghost::Prefork';
    use Data::Dumper qw/Dumper/;

    sub init {
        my $self = shift;
        $SIG{HUP} = sub { $self->hangup };
    }
    sub hangup {
        my $self = shift;
        $self->log->debug(Dumper($self->{pool}));
    }

lib/Acme/Ghost/Prefork.pm  view on Meta::CPAN

    my $g = MyGhost->new(
        logfile => 'daemon.log',
        pidfile => 'daemon.pid',
    );
    exit $g->ctrl(shift(@ARGV) // 'start');

    1;

    package MyGhost;

    use parent 'Acme::Ghost::Prefork';
    use Mojo::IOLoop;
    use Data::Dumper qw/Dumper/;

    sub init {
        my $self = shift;
        $self->{loop} = Mojo::IOLoop->new;
    }
    sub spirit {
        my $self = shift;
        my $loop = $self->{loop};

lib/Acme/Ghost/Prefork.pm  view on Meta::CPAN


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

our $VERSION = '1.01';

use parent qw/Acme::Ghost/;

use Carp qw/carp croak/;
use POSIX qw/WNOHANG/;
use Time::HiRes qw//;
use Scalar::Util qw/weaken/;
use IO::Poll qw/POLLIN POLLPRI/;

use constant {
    DEBUG   => !!($ENV{ACME_GHOST_PREFORK_DEBUG} || 0),
    SPARE   => 2,

t/03-filepid.t  view on Meta::CPAN

    waitpid $child, 0;
    done_testing;
} else { # child process
    my $p = Acme::Ghost::FilePid->new(file => $file, autoremove => 1); # hope for the best
    unless ($p->running) {
       $p->save;
       note sprintf "Start child process (Child PID: %s; Child Owner: %s)", $p->pid, $p->owner;
       sleep 3;
       note sprintf "Finish child process (Child PID: %s; Child Owner: %s)", $p->pid, $p->owner;
    }
    #note 'parent is running' if $p->running;
}

__END__

prove -lv t/03-filepid.t



( run in 0.628 second using v1.01-cache-2.11-cpan-4d50c553e7e )