Zarathustra has asked for the wisdom of the Perl Monks concerning the following question:
( wow, it's been 5! years since I last logged into perlmonks... ah, memories )
Ok, anyhow - I'm just getting back into perl again after a pretty long hiatus, and I hope some of you kind monks can help me out with a question/problem.
I've written a daemonizer in perl - for educational purposes - and now I'm trying to make it more useful by modularizing it. I still got the hang of oop in perl, but I'm lacking the camel book, and I need to know how best to get this thing to work as a module that can be easily instantiated by other scripts and/or modules.
The main problem I'm having, is when I run this ( code following, below ), I get errors such as 'SIGTERM handler "sigterm_catcher" not defined.' for each of my signal handlers... how do I get the namespace/context correct for this to work as expected as a module? ( it works just fine when I "unmodularize" it, and just run it as a self-contained script. )
Also, it's obviously coded as a mere module currently - but I'd like to make this into an actual first-class Class; will that be possible, or do the realities of "daemonization" prevent such a thing? Many thanks!
Here is an example/test script that uses my Daemonizer.pm:
And here is the Daemonizer.pm itself:#!/usr/bin/perl -w @INC = [ @INC, './' ]; use Daemonizer; Daemonizer::init; while (1) { sleep 20 }
package Daemonizer; use strict; use vars qw( @ISA @EXPORT_OK ); use Exporter; @ISA = qw( Exporter ); use IO::Seekable; use File::Basename; use POSIX qw( setsid ); use Sys::Syslog qw( :DEFAULT setlogsock ); my ( $PID, $lckfile ); $lckfile = '/tmp/' . fileparse( $0, qr{\..*} ) . '.pid'; # appease perl taint checking $ENV{'PATH'} = "/bin:/usr/bin"; # setup syslogging setlogsock('unix'); openlog( 'parselogd', 'pid', 'local6'); # setup signal traps $SIG{'INT'} = 'sigint_catcher'; $SIG{'TERM'} = 'sigterm_catcher'; $SIG{'QUIT'} = 'sigquit_catcher'; $SIG{'ABRT'} = 'sigabrt_catcher'; $SIG{'HUP'} = 'sighup_catcher'; # not strictly needed, but... $SIG{'CHLD'} = 'IGNORE'; # define sigtrap routines sub sigterm_catcher { &term('TERM') } sub sigquit_catcher { &term('QUIT') } sub sigabrt_catcher { &term('ABRT') } sub sigint_catcher { &term('INT') } sub sighup_catcher { &term('HUP') } # perl interpreter traps ( semi-dangerous ) $SIG{'__DIE__'} = sub { &crit( "Caught die: $_[0]" ) }; $SIG{'__WARN__'} = sub { syslog( 'err', "warn! $_[0]" ) }; ### cleanup ## ## sub clean { syslog( 'debug', "cleaning up" ); rm_lock() if $lckfile; } ### die elegantly ## ## sub crit { my $msg = shift; syslog( 'err', "CRIT!: $msg" ); syslog( 'err', "Aborting!" ); clean(); syslog( 'err', "Terminating daemon" ); closelog(); undef $SIG{'__DIE__'}; die "$msg"; } ### terminate process ## ## sub term { my $cause = shift; syslog( 'notice', "recieved $cause signal"); if ( $cause eq 'HUP' ) { syslog( 'notice', "Restarting daemon"); clean(); init(); } else { clean(); syslog( 'notice', "Terminating daemon"); exit; } } ### create lock file ## ## sub write_lock { syslog( 'info', "writing lock" ); open( LCK, ">$lckfile" ) or do { crit( "Could not create lock file: $!" ); }; print LCK "$PID\n"; close( LCK ); } ### remove lock file ## ## sub rm_lock { my ( $found_pid ); syslog( 'info', "removing lock" ); if ( -e $lckfile ) { open( LCK, "<$lckfile" ) or crit( "Could not read lock file: $!" ); while( <LCK> ) { chomp; /$PID/ and $found_pid = 1; } close( LCK ); if ( $found_pid ) { unlink $lckfile or syslog( 'warning', "Could not delete lock file: $!" ); } else { syslog( 'warning', "Unable to find pid: $PID" ); } } else { syslog( 'warning', "No lockfile found" ); } } ### initialize and spawn off daemon ## ## sub init { my ( $pid ); # grab current process id $PID = $$; syslog( 'notice', "starting daemon" ); if ( -e $lckfile ) { crit( "lock file exists! daemon may already be running" ); } syslog( 'debug', "initializing" ); # create the lock file write_lock(); # create child process defined( $pid = fork ) or crit( "unable to fork process!: $!" ); # be a nice little daemon and go to your root chdir('/') or crit( "unable to chdir to \'/\'!: $!" ); # say goodbye to our progeny exit if $pid; # redirect filehandles open STDOUT, ">/dev/null" or crit( "unable to write to /dev/null!: $!" ); open STDIN, "/dev/null" or crit( "unable to read from /dev/null!: $!" ); # create new session POSIX::setsid or crit( "unable to create new session!: $!" ); # fully establish our own identity $PID = $$; $0 = fileparse( $0, qr{\..*} ); # rewrite lock with new pid write_lock(); # hairy part is over, finally dissociate stderr open STDERR, '>&STDOUT' or crit( "unable to attach STDERR to STDOUT!: $!" ); # we're on our own now } 1;
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: daemon ... oop'ified?
by tlm (Prior) on Jun 17, 2005 at 08:38 UTC | |
by Zarathustra (Beadle) on Jun 17, 2005 at 08:50 UTC | |
by Zarathustra (Beadle) on Jun 17, 2005 at 09:14 UTC | |
|
Re: daemon ... oop'ified?
by japhy (Canon) on Jun 17, 2005 at 14:57 UTC | |
by Zarathustra (Beadle) on Jun 17, 2005 at 18:27 UTC | |
|
Re: daemon ... oop'ified?
by kiat (Vicar) on Jun 17, 2005 at 08:34 UTC | |
by Zarathustra (Beadle) on Jun 17, 2005 at 08:53 UTC |