Commit a0f2988d authored by Mike Hibler's avatar Mike Hibler

Slight generalization of dhcpd_wrapper suitable for use by other daemons.

This is only a first step.  Though this is a common daemon, you still start
multiple copies, and it most likely won't handle all daemons we might want
to auto restart.
parent 7d8b123b
......@@ -21,7 +21,7 @@ SBIN_SCRIPTS = vlandiff vlansync withadminprivs export_tables cvsupd.pl \
eventping grantnodetype import_commitlog dhcpd_wrapper \
opsreboot deletenode node_statewait grabwebcams \
grabswitchconfig backupswitches cvsinit checkquota \
spewconlog opsdb_control
spewconlog opsdb_control daemon_wrapper
LIBEXEC_SCRIPTS = webcreateimage newnode webdeletenode spewleds webcopy \
websetdest spewsource weblinkmon_ctl webcvsweb \
webspewconlog xlogin webviewvc spewevents
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2004, 2005, 2006 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
use Getopt::Std;
use POSIX qw(setsid);
sub usage()
{
print "Usage: daemon_wrapper [-i interval] [-p pidfile] [-l logfile] command args ...\n";
exit(1);
}
my $optlist = "di:p:l:";
my $debug = 0;
my $mininterval = 1;
my $maxinterval = (24 * 60 * 60);
my $interval = $mininterval;
my $TBOPS = "@TBOPSEMAIL@";
my $pidfile;
my $logfile;
my $daemon;
my $cmd;
my $cmdargs;
my $childpid;
# Turn off line buffering on output
$| = 1;
#
# Parse arguments
#
my %options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"d"})) {
$debug = 1;
}
if (defined($options{"i"})) {
$interval = int($options{"i"});
if ($interval < $mininterval || $interval > $maxinterval) {
usage();
}
$mininterval = $interval;
}
if (defined($options{"p"})) {
$pidfile = $options{"p"};
}
if (defined($options{"l"})) {
$logfile = $options{"l"};
}
if (@ARGV < 1) {
usage();
}
$cmd = shift;
if ($cmd =~ /.*\/([^\/]+)/) {
$daemon = $1;
}
$cmdargs = join(' ', @ARGV);
$pidfile = "/var/run/${daemon}_wrapper.pid"
if (!defined($pidfile));
$logfile = "/var/log/${daemon}_wrapper.log"
if (!defined($logfile));
# Only root.
if ($UID != 0) {
die("*** $0:\n".
" Must be root to run this script!\n");
}
#
# Testbed support libs.
#
use lib "@prefix@/lib";
use libtestbed;
# Signal handler to initiate cleanup in parent and the children.
sub Pcleanup($)
{
my ($signame) = @_;
$SIG{TERM} = 'IGNORE';
if (defined($childpid)) {
system("kill $childpid");
waitpid($childpid, 0);
}
unlink $pidfile;
print TBTimeStampWithDate(),
" [$PID]: wrapper exiting\n";
exit(0);
}
# Daemonize;
if (!$debug && TBBackGround($logfile)) {
sleep(1);
exit(0);
}
#
# Write our pid into the pid file so we can be killed later.
#
system("echo '$PID' > $pidfile") == 0 or
die("*** $0:\n".
" Could not create $pidfile!");
# Okay, cleanup function.
$SIG{TERM} = \&Pcleanup;
# Fully disconnect from bootup.
setsid();
print TBTimeStampWithDate(),
" [$PID]: wrapper starting '$cmd",
$cmdargs ? " $cmdargs" : "", "'\n";
# Loop forever, restarting the daemon if it ever dies.
while (1) {
my $runtime = time();
$childpid = fork();
die("*** $0:\n".
" Could not fork!\n")
if ($childpid < 0);
if ($childpid == 0) {
if (!exec("$cmd $cmdargs")) {
print STDERR "*** $0:\n".
" Could not exec $cmd!\n";
exit(1);
}
}
print TBTimeStampWithDate(),
" [$PID]: $daemon ($childpid) started\n";
waitpid($childpid, 0);
my $exitstat = $?;
my $ecode = $exitstat >> 8;
my $esig = $exitstat & 0x3F;
my $lpid = $childpid;
undef $childpid;
my $msg;
if ($esig != 0) {
$msg = "killed by signal $esig";
} else {
$msg = "died with exit code $ecode";
}
$runtime = time() - $runtime;
print TBTimeStampWithDate(),
" [$PID]: $daemon ($lpid) $msg ",
"after $runtime seconds, ";
if ($ecode == 1) {
print "not restarting!\n";
SENDMAIL($TBOPS, "$daemon died",
"$daemon died with exit code 1\n".
"Not restarting it; might be a configuration error",
$TBOPS);
unlink $pidfile;
die("*** $0:\n".
" Could not start $daemon! Might be a configuration error.\n");
}
#
# Anytime it exits, send email (unless TERM).
#
if ($exitstat != 15) {
SENDMAIL($TBOPS, "$daemon died",
"$daemon $msg after $runtime seconds; restarting it.",
$TBOPS);
}
#
# If the process ran for less than 5 seconds, there may be a problem
# with daemon startup. To avoid spamming testbed-ops for a process
# that will never start, back off the checks exponentially up to some
# maximum interval.
#
if ($runtime < 5) {
$interval *= 2;
if ($interval > $maxinterval) {
$interval = $maxinterval;
}
} else {
$interval = $mininterval;
}
print "restarting in $interval seconds\n";
sleep($interval);
}
exit(0);
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2004, 2005 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
use Getopt::Std;
use POSIX qw(setsid);
sub usage()
{
print "Usage: dhcpd_wrapper\n";
exit(1);
}
my $optlist = "";
my $debug = 0;
my $TBOPS = "@TBOPSEMAIL@";
my $PIDFILE = "/var/run/dhcpd_wrapper.pid";
my $LOGFILE = "/var/log/dhcpd_wrapper.log";
my $DHCPD = "/usr/local/sbin/dhcpd -f ";
#my $DHCPDOPTS = "-cf /usr/local/etc/dhcpd.conf.v3 fxp0";
my $DHCPDOPTS = "";
my $childpid;
# Turn off line buffering on output
$| = 1;
# Only root.
if ($UID != 0) {
die("*** $0:\n".
" Must be root to run this script!\n");
}
#
# Testbed support libs.
#
use lib "@prefix@/lib";
use libtestbed;
# Signal handler to initiate cleanup in parent and the children.
sub Pcleanup($)
{
my ($signame) = @_;
$SIG{TERM} = 'IGNORE';
if (defined($childpid)) {
system("kill $childpid");
waitpid($childpid, 0);
}
unlink $PIDFILE;
exit(0);
}
# Daemonize;
if (!$debug && TBBackGround($LOGFILE)) {
sleep(1);
exit(0);
}
#
# Write our pid into the pid file so we can be killed later.
#
system("echo '$PID' > $PIDFILE") == 0 or
die("*** $0:\n".
" Could not create $PIDFILE!");
# Okay, cleanup function.
$SIG{TERM} = \&Pcleanup;
# Fully disconnect from bootup.
setsid();
# Loop forever, restarting DHCPD if it ever dies.
while (1) {
$childpid = fork();
die("*** $0:\n".
" Could not fork!\n")
if ($childpid < 0);
if ($childpid == 0) {
exec("$DHCPD $DHCPDOPTS");
die("*** $0:\n".
" Could not exec $DHCPD!\n");
}
waitpid($childpid, 0);
if (($? >> 8) == 1) {
SENDMAIL($TBOPS, "DHCPD died",
"$DHCPD died with 1\n".
"Not restarting it; might be a config file error",
$TBOPS);
unlink $PIDFILE;
die("*** $0:\n".
" Could not start $DHCPD! Might be a config file error.\n");
}
#
# Anytime it exits, send email (unless TERM).
#
if ($? != 15) {
SENDMAIL($TBOPS, "DHCPD died",
"$DHCPD died with $?; restarting it.",
$TBOPS);
}
sleep(1);
}
exit(0);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment