Here's a script to run it. It just writes a message to /var/log/Demonize.log#!/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
#!/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 }
In reply to Demonize Module, What are your thoughts? by halfbaked
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |