App-Daemon
view release on metacpan or search on metacpan
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(daemonize cmd_line_parse detach);
use constant LSB_OK => 0;
use constant LSB_DEAD_PID_EXISTS => 1;
use constant LSB_DEAD_LOCK_EXISTS => 2;
use constant LSB_NOT_RUNNING => 3;
use constant LSB_UNKNOWN => 4;
use constant ALREADY_RUNNING => 150;
our ($pidfile, $logfile, $l4p_conf, $as_user, $as_group, $background,
$loglevel, $action, $appname, $default_pid_dir, $default_log_dir);
$action = "";
$appname = appname();
$default_pid_dir = ".";
$default_log_dir = ".";
our $kill_retries = 3;
our $kill_sig = SIGTERM; # maps to 15 via POSIX.pm
else {
$as_group ||= 'nogroup';
}
if($> != 0) {
# Not root? Then we're ourselves
($as_user) = getpwuid($>);
($as_group) = getgrgid(POSIX::getgid());
}
$background = 1 if(!defined $background);
$background = find_option('-X') ? 0 : $background;
$loglevel = $background ? $INFO : $DEBUG
if(!defined $loglevel);
$loglevel = find_option('-v') ? $DEBUG : $loglevel;
for (qw(start stop restart status)) {
if( find_option( $_ ) ) {
$action = $_;
last;
}
}
if($action eq "stop" or $action eq "status") {
$background = 0;
}
if( Log::Log4perl->initialized() ) {
DEBUG "Log4perl already initialized, doing nothing";
} elsif( $action eq "status" ) {
Log::Log4perl->easy_init( $loglevel );
} elsif( $l4p_conf ) {
Log::Log4perl->init( $l4p_conf );
} elsif( $logfile ) {
my $levelstring = Log::Log4perl::Level::to_level( $loglevel );
log4perl.appender.FileApp = Log::Log4perl::Appender::File
log4perl.appender.FileApp.filename = $logfile
log4perl.appender.FileApp.owner = $as_user
# this umask is only temporary
log4perl.appender.FileApp.umask = 0133
log4perl.appender.FileApp.layout = PatternLayout
log4perl.appender.FileApp.layout.ConversionPattern = %d %m%n
});
}
if(!$background) {
DEBUG "Running in foreground";
}
}
###########################################
sub daemonize {
###########################################
cmd_line_parse();
# Check beforehand so the user knows what's going on.
} else {
exit $exit_code;
}
}
if ( my $num = pid_file_process_running() ) {
LOGWARN "Already running: $num (pidfile=$pidfile)\n";
exit ALREADY_RUNNING;
}
if( $background ) {
detach( $as_user );
} elsif ($as_user) {
id_switch();
}
my $prev_sig = $SIG{__DIE__};
my $master_pid = $$;
DEBUG "Defining die handler";
=head1 SYNOPSIS
# Program:
use App::Daemon qw( daemonize );
daemonize();
do_something_useful(); # your application
# Then, in the shell: start application,
# which returns immediately, but continues
# to run do_something_useful() in the background
$ app start
$
# stop application
$ app stop
# start app in foreground (for testing)
$ app -X
# show if app is currently running
you'll get a script that, when called from the command line, returns
immediatly, but continues to run as a daemon for 10 seconds.
Along with the
common features offered by similar modules on CPAN, it
=over 4
=item *
supports logging with Log4perl: In background mode, it logs to a
logfile. In foreground mode, log messages go directly to the screen.
=item *
detects if another instance is already running and ends itself
automatically in this case.
=item *
shows with the 'status' command if an instance is already running
=head2 Command Line Options
=over 4
=item -X
Foreground mode. Log messages go to the screen.
=item -l logfile
Logfile to send Log4perl messages to in background mode. Defaults
to C<./[appname].log>. Note that having a logfile in the current directory
doesn't make sense except for testing environments, make sure to set this
to somewhere within C</var/log> for production use.
=item -u as_user
User to run as if started as root. Defaults to 'nobody'.
=item -g as_group
Instead of setting paramteters like the logfile, the pidfile etc. from
the command line, you can directly manipulate App::Daemon's global
variables:
use App::Daemon qw(daemonize);
$App::Daemon::logfile = "mylog.log";
$App::Daemon::pidfile = "mypid.log";
$App::Daemon::l4p_conf = "myconf.l4p";
$App::Daemon::background = 1;
$App::Daemon::as_user = "nobody";
$App::Daemon::as_group = "nogroup";
use Log::Log4perl qw(:levels);
$App::Daemon::loglevel = $DEBUG;
daemonize();
=head2 Application-specific command line options
App::Daemon - Start an Application as a Daemon
SYNOPSIS
# Program:
use App::Daemon qw( daemonize );
daemonize();
do_something_useful(); # your application
# Then, in the shell: start application,
# which returns immediately, but continues
# to run do_something_useful() in the background
$ app start
$
# stop application
$ app stop
# start app in foreground (for testing)
$ app -X
# show if app is currently running
use App::Daemon qw( daemonize );
daemonize();
sleep(10);
you'll get a script that, when called from the command line, returns
immediatly, but continues to run as a daemon for 10 seconds.
Along with the common features offered by similar modules on CPAN, it
* supports logging with Log4perl: In background mode, it logs to a
logfile. In foreground mode, log messages go directly to the screen.
* detects if another instance is already running and ends itself
automatically in this case.
* shows with the 'status' command if an instance is already running
and which PID it has:
./my-app status
Pid file: ./tt.pid
use constant LSB_DEAD_PID_EXISTS => 1;
use constant LSB_DEAD_LOCK_EXISTS => 2;
use constant LSB_NOT_RUNNING => 3;
use constant LSB_UNKNOWN => 4;
use constant ALREADY_RUNNING => 150;
Command Line Options
-X Foreground mode. Log messages go to the screen.
-l logfile
Logfile to send Log4perl messages to in background mode. Defaults to
"./[appname].log". Note that having a logfile in the current
directory doesn't make sense except for testing environments, make
sure to set this to somewhere within "/var/log" for production use.
-u as_user
User to run as if started as root. Defaults to 'nobody'.
-g as_group
Group to run as if started as root. Defaults to 'nogroup'.
Setting Parameters
Instead of setting paramteters like the logfile, the pidfile etc. from
the command line, you can directly manipulate App::Daemon's global
variables:
use App::Daemon qw(daemonize);
$App::Daemon::logfile = "mylog.log";
$App::Daemon::pidfile = "mypid.log";
$App::Daemon::l4p_conf = "myconf.l4p";
$App::Daemon::background = 1;
$App::Daemon::as_user = "nobody";
$App::Daemon::as_group = "nogroup";
use Log::Log4perl qw(:levels);
$App::Daemon::loglevel = $DEBUG;
daemonize();
Application-specific command line options
If an application needs additional command line options, it can use
t/002Params.t view on Meta::CPAN
# Turdix locks temp files, so unlock them just in case
flock $fh, LOCK_UN;
ok(1, "loaded ok");
open(OLDERR, ">&STDERR");
open(STDERR, ">$tempfile");
@ARGV = ();
$App::Daemon::background = 0;
daemonize();
close STDERR;
open(STDERR, ">&OLDERR");
close OLDERR;
ok(1, "running in foreground");
open FILE, "<$tempfile";
my $data = join '', <FILE>;
( run in 0.763 second using v1.01-cache-2.11-cpan-f56aa216473 )