App-Daemon
view release on metacpan or search on metacpan
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
###########################################
sub cmd_line_parse {
###########################################
if( find_option("-h") ) {
pod2usage();
}
if(my $_pidfile = find_option('-p', 1)) {
$pidfile = $_pidfile;
}
else {
$pidfile ||= ( "$default_pid_dir/" . $appname . ".pid" );
}
if(my $_logfile = find_option('-l', 1)) {
$logfile = $_logfile;
}
else {
$logfile ||= ( "$default_log_dir/" . $appname . ".log" );
}
if(my $_l4p_conf = find_option('-l4p', 1)) {
$l4p_conf = $_l4p_conf;
}
if(my $_as_user = find_option('-u', 1)) {
$as_user = $_as_user;
}
else {
$as_user ||= 'nobody';
}
if(my $_as_group = find_option('-g', 1)) {
$as_group = $_as_group;
}
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 );
Log::Log4perl->init(\ qq{
log4perl.logger = $levelstring, FileApp
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.
if(! -w dirname($pidfile) or -f $pidfile and ! -w $pidfile) {
my ($name,$passwd,$uid) = getpwuid($>);
LOGDIE "$pidfile not writable by user $name";
}
if($action eq "status") {
exit status();
}
sub detach {
###########################################
my($as_user) = @_;
# [rt #75219]
umask(0);
# Make sure the child isn't killed when the user closes the
# terminal session before the child detaches from the tty.
$SIG{'HUP'} = 'IGNORE';
my $child = fork();
if(! defined $child ) {
LOGDIE "Fork failed ($!)";
}
if( $child ) {
# parent doesn't do anything
exit 0;
}
# Become the session leader of a new session, become the
# process group leader of a new process group.
POSIX::setsid();
if( defined $pidfile ) {
INFO "Process ID is $$";
pid_file_write($$);
INFO "Written to $pidfile";
}
if($as_user) {
id_switch();
}
# close std file descriptors
if(-e "/dev/null") {
# On Unix, we want to point these file descriptors at /dev/null,
# so that any libary routines that try to read form stdin or
# write to stdout/err will have no effect (Stevens, APitUE, p. 426
# and [RT 51066].
open STDIN, '/dev/null';
open STDOUT, '>>/dev/null';
open STDERR, '>>/dev/null';
} else {
close(STDIN);
close(STDOUT);
close(STDERR);
}
}
###########################################
sub id_switch {
###########################################
if($> == 0) {
# If we're root, become user set as 'as_user' and the group in
# 'as_group'.
# Set the group first because it only works when still root
my ($group,undef,$gid) = getgrnam($as_group);
if(! defined $group) {
LOGDIE "Cannot switch to group $as_group";
}
POSIX::setgid($gid);
my ($name,$passwd,$uid) = getpwnam($as_user);
if(! defined $name) {
LOGDIE "Cannot switch to user $as_user";
}
POSIX::setuid( $uid );
}
}
###########################################
sub status {
###########################################
# Define exit codes according to
# http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
my $exit_code = LSB_UNKNOWN;
print "Pid file: $pidfile\n";
if(-f $pidfile) {
my $pid = pid_file_read();
my $running = process_running($pid);
print "Pid in file: $pid\n";
print "Running: ", $running ? "yes" : "no", "\n";
if($running) {
# see above
$exit_code = LSB_OK;
} else {
# see above
$exit_code = LSB_DEAD_PID_EXISTS;
}
} else {
print "No pidfile found\n";
$exit_code = LSB_NOT_RUNNING;
}
if( proc_processtable_available() ) {
my @cmdlines = processes_running_by_name( $appname );
print "Name match: ", scalar @cmdlines, "\n";
for(@cmdlines) {
print " ", $_, "\n";
}
}
return $exit_code;
}
###########################################
sub process_running {
###########################################
my($pid) = @_;
my $rc = kill( 0, $pid );
if( $rc ) {
# pseudo signal got delivered, process exists
return 1;
} elsif( $! == ESRCH ) {
# process doesn't exist
return 0;
( run in 0.895 second using v1.01-cache-2.11-cpan-ceb78f64989 )