package MooseX::StdDaemon; our $VERSION = '0.01'; use Moose::Role; with 'MooseX::Daemonize'; with 'MooseX::Getopt'; with 'MooseX::ConfigFromFile'; with 'MooseX::LazyLogDispatch'; requires 'run'; has 'syslog_min_level' => ( is => 'ro', isa => 'Str', default => 'info', ); has 'syslog_facility' => ( is => 'ro', isa => 'Str', default => 'daemon', ); has 'syslog_ident' => ( is => 'ro', isa => 'Str', default => $0, ); has log_dispatch_conf => ( is => 'ro', isa => 'HashRef', lazy => 1, required => 1, default => sub { my $self = shift; return $self->foreground ? { class => 'Log::Dispatch::Screen', min_level => 'debug', stderr => 1, format => '[%p] %m at %F line %L%n', } : { class => 'Log::Dispatch::Syslog', min_level => $self->syslog_min_level, facility => $self->syslog_facility, ident => $self->syslog_ident, format => '[%p] %m', }; }, ); sub daemon_action { my $self = shift; my ($command) = @{$self->extra_argv}; defined $command || die "No command specified"; $self->start if $command eq 'start'; $self->status if $command eq 'status'; $self->restart if $command eq 'restart'; $self->stop if $command eq 'stop'; warn($self->status_message); exit($self->exit_code); } after start => sub { my $self = shift; return unless $self->is_daemon; $self->run(); $self->quit(); }; sub quit { my $self = shift; $self->pidfile->remove if $self->pidfile->pid == $$; exit(0); } no Moose::Role; 1; __END__ =pod =head1 NAME MooseX::StdDaemon - Boilerplate for standard *nix daemons =head1 SYNOPSIS ### # myapp.pl - the script/daemon you execute: ### use MyApp; MyApp->new_with_options()->daemon_action(); ### # MyApp.pm - the class where you put your code: ### use Moose; with 'MooseX::StdDaemon'; # default the configfile has +configfile { default => '/etc/myapp.yaml' } # Your class attributes like these can be specified # on the commandline or in the configfile: has something { is => 'ro', isa => 'Int', documentation => '--something|-s Some Thing', } sub run { my $self = shift; $self->do_stuff_a_daemon_does(); $self->do_stuff_a_daemon_does(); $self->do_stuff_a_daemon_does(); return; # exits daemon, clearing pidfile } ### # Invoke with explicit configfile and pidfile locations: ### ./myapp.pl --something 123 --configfile /tmp/foo.yaml --pidfile /var/run/x.pid start ### # Invoke in foreground mode (does not daemonize, log output # goes to STDERR): ### ./myapp.pl --something 234 --configfile /tmp/foo.yaml -f start =head1 DESCRIPTION This role serves to pull together several useful MooseX roles into a standardized boilerplate for normal run-of-the-mill daemons. It automatically gives you daemonization with a pidfile, simple initscript integration, commandline flags with usage information, configfile support, and logging to syslog (or stderr if running in the foreground for debug purposes). Writing initscripts for your daemon is easy too. All of the hard parts have been wrapped up in this role already. Just invoke the daemon (with any necessary options like configfile) with any of the standard initscript commands (stop/start/restart/status) as the initscript action, as in (assuming you've got the rest of your normal OS initscript down): case "$1" in start) echo -n "Starting ${DESC}: " myapp.pl $OPTIONS start exit $? ;; stop) echo -n "Stopping ${DESC}: " myapp.pl $OPTIONS stop exit $? ;; restart) echo -n "Restarting ${DESC}: " myapp.pl $OPTIONS restart exit $? ;; status) echo -n "$DESC Status: " myapp.pl $OPTIONS status exit $? ;; =head1 ATTRIBUTES =head2 syslog_min_level Defaults to C. This is the minimum level of logger messages that will actually be sent to syslog by your daemon. =head2 syslog_ident Defaults to C<$0> (the program's name). This is the identifier that will be used in the syslog output. =head2 syslog_facility Defaults to C. This is the facility that will be used for the syslog output. =head1 METHODS =head2 daemon_action This checks for standard start/stop/status/restart on the commandline and takes the appropriate action for you. =head2 run You provide this method, it's required. Put the core of your daemon (runloop or whatever) here, along with any custom initialization like signal handlers. When you return from run(), the daemon will exit. =head2 quit This method wipes the pidfile and exits cleanly. It's what happens when you return from run() above. It's a good idea to use this when exiting via other means, like signal handlers. =head1 USEFUL STUFF These are provided by the other MooseX roles listed in the SEE ALSO section. This is a quick recap of the ones you'll want the most, but see those modules' documentation for more details and more stuff =head2 logger Supplied by L. Use this method to send log messages to syslog (or the console if running in the foreground), as in: $self->logger->notice("Notice: something happened"); $self->logger->debug("Debug Stuff!"); =head2 configfile This attribute is supplied by L via L. If you want to have a default configfile, specify it as so: has +configfile => ( default => '/etc/defcfg.yaml' ); Note that L uses L, which supports many configfile formats like YAML, JSON, and XML. You're responsible for making sure the correct module to parse the format is installed. The format is detected from the configfile extension, so YAML files need to be named something C<.yaml>, etc. =head1 SEE ALSO L L L L L =head1 AUTHOR Brandon L. Black, Eblblack@gmail.comE =head1 LICENSE This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut