summaryrefslogtreecommitdiffabout
authorMichael Krelin <hacker@klever.net>2004-07-23 21:31:57 (UTC)
committer Michael Krelin <hacker@klever.net>2004-07-23 21:31:57 (UTC)
commit125671c860a82643d36bc3da279d0b831fae4b34 (patch) (unidiff)
treeab5edcac7c58e769c9d8436ae0e803edb2ebca9f
parent0a7f5999eb47ce113b3cd47b03198947441945a7 (diff)
downloaddudki-125671c860a82643d36bc3da279d0b831fae4b34.zip
dudki-125671c860a82643d36bc3da279d0b831fae4b34.tar.gz
dudki-125671c860a82643d36bc3da279d0b831fae4b34.tar.bz2
ability to send arbitrary signals
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--NEWS.xml2
-rw-r--r--man/dudki.8.in11
-rw-r--r--src/dudki.cc20
3 files changed, 29 insertions, 4 deletions
diff --git a/NEWS.xml b/NEWS.xml
index 646bb90..cd12d05 100644
--- a/NEWS.xml
+++ b/NEWS.xml
@@ -1,14 +1,14 @@
1<?xml version="1.0" encoding="us-ascii"?> 1<?xml version="1.0" encoding="us-ascii"?>
2<news> 2<news>
3 <version version="0.2" date="July 23rd, 2004"> 3 <version version="0.2" date="July 23rd, 2004">
4 <ni>now dudki sends signals to the processes being monitored from the command line</ni> 4 <ni>now dudki sends arbitrary signals to the processes being monitored from the command line</ni>
5 </version> 5 </version>
6 <version version="0.1" date="July 21st, 2004"> 6 <version version="0.1" date="July 21st, 2004">
7 <ni><kbd>initgroups()</kbd> called before executing <kbd>RestartCommand</kbd></ni> 7 <ni><kbd>initgroups()</kbd> called before executing <kbd>RestartCommand</kbd></ni>
8 <ni>more civilized way of restarting on <kbd>SIGHUP</kbd></ni> 8 <ni>more civilized way of restarting on <kbd>SIGHUP</kbd></ni>
9 <ni>minor changes to build process</ni> 9 <ni>minor changes to build process</ni>
10 </version> 10 </version>
11 <version version="0.0" date="July 11th, 2004"> 11 <version version="0.0" date="July 11th, 2004">
12 <ni>Initial release</ni> 12 <ni>Initial release</ni>
13 </version> 13 </version>
14</news> 14</news>
diff --git a/man/dudki.8.in b/man/dudki.8.in
index 05db733..be60f53 100644
--- a/man/dudki.8.in
+++ b/man/dudki.8.in
@@ -1,81 +1,88 @@
1.TH dudki 8 "June 9th, 2004" "dudki(8)" "Klever Group (http://www.klever.net/)" 1.TH dudki 8 "July 23rd, 2004" "dudki(8)" "Klever Group (http://www.klever.net/)"
2.hla en 2.hla en
3.ds longopt @HAVE_GETOPT_LONG@ 3.ds longopt @HAVE_GETOPT_LONG@
4 4
5.SH NAME 5.SH NAME
6 6
7dudki \- a process monitoring daemon 7dudki \- a process maintenance daemon
8 8
9.SH SYNOPSYS 9.SH SYNOPSYS
10 10
11\fBdudki\fR [\fB-h\fR] 11\fBdudki\fR [\fB-h\fR]
12.if \*[longopt] [\fB--help\fR] [\fB--usage\fR] 12.if \*[longopt] [\fB--help\fR] [\fB--usage\fR]
13[\fB-V\fR] 13[\fB-V\fR]
14.if \*[longopt] [\fB--version\fR] 14.if \*[longopt] [\fB--version\fR]
15[\fB-L\fR] 15[\fB-L\fR]
16.if \*[longopt] [\fB--license\fR] 16.if \*[longopt] [\fB--license\fR]
17[\fB-f\fR \fIconfigfile\fR] 17[\fB-f\fR \fIconfigfile\fR]
18.if \*[longopt] [\fB--config=\fR\fIconfigfile\fR] 18.if \*[longopt] [\fB--config=\fR\fIconfigfile\fR]
19[\fB-k\fR] 19[\fB-k\fR]
20.if \*[longopt] [\fB--kill\fR] 20.if \*[longopt] [\fB--kill\fR]
21[\fB-r\fR] 21[\fB-r\fR]
22.if \*[longopt] [\fB--reload\fR] 22.if \*[longopt] [\fB--reload\fR]
23[\fB-c\fR] 23[\fB-c\fR]
24.if \*[longopt] [\fB--check\fR] 24.if \*[longopt] [\fB--check\fR]
25[\fB-s\fR \fIsignum\fR]
26.if \*[longopt] [\fB--signal=\fR\fIsignum\fR]
25[\fB-e\fR] 27[\fB-e\fR]
26.if \*[longopt] [\fB--ensure\fR] 28.if \*[longopt] [\fB--ensure\fR]
27[\fB-t\fR] 29[\fB-t\fR]
28.if \*[longopt] [\fB--test\fR] 30.if \*[longopt] [\fB--test\fR]
29[\fI<process-list>\fR] 31[\fI<process-list>\fR]
30 32
31.SH DESCRIPTION 33.SH DESCRIPTION
32 34
33dudki daemon is designed to run in the background and periodically 35dudki daemon is designed to run in the background and periodically
34check if certain processes specified in the configuration file are 36check if certain processes specified in the configuration file are
35running. If a process is detected as dead dudki tries to restart it 37running. If a process is detected as dead dudki tries to restart it
36using the command line specified in the configuration file and notifies 38using the command line specified in the configuration file and notifies
37the specified contact (currently only via email). 39the specified contact (currently only via email).
38 40
39.SH OPTIONS 41.SH OPTIONS
40 42
41.TP 43.TP
42.ie \*[longopt] \fB-f\fR \fIconfigfile\fR, \fB--config=\fR\fIconfigfile\fR 44.ie \*[longopt] \fB-f\fR \fIconfigfile\fR, \fB--config=\fR\fIconfigfile\fR
43.el \fB-f\fR \fIconfigfile\fR 45.el \fB-f\fR \fIconfigfile\fR
44Specify the configuration file to use (default is 46Specify the configuration file to use (default is
45\fI@sysconfdir@/dudki.conf\fR). 47\fI@sysconfdir@/dudki.conf\fR).
46.TP 48.TP
47.ie \*[longopt] \fB-k\fR, \fB--kill\fR 49.ie \*[longopt] \fB-k\fR, \fB--kill\fR
48.el \fB-k\fR 50.el \fB-k\fR
49Stop the running instance by sending the \fBSIGTERM\fR signal. If no process 51Stop the running instance by sending the \fBSIGTERM\fR signal. If no process
50name specified on the command line, dudki kills his own running instance. 52name specified on the command line, dudki kills his own running instance.
51.TP 53.TP
52.ie \*[longopt] \fB-r\fR, \fB--reload\fR 54.ie \*[longopt] \fB-r\fR, \fB--reload\fR
53.el \fB-r\fR 55.el \fB-r\fR
54Reload the running instance by sending the \fBSIGHUP\fR signal. Like with 56Reload the running instance by sending the \fBSIGHUP\fR signal. Like with
55\fB-k\fR, if no process name specified on the command line, dudki sends 57\fB-k\fR, if no process name specified on the command line, dudki sends
56\fBSIGHUP\fR to his own running instance. 58\fBSIGHUP\fR to his own running instance.
57.TP 59.TP
60.ie \*[longopt] \fB-s\fR \fIsignum\fR, \fB--signal=\fR\fIsignum\fR
61.el \fB-s\fR \fIsignum\fR
62Send arbitrary signal to the names processes (or self, but it doesn't make much
63sense).
64.TP
58.ie \*[longopt] \fB-c\fR, \fB--check\fR 65.ie \*[longopt] \fB-c\fR, \fB--check\fR
59.el \fB-c\fR 66.el \fB-c\fR
60Check if dudki is running. Exit with non-zero status if not. The same target 67Check if dudki is running. Exit with non-zero status if not. The same target
61rules as in \fB-k\fR and \fB-r\fR apply here. 68rules as in \fB-k\fR and \fB-r\fR apply here.
62.TP 69.TP
63.ie \*[longopt] \fB-e\fR, \fB--ensure\fR 70.ie \*[longopt] \fB-e\fR, \fB--ensure\fR
64.el \fB-e\fR 71.el \fB-e\fR
65Ensure that dudki is running. Load, if not. Useful for running as a 72Ensure that dudki is running. Load, if not. Useful for running as a
66cron job once in a while. If the daemon is running runs quietly 73cron job once in a while. If the daemon is running runs quietly
67providing no output. 74providing no output.
68.TP 75.TP
69.ie \*[longopt] \fB-t\fR, \fB--test\fR 76.ie \*[longopt] \fB-t\fR, \fB--test\fR
70.el \fB-t\fR 77.el \fB-t\fR
71Check the syntax of configuration file and exit. 78Check the syntax of configuration file and exit.
72.TP 79.TP
73.ie \*[longopt] \fB-h\fR, \fB--help\fR, \fB--usage\fR 80.ie \*[longopt] \fB-h\fR, \fB--help\fR, \fB--usage\fR
74.el \fB-h\fR 81.el \fB-h\fR
75Display short usage message and exit. 82Display short usage message and exit.
76.TP 83.TP
77.ie \*[longopt] \fB-V\fR, \fB--version\fR 84.ie \*[longopt] \fB-V\fR, \fB--version\fR
78.el \fB-V\fR 85.el \fB-V\fR
79Report version and exit. 86Report version and exit.
80.TP 87.TP
81.ie \*[longopt] \fB-L\fR, \fB--license\fR 88.ie \*[longopt] \fB-L\fR, \fB--license\fR
diff --git a/src/dudki.cc b/src/dudki.cc
index e91ad5e..9562079 100644
--- a/src/dudki.cc
+++ b/src/dudki.cc
@@ -1,27 +1,28 @@
1#include <unistd.h> 1#include <unistd.h>
2#include <signal.h> 2#include <signal.h>
3#include <syslog.h> 3#include <syslog.h>
4#include <errno.h>
4#include <iostream> 5#include <iostream>
5#include <fstream> 6#include <fstream>
6#include <stdexcept> 7#include <stdexcept>
7using namespace std; 8using namespace std;
8#include "configuration.h" 9#include "configuration.h"
9#include "util.h" 10#include "util.h"
10 11
11#include "config.h" 12#include "config.h"
12#ifdef HAVE_GETOPT_H 13#ifdef HAVE_GETOPT_H
13# include <getopt.h> 14# include <getopt.h>
14#endif 15#endif
15 16
16#ifndef DEFAULT_CONF_FILE 17#ifndef DEFAULT_CONF_FILE
17# define DEFAULT_CONF_FILE "/etc/dudki.conf" 18# define DEFAULT_CONF_FILE "/etc/dudki.conf"
18#endif 19#endif
19 20
20#define PHEADER PACKAGE " Version " VERSION 21#define PHEADER PACKAGE " Version " VERSION
21#define PCOPY "Copyright (c) 2004 Klever Group" 22#define PCOPY "Copyright (c) 2004 Klever Group"
22 23
23bool finishing = false; 24bool finishing = false;
24bool restarting = false; 25bool restarting = false;
25static char **_argv = NULL; 26static char **_argv = NULL;
26 27
27static void lethal_signal_handler(int signum) { 28static void lethal_signal_handler(int signum) {
@@ -47,97 +48,101 @@ void signal_self(const configuration& config,int signum) {
47 if(!pid) 48 if(!pid)
48 throw runtime_error("Can't detect running instance"); 49 throw runtime_error("Can't detect running instance");
49 if(pid==getpid()) 50 if(pid==getpid())
50 throw 0; 51 throw 0;
51 if(kill(pid,signum)) 52 if(kill(pid,signum))
52 throw runtime_error("Failed to signal running instance"); 53 throw runtime_error("Failed to signal running instance");
53} 54}
54 55
55int main(int argc,char **argv) { 56int main(int argc,char **argv) {
56 try { 57 try {
57 _argv = new char*[argc+1]; 58 _argv = new char*[argc+1];
58 if(!_argv) 59 if(!_argv)
59 throw runtime_error("memory allocation problem at the very start"); 60 throw runtime_error("memory allocation problem at the very start");
60 memmove(_argv,argv,sizeof(*_argv)*(argc+1)); 61 memmove(_argv,argv,sizeof(*_argv)*(argc+1));
61 string config_file = DEFAULT_CONF_FILE; 62 string config_file = DEFAULT_CONF_FILE;
62 enum { 63 enum {
63 op_default, 64 op_default,
64 op_work, 65 op_work,
65 op_signal, 66 op_signal,
66 op_ensure, 67 op_ensure,
67 op_test 68 op_test
68 } op = op_default; 69 } op = op_default;
69 int op_signum = 0; 70 int op_signum = 0;
70 while(true) { 71 while(true) {
71 #defineSHORTOPTSTRING "f:hVLrkcet" 72 #defineSHORTOPTSTRING "f:hVLrkcets:"
72#ifdef HAVE_GETOPT_LONG 73#ifdef HAVE_GETOPT_LONG
73 static struct option opts[] = { 74 static struct option opts[] = {
74 { "help", no_argument, 0, 'h' }, 75 { "help", no_argument, 0, 'h' },
75 { "usage", no_argument, 0, 'h' }, 76 { "usage", no_argument, 0, 'h' },
76 { "version", no_argument, 0, 'V' }, 77 { "version", no_argument, 0, 'V' },
77 { "license", no_argument, 0, 'L' }, 78 { "license", no_argument, 0, 'L' },
78 { "config", required_argument, 0, 'f' }, 79 { "config", required_argument, 0, 'f' },
79 { "kill", no_argument, 0, 'k' }, 80 { "kill", no_argument, 0, 'k' },
80 { "reload", no_argument, 0, 'r' }, 81 { "reload", no_argument, 0, 'r' },
82 { "signal", required_argument, 0, 's' },
81 { "check", no_argument, 0, 'c' }, 83 { "check", no_argument, 0, 'c' },
82 { "ensure", no_argument, 0, 'e' }, 84 { "ensure", no_argument, 0, 'e' },
83 { "test", no_argument, 0, 't' }, 85 { "test", no_argument, 0, 't' },
84 { NULL, 0, 0, 0 } 86 { NULL, 0, 0, 0 }
85 }; 87 };
86 int c = getopt_long(argc,argv,SHORTOPTSTRING,opts,NULL); 88 int c = getopt_long(argc,argv,SHORTOPTSTRING,opts,NULL);
87#else /* !HAVE_GETOPT_LONG */ 89#else /* !HAVE_GETOPT_LONG */
88 int c = getopt(argc,argv,SHORTOPTSTRING); 90 int c = getopt(argc,argv,SHORTOPTSTRING);
89#endif /* /HAVE_GETOPT_LONG */ 91#endif /* /HAVE_GETOPT_LONG */
90 if(c==-1) 92 if(c==-1)
91 break; 93 break;
92 switch(c) { 94 switch(c) {
93 case 'h': 95 case 'h':
94 cerr << PHEADER << endl 96 cerr << PHEADER << endl
95 << PCOPY << endl << endl 97 << PCOPY << endl << endl
96 << " " << argv[0] << " [options] [processes]" << endl << endl << 98 << " " << argv[0] << " [options] [processes]" << endl << endl <<
97#ifdef HAVE_GETOPT_LONG 99#ifdef HAVE_GETOPT_LONG
98 " -h, --help\n" 100 " -h, --help\n"
99 " --usage display this text\n" 101 " --usage display this text\n"
100 " -V, --version display version number\n" 102 " -V, --version display version number\n"
101 " -L, --license show license\n" 103 " -L, --license show license\n"
102 " -f filename, --config=filename\n" 104 " -f filename, --config=filename\n"
103 " specify the configuration file to use\n" 105 " specify the configuration file to use\n"
104 "\n" 106 "\n"
105 " -k, --kill stop running instance (send SIGTERM)\n" 107 " -k, --kill stop running instance (send SIGTERM)\n"
106 " -r, --reload reload running instance (send SIGHUP)\n" 108 " -r, --reload reload running instance (send SIGHUP)\n"
109 " -s signum, --signal=signum\n"
110 " send the specified signal to the running process\n"
107 " -c, --check check if the process is running\n" 111 " -c, --check check if the process is running\n"
108 " (the above commands operate on dudki itself if no\n" 112 " (the above commands operate on dudki itself if no\n"
109 " process name has been specified)\n" 113 " process name has been specified)\n"
110 " -e, --ensure ensure that dudki is running\n" 114 " -e, --ensure ensure that dudki is running\n"
111 " -t, --test test configuration file and exit" 115 " -t, --test test configuration file and exit"
112#else /* !HAVE_GETOPT_LONG */ 116#else /* !HAVE_GETOPT_LONG */
113 " -h display this text\n" 117 " -h display this text\n"
114 " -V display version number\n" 118 " -V display version number\n"
115 " -L show license\n" 119 " -L show license\n"
116 " -f filename specify the configuration file to use\n" 120 " -f filename specify the configuration file to use\n"
117 "\n" 121 "\n"
118 " -k stop running instance (send SIGTERM)\n" 122 " -k stop running instance (send SIGTERM)\n"
119 " -r reload running instance (send SIGHUP)\n" 123 " -r reload running instance (send SIGHUP)\n"
124 " -s signum send the specified signal to the running process\n"
120 " -c check if the process is running\n" 125 " -c check if the process is running\n"
121 " (the above commands operate on dudki itself if no\n" 126 " (the above commands operate on dudki itself if no\n"
122 " process name has been specified)\n" 127 " process name has been specified)\n"
123 " -e ensure that dudki is running\n" 128 " -e ensure that dudki is running\n"
124 " -t test configuration file and exit" 129 " -t test configuration file and exit"
125#endif /* /HAVE_GETOPT_LONG */ 130#endif /* /HAVE_GETOPT_LONG */
126 << endl; 131 << endl;
127 exit(0); 132 exit(0);
128 break; 133 break;
129 case 'V': 134 case 'V':
130 cerr << VERSION << endl; 135 cerr << VERSION << endl;
131 exit(0); 136 exit(0);
132 break; 137 break;
133 case 'L': 138 case 'L':
134 extern const char *COPYING; 139 extern const char *COPYING;
135 cerr << COPYING << endl; 140 cerr << COPYING << endl;
136 exit(0); 141 exit(0);
137 break; 142 break;
138 case 'f': 143 case 'f':
139 config_file = optarg; 144 config_file = optarg;
140 break; 145 break;
141 case 'k': 146 case 'k':
142 if(op!=op_default) { 147 if(op!=op_default) {
143 cerr << "Can't obey two or more orders at once" << endl; 148 cerr << "Can't obey two or more orders at once" << endl;
@@ -152,48 +157,61 @@ int main(int argc,char **argv) {
152 } 157 }
153 op = op_signal; op_signum = SIGHUP; 158 op = op_signal; op_signum = SIGHUP;
154 break; 159 break;
155 case 'c': 160 case 'c':
156 if(op!=op_default) { 161 if(op!=op_default) {
157 cerr << "Can't obey two or more orders at once" << endl; 162 cerr << "Can't obey two or more orders at once" << endl;
158 exit(1); 163 exit(1);
159 } 164 }
160 op = op_signal; op_signum = 0; 165 op = op_signal; op_signum = 0;
161 break; 166 break;
162 case 'e': 167 case 'e':
163 if(op!=op_default) { 168 if(op!=op_default) {
164 cerr << "Can't obey two or more orders at once" << endl; 169 cerr << "Can't obey two or more orders at once" << endl;
165 exit(1); 170 exit(1);
166 } 171 }
167 op = op_ensure; 172 op = op_ensure;
168 break; 173 break;
169 case 't': 174 case 't':
170 if(op!=op_default) { 175 if(op!=op_default) {
171 cerr << "Can't obey two or more orders at once" << endl; 176 cerr << "Can't obey two or more orders at once" << endl;
172 exit(1); 177 exit(1);
173 } 178 }
174 op = op_test; 179 op = op_test;
175 break; 180 break;
181 case 's':
182 if(op!=op_default) {
183 cerr << "Can't obey two or more orders at once" << endl;
184 exit(1);
185 }
186 op = op_signal;
187 errno = 0;
188 op_signum = strtol(optarg,NULL,0);
189 if(errno) {
190 cerr << "Can't obtain the signal value" << endl;
191 exit(1);
192 }
193 break;
176 default: 194 default:
177 cerr << "Huh??" << endl; 195 cerr << "Huh??" << endl;
178 exit(1); 196 exit(1);
179 break; 197 break;
180 } 198 }
181 } 199 }
182 const char *sid = *argv; 200 const char *sid = *argv;
183 const char *t; 201 const char *t;
184 while(t = index(sid,'/')) { 202 while(t = index(sid,'/')) {
185 sid = t; sid++; 203 sid = t; sid++;
186 } 204 }
187 openlog(sid,LOG_CONS|LOG_PERROR|LOG_PID,LOG_DAEMON); 205 openlog(sid,LOG_CONS|LOG_PERROR|LOG_PID,LOG_DAEMON);
188 configuration config; 206 configuration config;
189 config.parse(config_file); 207 config.parse(config_file);
190 switch(op) { 208 switch(op) {
191 case op_test: 209 case op_test:
192 cerr << "Configuration OK" << endl; 210 cerr << "Configuration OK" << endl;
193 break; 211 break;
194 case op_signal: 212 case op_signal:
195 try { 213 try {
196 if(optind>=argc) { 214 if(optind>=argc) {
197 signal_self(config,op_signum); 215 signal_self(config,op_signum);
198 }else{ 216 }else{
199 int failures = 0; 217 int failures = 0;