Daemon-Control

 view release on metacpan or  search on metacpan

lib/Daemon/Control.pm  view on Meta::CPAN

            $self->trace("Set PID => $new_pid" );
            $self->write_pid;
            _exit 0;
        }
    } elsif ( not defined $pid ) { # We couldn't fork.  =(
        warn "Cannot fork: $!";
    } else { # In the parent, $pid = child's PID, return it.
        waitpid( $pid, 0 );
    }
    return $self;
}

sub _foreground { shift->_launch_program }

sub _fork {
    my ( $self ) = @_;
    my $pid = fork();

    $self->trace( "_fork()" );
    if ( $pid == 0 ) { # Child, launch the process here.
        $self->_launch_program;
    } elsif ( not defined $pid ) {
        warn "Cannot fork: $!";
    } else { # In the parent, $pid = child's PID, return it.
        $self->pid( $pid );
        $self->trace("Set PID => $pid" );
        $self->write_pid;
    }
    return $self;
}

sub _launch_program {
    my ($self) = @_;

    if ( $self->directory ) {
        chdir( $self->directory );
        $self->trace( "chdir(" . $self->directory . ")" );
    }

    my @args = @{$self->program_args || [ ]};

    if ( ref $self->program eq 'CODE' ) {
        $self->program->( $self, @args );
    } else {
        exec ( $self->program, @args )
            or die "Failed to exec " . $self->program . " "
                . join( " ", @args ) . ": $!";
    }
    return 0;
}

sub write_pid {
    my ( $self ) = @_;

    # Create the PID file as the user we currently are,
    # and change the permissions to our target UID/GID.

    $self->_write_pid;

    if ( $self->uid && $self->gid ) {
        chown $self->uid, $self->gid, $self->pid_file;
        $self->trace("PID => chown(" . $self->uid . ", " . $self->gid .")");
    }
}

sub _write_pid {
    my ( $self ) = @_;

    my ($volume, $dir, $file) = File::Spec->splitpath($self->pid_file);
    return 0 if not $self->_create_dir($dir);

    open my $sf, ">", $self->pid_file
        or die "Failed to write " . $self->pid_file . ": $!";
    print $sf $self->pid;
    close $sf;
    $self->trace( "Wrote pid (" . $self->pid . ") to pid file (" . $self->pid_file . ")" );
    return $self;
}

sub read_pid {
    my ( $self ) = @_;

    # If we don't have a PID file, we're going to set it
    # to 0 -- this will prevent killing normal processes,
    # and make is_running return false.
    if ( ! -f $self->pid_file ) {
        $self->pid( 0 );
        return 0;
    }

    open my $lf, "<", $self->pid_file
        or die "Failed to read " . $self->pid_file . ": $!";
    my $pid = do { local $/; <$lf> };
    close $lf;
    $self->pid( $pid );
    return $pid;
}

sub pid_running {
    my ( $self, $pid ) = @_;

    $pid ||= $self->read_pid;

    return 0 unless $self->pid >= 1;
    return 0 unless kill 0, $self->pid;

    if ( $self->scan_name ) {
        open my $lf, "-|", "ps", "-w", "-w", "-p", $self->pid, "-o", "command="
            or die "Failed to get pipe to ps for scan_name.";
        while ( my $line = <$lf> ) {
            return 1 if $line =~ $self->scan_name;
        }
        return 0;
    }
    # Scan name wasn't used, testing normal PID.
    return kill 0, $self->pid;
}

sub process_running {
    my ( $self, $pattern ) = @_;

    my $psopt = $^O =~ m/bsd$/ ? '-ax' : '-u ' . $self->user;

lib/Daemon/Control.pm  view on Meta::CPAN


=head2 init_code

When given, whatever text is in this field will be dumped directly into
the generated init file.

    $daemon->init_code( "Arbitrary code goes here." )

=head2 help

Any text in this accessor will be printed when the script is called
with the argument C<--help> or <help>.

    $daemon->help( "Read The Friendly Source." );

=head2 redirect_before_fork

By default this is set to true.  STDOUT will be redirected to C<stdout_file>,
and STDERR will be redirected to C<stderr_file>.  Setting this to 0 will disable
redirecting before a double fork.  This is useful when you are using a code
reference and would like to leave the filehandles alone until you're in control.

Call C<< ->redirect_filehandles >> on the Daemon::Control instance your coderef is
passed to redirect the filehandles.

=head2 stdout_file

If provided stdout will be redirected to the given file.  This is only supported
in double fork mode.

    $daemon->stdout_file( "/tmp/mydaemon.stdout" );

Alternatively, you can specify an arrayref of arguments to C<open()>:

    $daemon->stdout_file( [ '>',  '/tmp/overwrite-every-run'  ] );
    $daemon->stdout_file( [ '|-', 'my_pipe_program', '-a foo' ] );

=head2 stderr_file

If provided stderr will be redirected to the given file.  This is only supported
in double fork mode.

    $daemon->stderr_file( "/tmp/mydaemon.stderr" );

Alternatively, you can specify an arrayref of arguments to C<open()>:

    $daemon->stderr_file( [ '>',  '/tmp/overwrite-every-run'  ] );
    $daemon->stderr_file( [ '|-', 'my_pipe_program', '-a foo' ] );

=head2 pid_file

The location of the PID file to use.  Warning: if using single-fork mode, it is
recommended to set this to the file which the daemon launching in single-fork
mode will put its PID.  Failure to follow this will most likely result in status,
stop, and restart not working.

    $daemon->pid_file( "/var/run/mydaemon/mydaemon.pid" );

=head2 resource_dir

This directory will be created, and chowned to the user/group provided in
C<user>, and C<group>.

    $daemon->resource_dir( "/var/run/mydaemon" );

=head2 prereq_no_process -- EXPERIMENTAL

This option is EXPERIMENTAL and defaults to OFF.

If this is set, then the C<ps> list will be checked at startup for any
processes that look like the daemon to be started.  By default the pattern used
is C<< /\b<program name>\b/ >>, but you can pass an override regexp in this field
instead (to use the default pattern, just pass C<< prereq_no_process => 1 >>).
If matching processes are found, those pids are output, and the daemon will not
start.

This may produce some false positives on your system, depending on what else is
running on your system, but it may still be of some use, e.g. if you seem to
have daemons left running where the associated pid file is getting deleted
somehow.

=head2 fork

The mode to use for fork.  By default a double-fork will be used.

In double-fork, uid, gid, std*_file, and a number of other things are
supported.  A traditional double-fork is used and setsid is called.

In single-fork none of the above are called, and it is the responsibility
of whatever you're forking to reopen files, associate with the init process
and do all that fun stuff.  This mode is recommended when the program you want
to control has its own daemonizing code.  It is important to note that the PID
file should be set to whatever PID file is used by the daemon.

In no-fork mode, C<fork(0)>, the program is run in the foreground.  By default
quiet is still turned off, so status updates will be shown on the screen such
as that the daemon started.  A shortcut to turn status off and go into foreground
mode is C<foreground> being set to 1, or C<DC_FOREGROUND> being set as an
environment variable.  Additionally, calling C<foreground> instead of C<start> will
override the forking mode at run-time.

    $daemon->fork( 0 );

    $daemon->fork( 1 );

    $daemon->fork( 2 ); # Default

=head2 scan_name

This provides an extra check to see if the program is running.  Normally
we only check that the PID listed in the PID file is running.  When given
a regular expression, we will also match the name of the program as shown
in ps.

    $daemon->scan_name( qr|mydaemon| );

=head2 kill_timeout

This provides an amount of time in seconds between kill signals being
sent to the daemon.  This value should be increased if your daemon has
a longer shutdown period.  By default 1 second is used.



( run in 1.318 second using v1.01-cache-2.11-cpan-71847e10f99 )