Compare commits
8 Commits
Author | SHA1 | Date |
---|---|---|
|
b2aadf503b | |
|
639944b905 | |
|
c55693ce1c | |
|
b17eed9466 | |
|
b26bd15791 | |
|
f611c2acf7 | |
![]() |
4a50315f12 | |
![]() |
45bbf6bf1c |
10
README
10
README
|
@ -1,8 +1,10 @@
|
|||
daemonitor
|
||||
==============================================================================
|
||||
(c)2007, Laurence Withers, <l@lwithers.me.uk>.
|
||||
Released under the GNU GPLv3. See file COPYING or
|
||||
http://www.gnu.org/copyleft/gpl.html for details.
|
||||
========================================================================
|
||||
Copyright: ©2007–2012, Güralp Systems Limited
|
||||
Author: Laurence Withers <lwithers@guralp.com>
|
||||
License: GPLv3
|
||||
|
||||
See file COPYING for detail license information.
|
||||
|
||||
Really Quick Instructions
|
||||
-------------------------
|
||||
|
|
7
config
7
config
|
@ -1,10 +1,9 @@
|
|||
# daemonitor/config
|
||||
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
||||
# vim: syntax=sh:expandtab:ts=4:sw=4
|
||||
#
|
||||
# (c)2007, Laurence Withers, <l@lwithers.me.uk>.
|
||||
# Released under the GNU GPLv3. See file COPYING or
|
||||
# http://www.gnu.org/copyleft/gpl.html for details.
|
||||
# Copyright: ©2007–2012, Güralp Systems Limited
|
||||
# Author: Laurence Withers <lwithers@guralp.com>
|
||||
# License: GPLv3
|
||||
#
|
||||
# This file contains options used to build daemonitor.
|
||||
|
||||
|
|
15
make.sh
15
make.sh
|
@ -1,9 +1,9 @@
|
|||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
# daemonitor/make.sh
|
||||
#
|
||||
# (c)2006-2007, Laurence Withers, <l@lwithers.me.uk>.
|
||||
# Released under the GNU GPLv3. See file COPYING or
|
||||
# http://www.gnu.org/copyleft/gpl.html for details.
|
||||
# Copyright: ©2007–2012, Güralp Systems Limited
|
||||
# Author: Laurence Withers <lwithers@guralp.com>
|
||||
# License: GPLv3
|
||||
#
|
||||
|
||||
|
||||
|
@ -15,19 +15,19 @@ then
|
|||
echo "Configuration file not found???"
|
||||
exit 1
|
||||
fi
|
||||
source "config" # don't fail on error, since last command in config might return false
|
||||
source "./config" # don't fail on error, since last command in config might return false
|
||||
|
||||
|
||||
|
||||
# Get version information
|
||||
source version || exit 1
|
||||
source "./version" || exit 1
|
||||
VERSION="${VERMAJOR}.${VERMINOR}.${VERMICRO}"
|
||||
|
||||
|
||||
|
||||
# Get standard functions
|
||||
[ -z "${VERBOSE}" ] && VERBOSE="0"
|
||||
source scripts/functions.sh || exit 1
|
||||
source "./scripts/functions.sh" || exit 1
|
||||
|
||||
|
||||
# List of directories which will be emptied by clean.
|
||||
|
@ -292,5 +292,4 @@ done
|
|||
|
||||
exit 0
|
||||
|
||||
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
||||
# vim: expandtab:ts=4:sw=4
|
||||
|
|
25
run-test.sh
25
run-test.sh
|
@ -1,9 +1,9 @@
|
|||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
# daemonitor/test.sh
|
||||
#
|
||||
# (c)2007, Laurence Withers, <l@lwithers.me.uk>.
|
||||
# Released under the GNU GPLv3. See file COPYING or
|
||||
# http://www.gnu.org/copyleft/gpl.html for details.
|
||||
# Copyright: ©2007–2012, Güralp Systems Limited
|
||||
# Author: Laurence Withers <lwithers@guralp.com>
|
||||
# License: GPLv3
|
||||
#
|
||||
|
||||
# Running this script on its own will display a summary of all the
|
||||
|
@ -21,12 +21,7 @@ run_test() {
|
|||
return 1
|
||||
fi
|
||||
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
LD_LIBRARY_PATH="obj" ${EXE} || return 1
|
||||
else
|
||||
LD_LIBRARY_PATH="obj" ${EXE} "$*" || return 1
|
||||
fi
|
||||
LD_LIBRARY_PATH="obj:${LD_LIBRARY_PATH}" "${EXE}" "$@" || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
|
@ -38,14 +33,15 @@ print_tests() {
|
|||
echo "---------------------------------------------------------------------"
|
||||
for EXE in obj/tests/*
|
||||
do
|
||||
[ -x ${EXE} ] || continue
|
||||
NAME=$(echo ${EXE} | sed 's,obj/tests/,,')
|
||||
[ -x "${EXE}" ] || continue
|
||||
NAME="$(echo "${EXE}" | sed 's,obj/tests/,,')"
|
||||
echo -ne "${NAME}\t"
|
||||
LD_LIBRARY_PATH="obj" ${EXE} --print-summary
|
||||
LD_LIBRARY_PATH="obj:${LD_LIBRARY_PATH}" "${EXE}" --print-summary
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Main script
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
|
@ -53,7 +49,6 @@ then
|
|||
exit 0
|
||||
fi
|
||||
|
||||
run_test $*
|
||||
run_test "$@"
|
||||
|
||||
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
||||
# vim: expandtab:ts=4:sw=4
|
||||
|
|
|
@ -7,6 +7,7 @@ build.docs.none
|
|||
build.files.none
|
||||
build.firmware.gpasm
|
||||
build.firmware.sdcc
|
||||
build.header.c
|
||||
build.lib.c
|
||||
build.lib.c++
|
||||
build.make.none
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# daemonitor/scripts/functions.sh
|
||||
#
|
||||
# (c)2007, Laurence Withers, <l@lwithers.me.uk>.
|
||||
# Released under the GNU GPLv3. See file COPYING or
|
||||
# http://www.gnu.org/copyleft/gpl.html for details.
|
||||
# Copyright: ©2007–2012, Güralp Systems Limited
|
||||
# Author: Laurence Withers, <lwithers@guralp.com>
|
||||
# License: GPLv3
|
||||
#
|
||||
|
||||
# Common functions
|
||||
|
@ -63,5 +63,4 @@ do_cmd_redir() {
|
|||
fi
|
||||
}
|
||||
|
||||
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
||||
# vim: expandtab:ts=4:sw=4
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# daemonitor/scripts/paths
|
||||
#
|
||||
# (c)2007, Laurence Withers, <l@lwithers.me.uk>.
|
||||
# Released under the GNU GPLv3. See file COPYING or
|
||||
# http://www.gnu.org/copyleft/gpl.html for details.
|
||||
# Copyright: ©2007–2012, Güralp Systems Limited
|
||||
# Author: Laurence Withers, <lwithers@guralp.com>
|
||||
# License: GPLv3
|
||||
#
|
||||
# Default path setup. Not meant for editing; use environment variables
|
||||
# to override values if needed.
|
||||
|
@ -60,5 +60,4 @@ fi
|
|||
[ -z "${WEBDIR}" ] && WEBDIR="${SRVDIR}/http"
|
||||
[ -z "${CGIDIR}" ] && CGIDIR="${WEBDIR}/cgi-bin"
|
||||
|
||||
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
||||
# vim: syntax=sh:expandtab:ts=4:sw=4
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/* daemonitor/src/daemonitor/200_log.c
|
||||
*
|
||||
* (c)2007, Laurence Withers, <l@lwithers.me.uk>.
|
||||
* Released under the GNU GPLv3. See file COPYING or
|
||||
* http://www.gnu.org/copyleft/gpl.html for details.
|
||||
*/
|
||||
* Copyright: ©2007–2012, Laurence Withers.
|
||||
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||
* License: GPLv3
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
@ -170,16 +170,25 @@ void log_func_syslog(int level, const char* fmt, ...)
|
|||
/* log_destination_set()
|
||||
* Set `log_func' function pointer.
|
||||
*/
|
||||
void log_destination_set(enum log_destination_t dest)
|
||||
void
|
||||
log_destination_set(enum log_destination_t dest)
|
||||
{
|
||||
switch(dest) {
|
||||
case log_destination_stdout:
|
||||
log_func_fd = STDOUT_FILENO;
|
||||
log_func_fd = dup(STDOUT_FILENO);
|
||||
if(log_func_fd == -1) {
|
||||
printf("dup() failed: %m.");
|
||||
exit(1);
|
||||
}
|
||||
log_func = log_func_file;
|
||||
break;
|
||||
|
||||
case log_destination_stderr:
|
||||
log_func_fd = STDERR_FILENO;
|
||||
log_func_fd = dup(STDERR_FILENO);
|
||||
if(log_func_fd == -1) {
|
||||
fprintf(stderr, "dup() failed: %m.");
|
||||
exit(1);
|
||||
}
|
||||
log_func = log_func_file;
|
||||
break;
|
||||
|
||||
|
@ -210,6 +219,5 @@ int log_destination_set_file(const char* filename)
|
|||
|
||||
|
||||
/* options for text editors
|
||||
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
||||
vim: expandtab:ts=4:sw=4
|
||||
*/
|
||||
|
|
|
@ -1,160 +0,0 @@
|
|||
/* daemonitor/src/daemonitor/400_daemon.c
|
||||
*
|
||||
* (c)2007, Laurence Withers, <l@lwithers.me.uk>.
|
||||
* Released under the GNU GPLv3. See file COPYING or
|
||||
* http://www.gnu.org/copyleft/gpl.html for details.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* DAEMON ROUTINES ********************************************************************************
|
||||
*
|
||||
* This file provides the daemonise() routine, which makes the process a daemon (fork() + setsid()
|
||||
* so that the process lives in the background, also opens /dev/console). It also provides the
|
||||
* close_file_descriptors() routine, which clears all file descriptors but 0, 1 and 2.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* PUBLIC API ************************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* daemonise()
|
||||
* Performs a fork() and setsid() so that the process lives in the background. It closes stdin,
|
||||
* stdout and stderr and opens /dev/null and/or /dev/console instead, as appropriate. On error,
|
||||
* this function exits the program.
|
||||
*/
|
||||
void daemonise(void);
|
||||
|
||||
|
||||
|
||||
/* close_file_descriptors()
|
||||
* Closes all file descriptors but stdin, stdout and stderr. Should be called whether we are
|
||||
* daemonising or not.
|
||||
*/
|
||||
void close_file_descriptors(void);
|
||||
|
||||
|
||||
|
||||
/* IMPLEMENTATION ********************************************************************************/
|
||||
|
||||
|
||||
|
||||
void daemonise(void)
|
||||
{
|
||||
int fd;
|
||||
pid_t pid;
|
||||
|
||||
/* close stdin and reopen it as /dev/null */
|
||||
TEMP_FAILURE_RETRY( close(STDIN_FILENO) );
|
||||
fd = open("/dev/null", O_RDONLY);
|
||||
switch(fd) {
|
||||
case -1:
|
||||
LOG(LOG_CRIT, "Could not open `/dev/null' (%m).");
|
||||
exit(1);
|
||||
|
||||
case STDIN_FILENO:
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG(LOG_CRIT, "Opened `/dev/null' for stdin, but got file descriptor %d instead.", fd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* close stdout and reopen it as /dev/console if possible, or /dev/null if not */
|
||||
TEMP_FAILURE_RETRY( close(STDOUT_FILENO) );
|
||||
fd = open("/dev/console", O_WRONLY | O_NOCTTY);
|
||||
if(fd == -1) {
|
||||
LOG(LOG_WARNING, "Could not open `/dev/console' for stdout (%m).");
|
||||
fd = open("/dev/null", O_WRONLY);
|
||||
}
|
||||
switch(fd) {
|
||||
case -1:
|
||||
LOG(LOG_CRIT, "Could not open `/dev/null' (%m).");
|
||||
exit(1);
|
||||
|
||||
case STDOUT_FILENO:
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG(LOG_CRIT, "Opened `/dev/null' for stdout, but got file descriptor %d instead.", fd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* close stderr and reopen it as /dev/console if possible, or /dev/null if not */
|
||||
TEMP_FAILURE_RETRY( close(STDERR_FILENO) );
|
||||
fd = open("/dev/console", O_WRONLY | O_NOCTTY);
|
||||
if(fd == -1) {
|
||||
LOG(LOG_WARNING, "Could not open `/dev/console' for stderr (%m).");
|
||||
/* force fd closed again, in case glibc kindly connected it to syslog for us */
|
||||
TEMP_FAILURE_RETRY( close(STDERR_FILENO) );
|
||||
fd = open("/dev/null", O_WRONLY);
|
||||
}
|
||||
switch(fd) {
|
||||
case -1:
|
||||
LOG(LOG_CRIT, "Could not open `/dev/null' (%m).");
|
||||
exit(1);
|
||||
|
||||
case STDERR_FILENO:
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG(LOG_CRIT, "Opened `/dev/null' for stderr, but got file descriptor %d instead.", fd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* daemonise */
|
||||
pid = fork();
|
||||
if(pid == (pid_t)-1) {
|
||||
LOG(LOG_CRIT, "Could not fork daemonised process (%m).");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(pid) {
|
||||
/* parent */
|
||||
_exit(0); /* don't call atexit() et al. in parent */
|
||||
}
|
||||
|
||||
|
||||
setsid();
|
||||
LOG(LOG_NOTICE, "Daemonised, PID %lu.", (unsigned long)getpid());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* close_file_descriptors()
|
||||
* Adapted from libgslutil (GPL-3).
|
||||
*/
|
||||
void close_file_descriptors(void)
|
||||
{
|
||||
DIR* d;
|
||||
struct dirent* de;
|
||||
int i, end, dfd;
|
||||
|
||||
d = opendir("/proc/self/fd");
|
||||
if(!d) {
|
||||
/* backup method */
|
||||
for(i = STDERR_FILENO + 1, end = getdtablesize(); i < end; ++i) {
|
||||
close(i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
dfd = dirfd(d);
|
||||
|
||||
while( (de = readdir(d)) ) {
|
||||
if(de->d_name[0] == '.') continue;
|
||||
i = strtol(de->d_name, 0, 10);
|
||||
if(i == dfd) continue; /* skip file descriptor associated with `DIR* d' */
|
||||
if(i <= STDERR_FILENO) continue; /* leave stdin, stdout, stderr alone */
|
||||
TEMP_FAILURE_RETRY( close(i) );
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* options for text editors
|
||||
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
||||
vim: expandtab:ts=4:sw=4
|
||||
*/
|
|
@ -1,9 +1,9 @@
|
|||
/* daemonitor/src/daemonitor/600_run_program.c
|
||||
*
|
||||
* (c)2007, Laurence Withers, <l@lwithers.me.uk>.
|
||||
* Released under the GNU GPLv3. See file COPYING or
|
||||
* http://www.gnu.org/copyleft/gpl.html for details.
|
||||
*/
|
||||
* Copyright: ©2007–2012, Laurence Withers.
|
||||
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||
* License: GPLv3
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
@ -45,8 +45,8 @@ volatile int sigterm_received = 0;
|
|||
|
||||
|
||||
/* close_file_descriptors()
|
||||
* Closes all file descriptors but stdin, stdout and stderr. Should be called whether we are
|
||||
* daemonising or not.
|
||||
* Closes all file descriptors but stdin, stdout and stderr (which it leaves
|
||||
* unchanged).
|
||||
*/
|
||||
void close_file_descriptors(void);
|
||||
|
||||
|
@ -56,6 +56,38 @@ void close_file_descriptors(void);
|
|||
|
||||
|
||||
|
||||
/* close_file_descriptors()
|
||||
* Adapted from libgslutil (GPL-3).
|
||||
*/
|
||||
void
|
||||
close_file_descriptors(void)
|
||||
{
|
||||
DIR* d;
|
||||
struct dirent* de;
|
||||
int i, end, dfd;
|
||||
|
||||
d = opendir("/proc/self/fd");
|
||||
if(!d) {
|
||||
/* backup method */
|
||||
for(i = STDERR_FILENO + 1, end = getdtablesize(); i < end; ++i) {
|
||||
close(i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
dfd = dirfd(d);
|
||||
|
||||
while( (de = readdir(d)) ) {
|
||||
if(de->d_name[0] == '.') continue;
|
||||
i = strtol(de->d_name, 0, 10);
|
||||
if(i == dfd) continue; /* skip file descriptor associated with `DIR* d' */
|
||||
if(i <= STDERR_FILENO) continue; /* leave stdin, stdout, stderr alone */
|
||||
TEMP_FAILURE_RETRY( close(i) );
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* crash()
|
||||
* Crash the program. This is better than just calling exit() because it doesn't clean up. We
|
||||
* should leave our PID file lying around to look like we crashed. This function is paranoid.
|
||||
|
@ -113,6 +145,8 @@ void run_program(const char* exe_path, char** argv)
|
|||
|
||||
/* child -- execute new process */
|
||||
if(pid == 0) {
|
||||
close_file_descriptors();
|
||||
|
||||
/* clear the child's signal mask */
|
||||
sigemptyset(&ss);
|
||||
sigprocmask(SIG_SETMASK, &ss, 0);
|
||||
|
@ -203,6 +237,5 @@ void run_program(const char* exe_path, char** argv)
|
|||
|
||||
|
||||
/* options for text editors
|
||||
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
||||
vim: expandtab:ts=4:sw=4
|
||||
*/
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/* daemonitor/src/daemonitor/700_signal.c
|
||||
*
|
||||
* (c)2007, Laurence Withers, <l@lwithers.me.uk>.
|
||||
* Released under the GNU GPLv3. See file COPYING or
|
||||
* http://www.gnu.org/copyleft/gpl.html for details.
|
||||
*/
|
||||
* Copyright: ©2007–2012, Laurence Withers.
|
||||
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||
* License: GPLv3
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
@ -45,7 +45,7 @@ void sigterm_handler(int signum __attribute__((unused)))
|
|||
/* uck -- we can't call exit() because it's not async-signal-safe, so we must call _exit() and
|
||||
* clean up manually, with no logging */
|
||||
unlink(pidfile_filename);
|
||||
exit(0);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -72,8 +72,9 @@ void signal_setup(void)
|
|||
sigdelset(&ss, SIGSEGV);
|
||||
sigdelset(&ss, SIGBUS);
|
||||
|
||||
/* we'd like to deal with SIGTERM specially */
|
||||
/* we'd like to deal with SIGTERM/SIGINT specially */
|
||||
sigdelset(&ss, SIGTERM);
|
||||
sigdelset(&ss, SIGINT);
|
||||
|
||||
/* don't block SIGCHLD or wait(2) won't work */
|
||||
sigdelset(&ss, SIGCHLD);
|
||||
|
@ -90,9 +91,10 @@ void signal_setup(void)
|
|||
sigaction(SIGBUS, &sa, 0);
|
||||
sigaction(SIGCHLD, &sa, 0);
|
||||
|
||||
/* install our own handler for SIGTERM */
|
||||
/* install our own handler for SIGTERM/SIGINT */
|
||||
sa.sa_handler = sigterm_handler;
|
||||
sigaction(SIGTERM, &sa, 0);
|
||||
sigaction(SIGINT, &sa, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,186 @@
|
|||
/* daemonitor/src/daemonitor/800_checks.c
|
||||
*
|
||||
* Copyright: ©2012, Laurence Withers.
|
||||
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||
* License: GPLv3
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* RESPAWN CHECKS **************************************************************
|
||||
*
|
||||
* This file implements functionality for various checks that may be carried
|
||||
* out whenever the child process needs to be respawned. An arbitrary number of
|
||||
* checks may be registered; if any single check fails, the entire test counts
|
||||
* as failing. The result of the checks is found by calling run_checks().
|
||||
*
|
||||
* A failed check will log details at LOG_NOTICE (or above).
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* PUBLIC API *****************************************************************/
|
||||
|
||||
|
||||
|
||||
/* check_command_register()
|
||||
* cmd: A command (passed to system(3)) to run. If it exits with code 0, the
|
||||
* check passes.
|
||||
*/
|
||||
void check_command_register(const char* cmd);
|
||||
|
||||
|
||||
|
||||
/* check_file_register()
|
||||
* path: A file to test. If it exists, the check passes.
|
||||
*/
|
||||
void check_file_register(const char* cmd);
|
||||
|
||||
|
||||
|
||||
/* run_checks()
|
||||
* Returns 0 if all checks succeeded (including when none are registered) and
|
||||
* non-0 if any check failed.
|
||||
*/
|
||||
int run_checks(void);
|
||||
|
||||
|
||||
|
||||
/* IMPLEMENTATION *************************************************************/
|
||||
|
||||
|
||||
|
||||
enum check_type {
|
||||
check_type_command,
|
||||
check_type_file,
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* struct check
|
||||
* check_head
|
||||
* A linked list of the checks that are to be run.
|
||||
*/
|
||||
struct check {
|
||||
enum check_type type;
|
||||
|
||||
/* can be the argument for system(3) or the path to check for a file */
|
||||
const char* arg;
|
||||
|
||||
/* linked list structure */
|
||||
struct check* next;
|
||||
};
|
||||
|
||||
struct check* check_head = 0;
|
||||
|
||||
|
||||
|
||||
/* check_generic_register()
|
||||
* Instantiates a ‘struct check’ and adds it to the list at ‘check_head’.
|
||||
*/
|
||||
void
|
||||
check_generic_register(enum check_type type, const char* arg)
|
||||
{
|
||||
struct check* c;
|
||||
|
||||
c = malloc(sizeof(*c));
|
||||
c->type = type;
|
||||
c->arg = arg;
|
||||
c->next = check_head;
|
||||
check_head = c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
check_command_register(const char* cmd)
|
||||
{
|
||||
check_generic_register(check_type_command, cmd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
check_command_run(const struct check* iter)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = system(iter->arg);
|
||||
if(ret == -1) {
|
||||
LOG(LOG_ERR, "Unable to run check command \"%s\": %m.", iter->arg);
|
||||
return 0; /* don't exit just because system(3) failed */
|
||||
}
|
||||
|
||||
if(WIFSIGNALED(ret)) {
|
||||
LOG(LOG_WARNING, "Check command \"%s\" killed by signal (%s). Exiting.",
|
||||
iter->arg, strsignal(WTERMSIG(ret)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!WIFEXITED(ret)) {
|
||||
LOG(LOG_WARNING, "Unrecognised exit code 0x%X from check command "
|
||||
"\"%s\".", ret, iter->arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(WEXITSTATUS(ret)) {
|
||||
LOG(LOG_NOTICE, "Check command \"%s\" signalled failure (exit code "
|
||||
"%d). Exiting.", iter->arg, WEXITSTATUS(ret));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
check_file_register(const char* path)
|
||||
{
|
||||
check_generic_register(check_type_file, path);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
check_file_run(const struct check* iter)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = access(iter->arg, F_OK);
|
||||
if(ret) {
|
||||
LOG(LOG_NOTICE, "Check file \"%s\" does not exist. Exiting.",
|
||||
iter->arg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
run_checks(void)
|
||||
{
|
||||
const struct check* iter;
|
||||
|
||||
for(iter = check_head; iter; iter = iter->next) {
|
||||
switch(iter->type) {
|
||||
case check_type_command:
|
||||
if(check_command_run(iter)) return -1;
|
||||
break;
|
||||
|
||||
case check_type_file:
|
||||
if(check_file_run(iter)) return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* options for text editors
|
||||
vim: expandtab:ts=4:sw=4
|
||||
*/
|
|
@ -1,9 +1,9 @@
|
|||
/* daemonitor/src/daemonitor/999_main.c
|
||||
*
|
||||
* (c)2007, Laurence Withers, <l@lwithers.me.uk>.
|
||||
* Released under the GNU GPLv3. See file COPYING or
|
||||
* http://www.gnu.org/copyleft/gpl.html for details.
|
||||
*/
|
||||
* Copyright: ©2007–2012, Laurence Withers.
|
||||
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||
* License: GPLv3
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
@ -37,6 +37,10 @@ void usage(void)
|
|||
" " DEFAULT_RESTART_INTERVAL_S "). May be 0 to restart immediately.\n"
|
||||
" -E, --environment <path> Name of file containing environment variables for\n"
|
||||
" child process, one NAME=VALUE entry per line.\n"
|
||||
" -C, --check-command <cmd> Runs <cmd> via /bin/sh before restarting a service\n"
|
||||
" that has exited. Stops if <cmd> fails.\n"
|
||||
" -F, --check-file <path> Checks that <path> exists before restarting a service\n"
|
||||
" that has exited. Stops if it does not exist.\n"
|
||||
"", stderr);
|
||||
}
|
||||
|
||||
|
@ -53,6 +57,8 @@ struct option options[] = {
|
|||
{ "pidfile", required_argument, 0, 'p' },
|
||||
{ "restart-interval", required_argument, 0, 'R' },
|
||||
{ "environment", required_argument, 0, 'E' },
|
||||
{ "check-command", required_argument, 0, 'C' },
|
||||
{ "check-file", required_argument, 0, 'F' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
@ -61,7 +67,7 @@ struct option options[] = {
|
|||
/* optstr
|
||||
* The list of short commandline options for getopt(3). Sorted alphabetically, lowercase first.
|
||||
*/
|
||||
const char* optstr = "dhl:p:E:R:V";
|
||||
const char* optstr = "dhl:p:C:E:F:R:V";
|
||||
|
||||
|
||||
|
||||
|
@ -73,7 +79,7 @@ int main(int argc, char* argv[])
|
|||
{
|
||||
char* endp;
|
||||
const char* log_argument = 0, * pidfile_argument = 0, * restart_argument = 0;
|
||||
int daemon = 0, restart_interval = DEFAULT_RESTART_INTERVAL;
|
||||
int do_daemon = 0, restart_interval = DEFAULT_RESTART_INTERVAL;
|
||||
|
||||
/* safety */
|
||||
close_file_descriptors(); /* leaves stdout etc. open */
|
||||
|
@ -85,11 +91,13 @@ int main(int argc, char* argv[])
|
|||
case '?': LOG_ANYWHERE("Invalid commandline options."); return 1;
|
||||
case 'h': usage(); return 1;
|
||||
case 'V': fputs("daemonitor " VERSION "\n", stderr); return 1;
|
||||
case 'd': ++daemon; break;
|
||||
case 'd': ++do_daemon; break;
|
||||
case 'l': log_argument = optarg; break;
|
||||
case 'p': pidfile_argument = optarg; break;
|
||||
case 'R': restart_argument = optarg; break;
|
||||
case 'E': set_environment_file(optarg); break;
|
||||
case 'C': check_command_register(optarg); break;
|
||||
case 'F': check_file_register(optarg); break;
|
||||
}
|
||||
}
|
||||
opts_done:
|
||||
|
@ -128,7 +136,12 @@ int main(int argc, char* argv[])
|
|||
if(load_child_environ()) return 1;
|
||||
|
||||
/* daemonise? */
|
||||
if(daemon) daemonise();
|
||||
if(do_daemon) {
|
||||
if(daemon(0, 0)) {
|
||||
LOG(LOG_CRIT, "daemon() failed: %m.");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* write a PID file */
|
||||
if(pidfile_argument) {
|
||||
|
@ -150,6 +163,8 @@ int main(int argc, char* argv[])
|
|||
LOG(LOG_NOTICE, "Sleeping for %d seconds.", restart_interval);
|
||||
safe_sleep_fixed(restart_interval, 0);
|
||||
}
|
||||
|
||||
if(run_checks()) return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -158,6 +173,5 @@ int main(int argc, char* argv[])
|
|||
|
||||
|
||||
/* options for text editors
|
||||
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
||||
vim: expandtab:ts=4:sw=4
|
||||
*/
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
if [ -z ${daemonitor_BUILT} ]
|
||||
then
|
||||
daemonitor="obj/daemonitor"
|
||||
EXTRAS="-D_GNU_SOURCE"
|
||||
EXTRAS="-std=gnu99 -D_GNU_SOURCE -DAPP_NAME=\"daemonitor\""
|
||||
|
||||
echo "Building application ${daemonitor}..."
|
||||
|
||||
|
@ -37,5 +37,4 @@ then
|
|||
|
||||
fi
|
||||
|
||||
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
||||
# vim: syntax=sh:expandtab:ts=4:sw=4
|
||||
|
|
|
@ -8,5 +8,4 @@ echo "Installing binaries into '${SBINDIR}'"
|
|||
install_file "${daemonitor}" "${SBINDIR}" 0755 || return 1
|
||||
print_success "Done"
|
||||
|
||||
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
||||
# vim: syntax=sh:expandtab:ts=4:sw=4
|
||||
|
|
|
@ -14,5 +14,4 @@ then
|
|||
MONOLITHIC_DOC="${MONOLITHIC_DOC} ${SRC}"
|
||||
fi
|
||||
|
||||
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
||||
# vim: syntax=sh:expandtab:ts=4:sw=4
|
||||
|
|
9
version
9
version
|
@ -1,8 +1,8 @@
|
|||
# daemonitor/version
|
||||
#
|
||||
# (c)2007, Laurence Withers, <l@lwithers.me.uk>.
|
||||
# Released under the GNU GPLv3. See file COPYING or
|
||||
# http://www.gnu.org/copyleft/gpl.html for details.
|
||||
# Copyright: ©2007–2012, Güralp Systems Limited
|
||||
# Author: Laurence Withers <lwithers@guralp.com>
|
||||
# License: GPLv3
|
||||
#
|
||||
|
||||
|
||||
|
@ -11,7 +11,6 @@
|
|||
# expected to be in 'major.minor.micro' format.
|
||||
VERMAJOR=1
|
||||
VERMINOR=0
|
||||
VERMICRO=1
|
||||
VERMICRO=3
|
||||
|
||||
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
||||
# vim: expandtab:ts=4:sw=4:syntax=sh
|
||||
|
|
Loading…
Reference in New Issue