I\'d like a daemonizer that can turn an arbitrary, generic script or command into a daemon.
There are two common cases I\'d like to deal with:
I hav
This is a working version complete with an example which you can copy into an empty directory and try out (after installing the CPAN dependencies, which are Getopt::Long, File::Spec, File::Pid, and IPC::System::Simple -- all pretty standard and are highly recommended for any hacker: you can install them all at once with cpan <modulename> <modulename> ...
).
keepAlive.pl:
#!/usr/bin/perl
# Usage:
# 1. put this in your crontab, to run every minute:
# keepAlive.pl --pidfile=<pidfile> --command=<executable> <arguments>
# 2. put this code somewhere near the beginning of your script,
# where $pidfile is the same value as used in the cron job above:
# use File::Pid;
# File::Pid->new({file => $pidfile})->write;
# if you want to stop your program from restarting, you must first disable the
# cron job, then manually stop your script. There is no need to clean up the
# pidfile; it will be cleaned up automatically when you next call
# keepAlive.pl.
use strict;
use warnings;
use Getopt::Long;
use File::Spec;
use File::Pid;
use IPC::System::Simple qw(system);
my ($pid_file, $command);
GetOptions("pidfile=s" => \$pid_file,
"command=s" => \$command)
or print "Usage: $0 --pidfile=<pidfile> --command=<executable> <arguments>\n", exit;
my @arguments = @ARGV;
# check if process is still running
my $pid_obj = File::Pid->new({file => $pid_file});
if ($pid_obj->running())
{
# process is still running; nothing to do!
exit 0;
}
# no? restart it
print "Pid " . $pid_obj->pid . " no longer running; restarting $command @arguments\n";
system($command, @arguments);
example.pl:
#!/usr/bin/perl
use strict;
use warnings;
use File::Pid;
File::Pid->new({file => "pidfile"})->write;
print "$0 got arguments: @ARGV\n";
Now you can invoke the example above with: ./keepAlive.pl --pidfile=pidfile --command=./example.pl 1 2 3
and the file pidfile
will be created, and you will see the output:
Pid <random number here> no longer running; restarting ./example.pl 1 2 3
./example.pl got arguments: 1 2 3
You should have a look at daemonize. It allows to detect second copy (but it uses file locking mechanism). Also it works on different UNIX and Linux distributions.
If you need to automatically start your application as daemon, then you need to create appropriate init-script.
You can use the following template:
#!/bin/sh
#
# mydaemon This shell script takes care of starting and stopping
# the <mydaemon>
#
# Source function library
. /etc/rc.d/init.d/functions
# Do preliminary checks here, if any
#### START of preliminary checks #########
##### END of preliminary checks #######
# Handle manual control parameters like start, stop, status, restart, etc.
case "$1" in
start)
# Start daemons.
echo -n $"Starting <mydaemon> daemon: "
echo
daemon <mydaemon>
echo
;;
stop)
# Stop daemons.
echo -n $"Shutting down <mydaemon>: "
killproc <mydaemon>
echo
# Do clean-up works here like removing pid files from /var/run, etc.
;;
status)
status <mydaemon>
;;
restart)
$0 stop
$0 start
;;
*)
echo $"Usage: $0 {start|stop|status|restart}"
exit 1
esac
exit 0
I think you may want to try start-stop-daemon(8). Check out scripts in /etc/init.d
in any Linux distro for examples. It can find started processes by command line invoked or PID file, so it matches all your requirements except being a watchdog for your script. But you can always start another daemon watchdog script that just restarts your script if necessary.
You might also try Monit. Monit is a service that monitors and reports on other services. While it's mainly used as a way to notify (via email and sms) about runtime problems, it can also do what most of the other suggestions here have advocated. It can auto (re)start and stop programs, send emails, initiate other scripts, and maintain a log of output that you can pick up. In addition, I've found it's easy to install and maintain since there's solid documentation.
I apologise for the long answer (please see comments about how my answer nails the spec). I'm trying to be comprehensive, so you have as good of a leg up as possible. :-)
If you are able to install programs (have root access), and are willing to do one-time legwork to set up your script for daemon execution (i.e., more involved than simply specifying the command-line arguments to run on the command line, but only needing to be done once per service), I have a way that's more robust.
It involves using daemontools. The rest of the post describes how to set up services using daemontools.
/service
. The installer should have already done this, but just verify, or if installing manually. If you dislike this location, you can change it in your svscanboot
script, although most daemontools users are used to using /service
and will get confused if you don't use it.init
(i.e., doesn't use /etc/inittab
), you will need to use the pre-installed inittab
as a base for arranging svscanboot
to be called by init
. It's not hard, but you need to know how to configure the init
that your OS uses.
svscanboot
is a script that calls svscan
, which does the main work of looking for services; it's called from init
so init
will arrange to restart it if it dies for any reason./var/lib/svscan
, but any new location will be fine.I usually use a script to set up the service directory, to save lots of manual repetitive work. e.g.,
sudo mkservice -d /var/lib/svscan/some-service-name -l -u user -L loguser "command line here"
where some-service-name
is the name you want to give your service, user
is the user to run that service as, and loguser
is the user to run the logger as. (Logging is explained in just a little bit.)
svc
.run
script to ensure it's doing what you want it to. You may need to place a sleep
call at the top, if you expect your service to exit frequently./service
pointing to your service directory. (Don't put service directories directly within /service
; it makes it harder to remove the service from svscan
's watch.)mkservice
); svscan
takes care of sending log messages to the logging service.mkservice
will create auto-rotated, timestamped log files in the log/main
directory. The current log file is called current
.svc -t /service/some-service-name
; -t
means "send SIGTERM
".-h
(SIGHUP
), -a
(SIGALRM
), -1
(SIGUSR1
), -2
(SIGUSR2
), and -k
(SIGKILL
).-d
. You can also prevent a service from automatically starting at bootup by creating a file named down
in the service directory.-u
. This is not necessary unless you've downed it previously (or set it up not to auto-start).-x
; usually used with -d
to terminate the service as well. This is the usual way to allow a service to be removed, but you have to unlink the service from /service
first, or else svscan
will restart the supervisor.
Also, if you created your service with a logging service (mkservice -l
), remember to also exit the logging supervisor (e.g., svc -dx /var/lib/svscan/some-service-name/log
) before removing the service directory.Pros:
init
provides.Cons:
svc
, and cannot run the run scripts directly (since they would then not be under the control of the supervisor).supervise
processes in your process table.)In balance, I think daemontools is an excellent system for your needs. I welcome any questions about how to set it up and maintain it.
First get createDaemon()
from http://code.activestate.com/recipes/278731/
Then the main code:
import subprocess
import sys
import time
createDaemon()
while True:
subprocess.call(" ".join(sys.argv[1:]),shell=True)
time.sleep(10)