I wrote this module I called Demonize.pm. I think it's pretty useful, but I was wondering what the Perl Monks think of it. It's a general class to create Perl daemons by subclassing Demonize and overriding the run method.

I know there are other modules out there that do something similar to this, is this module just something that I find useful?

#!/usr/bin/perl -w # This is a general-purpose daemon class module. # Extend this class and override the run method with your own. # # You can run this class alone and it will create a /var/log/Demonize. +log file and write # a message to it. # # In your sub-class you should should set error_recipient to an email +address that will be notified # if the daemon dies (you could do numerous email addresses like this +alerts@yourdomain.com,help@yourdomain.com # # You should also call method email and set the "From" for the error m +essages. # # To set the number of seconds daemon should sleep, call sleep method. # # To set logdir call logdir. # # To set logfile all logfile. # # Here's an example from a constructor I have in use that uses YAML to + store the configuration data: # # $self->logfile(sprintf('%s/%s.log', $self->logdir, $self->name)); # # $self->logdir($config->{logdir}); # # $self->error_recipient($config->{error_recipient}); # $self->email($config->{email}); # $self->seconds($config->{sleepfor}); # # Created By: Keith Vance <next@take88.com> # Created On: 11/28/2008 # package Demonize; use strict; use warnings FATAL => 'all', NONFATAL => 'redefine'; use DBI; use Proc::PID::File(); use POSIX; use MIME::Lite(); use LWP::Simple; our %Demon = (LOG_DIR => '', ERROR_RECIPIENT => '', EMAIL => '', SECONDS => '', LOG_FILE => ''); our $_Demon; sub _classobject { my $self = shift; my $class = ref($self) || $self; no strict "refs"; return \%$class; } sub new { my $class = shift; my $classobj = $class->_classobject(); bless my $self = { LOG_DIR => '/var/log', ERROR_RECIPIENT => 'youremail@yourdomain.com', EMAIL => 'youremail@yourdomain.com', SECONDS => 1} => (ref $class || $class); $self->logfile(sprintf('%s/%s.log', $self->logdir, $self->name)); $_Demon = $self; return $self; } sub start { my $self = shift; if (my $pid = fork()) { exit 0; } if (Proc::PID::File->running({name=>$self->name})) { die "Couldn't start: " . $self->name . " already running."; } $self->init_daemon; } sub logfile { my $self = shift; $self->{LOG_FILE} = shift if @_; return $self->{LOG_FILE}; } sub name { return __PACKAGE__ } sub logdir { my $self = shift; $self->{LOG_DIR} = shift if @_; return $self->{LOG_DIR}; } sub error_recipient { my $self = shift; $self->{ERROR_RECIPIENT} = shift if @_; return $self->{ERROR_RECIPIENT}; } sub email { my $self = shift; $self->{EMAIL} = shift if @_; return $self->{EMAIL}; } sub seconds { my $self = shift; $self->{SECONDS} = shift if @_; return $self->{SECONDS}; } sub init_daemon { my $self = shift; printf "Starting: %s\n", $self->name; *CORE::GLOBAL::warn = \&warn_to_log; $SIG{__DIE__} = \&die_to_log; $SIG{__WARN__} = \&warn_to_log; eval { chdir '/' or die $!; open STDIN, '/dev/null' or die $!; open(STDOUT, '>>' . $self->logfile); open(STDERR, '+>&STDOUT'); logmsg(sprintf('Starting %s', $self->name)); POSIX::setsid or die $!; logmsg('Successful'); }; if ($@) { die "Couldn't start child '" . $self->name . "': $@"; } local $SIG{CHLD} = 'IGNORE'; $self->run; } sub stop { my $self = shift; my $pid; unless ($pid = Proc::PID::File->running({name=>$self->name})) { printf "%s not running\n", $self->name; return; } $| = 1; printf "Shutting down %s", $self->name; kill -3 => $pid; my $i = 0; while (kill (-0 => $pid) && $i++ < 30) { print '.'; sleep 1; } unless (kill -0 => $pid) { print "\nShut down complete\n"; return 0; } print "\nNot responding - sending kill signal\n"; kill -9 => $pid; return; } sub status { my $self = shift; if (Proc::PID::File->running({name=>$self->name})) { printf "%s is running\n", $self->name; } else { printf "%s is not running\n", $self->name; } exit 0; } sub run { my $self = shift; while (1) { logmsg("I'm not doing anything, I'm just sleeping for " . $self->s +econds . " seconds. Please override the run method in your subclass t +o do something interesting instead of writing this log message."); sleep($self->seconds); } } sub logmsg { print format_msg($_[0]); } sub format_msg { return (timestamp(),' [',(caller(1))[0]," $$] : ",$_[0]."\n"); } sub timestamp { my ($sec,$min,$hour,$day,$mon,$year) = localtime; return sprintf ("%4d-%02d-%02d %02d:%02d:%02d", $year+1900,++$mon,$day,$hour,$min,$sec); } sub warn_to_log { print format_msg('**** ' . $_[0]); } sub die_to_log { return if $^S; my $error = $_[0]; my $self = $_Demon; eval { my @to = ($self->error_recipient); my $msg = MIME::Lite->new( From => $self->email, To => @to, Subject => 'Error running ' . $self->name, Data => $self->name . ".pm DIED\n" . $error, Encoding => 'quoted-printable' ); $msg->attr('content-type', => 'text/plain; charset=utf-8; format=f +lowed'); $msg->send(); }; if ($@) { $error .= ' Additionally, an error occurred sending the alert emai +l: ' . $@; } die format_msg('**** DIE!!! **** ' . $error); } 1
Here's a script to run it. It just writes a message to /var/log/Demonize.log

#!/usr/bin/perl -w use strict; use Demonize; my $command = shift @ARGV || ''; my $demon = Demonize->new; if ($command eq 'start') { exit $demon->start; } elsif ($command eq 'restart') { $demon->stop; exit $demon->start; } elsif ($command eq 'stop') { $demon->stop; } elsif ($command eq 'status') { $demon->status; } else { die <<USAGE; Usage : $0 stop|start|restart|status USAGE }


To do something interesting, you have to subclass Demonize

In reply to Demonize Module, What are your thoughts? by halfbaked

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.