summaryrefslogtreecommitdiff
path: root/lib/PerlDaemon/PerlDaemon.pl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/PerlDaemon/PerlDaemon.pl')
-rw-r--r--lib/PerlDaemon/PerlDaemon.pl164
1 files changed, 164 insertions, 0 deletions
diff --git a/lib/PerlDaemon/PerlDaemon.pl b/lib/PerlDaemon/PerlDaemon.pl
new file mode 100644
index 0000000..240134d
--- /dev/null
+++ b/lib/PerlDaemon/PerlDaemon.pl
@@ -0,0 +1,164 @@
+#!/usr/bin/perl
+
+# Minimal PerlDaemon (c) 2011 Paul Buetow
+
+use strict;
+use warnings;
+
+use Shell qw(mv);
+use POSIX qw(setsid strftime);
+
+use PerlDaemon::Logger;
+use PerlDaemon::RunModule;
+
+$| = 1;
+
+sub trimstr (@) {
+ my @str =
+ @_;
+
+ for (@str) {
+ chomp;
+ s/^[\t\s]+//;
+ s/[\t\s]+$//;
+ }
+
+ return @str;
+}
+
+sub trunc ($) {
+ my $file = shift;
+ open my $fh, ">$file" or die "Can't write $file: $!\n";
+ print $fh '';
+ close $fh;
+}
+
+sub checkpid ($) {
+ my $conf = shift;
+ my $pidfile = $conf->{'daemon.pidfile'};
+ my $logger = $conf->{logger};
+
+ trunc $pidfile unless -f $pidfile;
+
+ open my $fh, $pidfile or $logger->err("Can't read pidfile $pidfile: $!");
+ my ($pid) = <$fh>;
+ close $fh;
+
+ if (defined $pid) {
+ chomp $pid;
+ $logger->err("Process with pid $pid already running") if 0 < int $pid && kill 0, $pid;
+ }
+}
+
+sub writepid ($) {
+ my $conf = shift;
+ my $logger = $conf->{logger};
+
+ my $pidfile = $conf->{'daemon.pidfile'};
+
+ open my $fh, ">$pidfile" or $logger->err("Can't write pidfile: $!");
+ print $fh "$$\n";
+ close $fh;
+}
+
+
+sub readconf ($) {
+ my $conffile = shift;
+
+ open my $fh, $conffile or die "Can't read $conffile\n";
+ my %conf;
+
+ while (<$fh>) {
+ next if /^[\t\w]+#/;
+ s/#.*//;
+
+ my ($key, $val) = trimstr split '=', $_, 2;
+ next unless defined $val;
+
+ $conf{$key} = $val;
+ }
+
+ close $fh;
+
+ # Check
+ my $msg = 'Missing property:';
+
+ foreach (qw(wd loopinterval alivefile pidfile logfile)) {
+ my $key = "daemon.$_";
+ die "$msg $key\n" unless exists $conf{$key};
+ }
+
+ return \%conf;
+}
+
+sub daemonize ($) {
+ my $conf = shift;
+ my $logger = $conf->{logger};
+ $logger->logmsg('Daemonizing...');
+
+ chdir $conf->{'daemon.wd'} or $logger->err("Can't chdir to wd: $!");
+
+ my $msg = 'Can\'t read /dev/null:';
+
+ open STDIN, '>/dev/null' or $logger->err("$msg $!");
+ open STDOUT, '>/dev/null' or $logger->err("$msg $!");
+ open STDERR, '>/dev/null' or $logger->err("$msg $!");
+
+ defined (my $pid = fork) or $logger->err("Can't fork: $!");
+ exit if $pid;
+
+ setsid or $logger->err("Can't start a new session: $!");
+
+ writepid $conf;
+ $logger->logmsg('Daemonizing completed');
+}
+
+sub sighandlers ($) {
+ my $conf = shift;
+ my $logger = $conf->{logger};
+
+ $SIG{TERM} = sub {
+ # On shutdown
+ $logger->logmsg('Received SIGTERM. Shutting down....');
+ unlink $conf->{'daemon.pidfile'} if -f $conf->{'daemon.pidfile'};
+ exit 0;
+ };
+
+ $SIG{HUP} = sub {
+ # On logrotate
+ $logger->logmsg('Received SIGHUP.');
+ $logger->rotatelog();
+ };
+}
+
+sub prestartup ($) {
+ my $conf = shift;
+ checkpid $conf;
+}
+
+sub alive ($) {
+ my $conf = shift;
+}
+
+sub daemonloop ($) {
+ my $conf = shift;
+ my $rmodule = PerlDaemon::RunModule->new($conf);
+ my $loopinterval = $conf->{'daemon.loopinterval'};
+
+ my $loop = shift;
+ for (my $i = 1;;++$i) {
+ $rmodule->do();
+ sleep $loopinterval;
+ alive $conf;
+ }
+}
+
+my $conf = readconf shift;
+$conf->{logger} = PerlDaemon::Logger->new($conf);
+
+prestartup $conf;
+daemonize $conf;
+sighandlers $conf;
+daemonloop $conf;
+
+