File: Selective-logging.patch

package info (click to toggle)
cron 3.0pl1-197
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 3,816 kB
  • sloc: ansic: 54,879; xml: 1,600; perl: 733; sh: 463; makefile: 446; python: 43
file content (259 lines) | stat: -rw-r--r-- 7,326 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
From: Christian Kastner <ckk@kvr.at>
Date: Fri, 15 Jan 2016 23:05:10 +0100
Subject: Selective logging

This implements a fine-grained control over what the cron daemon logs when it
executes jobs. This is driven via the '-L' command line option, which accepts a
bitmask of values for logging the start, end, failure and PID of jobs. The
following things can be logged:
    * Start of cron jobs
    * End of cron jobs
    * Failed jobs
    * Include PID of cron job in messages

The default is to log the start of jobs. 

Initially contributed by Steve Fosdick <dbugs@pelvoux.nildram.co.uk>.

Bug-Debian: https://bugs.debian.org/271747
Bug-Debian: https://bugs.debian.org/318247
Forwarded: no
Last-Update: 2016-01-15
---
 cron.8       | 25 ++++++++++++++++++++++++-
 cron.c       |  8 ++++++--
 cron.h       |  9 ++++++++-
 do_command.c | 56 ++++++++++++++++++++++++++++++++++++++++----------------
 4 files changed, 78 insertions(+), 20 deletions(-)

diff --git a/cron.8 b/cron.8
index 23a50c0..77cb100 100644
--- a/cron.8
+++ b/cron.8
@@ -25,6 +25,8 @@ cron \- daemon to execute scheduled commands (Vixie Cron)
 cron
 .RB [ \-f ]
 .RB [ \-l ]
+.RB [ \-L
+.IR loglevel ]
 .SH DESCRIPTION
 .I cron
 is started automatically from /etc/init.d on entering multi-user
@@ -38,6 +40,27 @@ Stay in foreground mode, don't daemonize.
 Enable LSB compliant names for /etc/cron.d files.  This setting, however, does
 not affect the parsing of files under /etc/cron.hourly, /etc/cron.daily,
 /etc/cron.weekly or /etc/cron.monthly.
+.TP
+.B \-L loglevel
+Tell cron what to log about \fBjobs\fR (errors are logged regardless of this
+value) as the sum of the following values:
+.br
+.RS 12
+.IP \fB1\fR
+will log the start of all cron jobs
+.IP \fB2\fR
+will log the end of all cron jobs
+.IP \fB4\fR
+will log all failed jobs (exit status != 0)
+.IP \fB8\fR
+will log the process number of all cron jobs
+.RE
+.IP
+The default is to log the start of all jobs (1).
+Logging will be disabled if
+.I levels
+is set to zero (0).
+A value of fifteen (15) will select all options.
 .SH NOTES
 .PP
 .I cron
@@ -272,7 +295,7 @@ daemon.  This file determines whether
 will read the system's environment variables and makes it possible to add
 additional options to the
 .I cron
-program before it is executed, for example to define how
+program before it is executed, either to configure its logging or to define how
 it will treat the files under /etc/cron.d.
 
 .SH "SEE ALSO"
diff --git a/cron.c b/cron.c
index 53a6dae..84b19e6 100644
--- a/cron.c
+++ b/cron.c
@@ -447,9 +447,9 @@ sighup_handler(int x) {
 
 
 #if DEBUGGING
-const char *getoptarg = "flx:";
+const char *getoptarg = "flL:x:";
 #else
-const char *getoptarg = "fl";
+const char *getoptarg = "flL:";
 #endif
 
 static void
@@ -461,6 +461,7 @@ parse_args(argc, argv)
 
 	stay_foreground = 0;
 	lsbsysinit_mode = 0;
+	log_level = 1;
 
 	while (EOF != (argch = getopt(argc, argv, getoptarg))) {
 		switch (argch) {
@@ -472,6 +473,9 @@ parse_args(argc, argv)
 		case 'l':
 			lsbsysinit_mode = 1;
 			break;
+		case 'L':
+			log_level = atoi(optarg);
+			break;
 #if DEBUGGING
 		case 'x':
 			if (!set_debug_flags(optarg))
diff --git a/cron.h b/cron.h
index 30b36e9..6c866a4 100644
--- a/cron.h
+++ b/cron.h
@@ -138,6 +138,12 @@
 
 typedef int time_min;
 
+/* Log levels */
+#define	CRON_LOG_JOBSTART	0x01
+#define	CRON_LOG_JOBEND		0x02
+#define	CRON_LOG_JOBFAILED	0x04
+#define	CRON_LOG_JOBPID		0x08
+
 #define SECONDS_PER_MINUTE 60
 
 #define	FIRST_MINUTE	0
@@ -210,7 +216,6 @@ typedef	struct _cron_db {
 	time_t		sysd_mtime;     /* last modtime on system crondir */
 } cron_db;
 
-
 void		set_cron_uid __P((void)),
 		set_cron_cwd __P((void)),
 		load_database __P((cron_db *)),
@@ -294,6 +299,7 @@ static long GMToff;
 
 int	stay_foreground;
 int	lsbsysinit_mode;
+int	log_level;
 
 char	cron_default_mail_charset[MAX_ENVSTR] = "";
 
@@ -310,6 +316,7 @@ extern	char	*copyright[],
 		*DowNames[],
 		*ProgramName;
 extern	int	lsbsysinit_mode;
+extern	int	log_level;
 extern	int	LineNumber;
 extern	time_t	StartTime;
 extern  time_min timeRunning;
diff --git a/do_command.c b/do_command.c
index 923e507..e024995 100644
--- a/do_command.c
+++ b/do_command.c
@@ -131,6 +131,7 @@ child_process(e, u)
 	register char	*input_data;
 	char		*usernm, *mailto;
 	int		children = 0;
+	pid_t		job_pid;
 #if defined(USE_PAM)
 	int		retcode = 0;
 #endif
@@ -228,7 +229,7 @@ child_process(e, u)
 
 	/* fork again, this time so we can exec the user's command.
 	 */
-	switch (fork()) {
+	switch (job_pid = fork()) {
 	case -1:
 		log_it("CRON",getpid(),"error","can't fork");
 		exit(ERROR_EXIT);
@@ -242,14 +243,12 @@ child_process(e, u)
 		 * the actual user command shell was going to get and the
 		 * PID is part of the log message.
 		 */
-		/*local*/{
+		if ((log_level & CRON_LOG_JOBSTART) && ! (log_level & CRON_LOG_JOBPID)) {
 			char *x = mkprints((u_char *)e->cmd, strlen(e->cmd));
-
 			log_it(usernm, getpid(), "CMD", x);
 			free(x);
 		}
-
-		/* that's the last thing we'll log.  close the log files.
+		/* nothing to log from now on. close the log files.
 		 */
 		log_close();
 
@@ -357,6 +356,16 @@ child_process(e, u)
 		break;
 	default:
 		/* parent process */
+		/* write a log message if we want the parent and child
+		 * PID values
+		 */
+		if ( (log_level & CRON_LOG_JOBSTART) && (log_level & CRON_LOG_JOBPID)) {
+			char logcmd[MAX_COMMAND + 8];
+			snprintf(logcmd, sizeof(logcmd), "[%d] %s", (int) job_pid, e->cmd);
+			char *x = mkprints((u_char *)logcmd, strlen(logcmd));
+			log_it(usernm, getpid(), "CMD", x);
+			free(x);
+		}
 		break;
 	}
 
@@ -458,17 +467,19 @@ child_process(e, u)
 		Debug(DPROC, ("[%d] grandchild #%d finished, status=%04x\n",
 			getpid(), pid, WEXITSTATUS(waiter)))
 
-		if (WIFEXITED(waiter) && WEXITSTATUS(waiter)) {
-			status = waiter;
-			snprintf(msg, 256, "grandchild #%d failed with exit "
-				"status %d", pid, WEXITSTATUS(waiter));
-			log_it("CRON", getpid(), "error", msg);
-		} else if (WIFSIGNALED(waiter)) {
-			status = waiter;
-			snprintf(msg, 256, "grandchild #%d terminated by signal"
-				" %d%s", pid, WTERMSIG(waiter),
-				WCOREDUMP(waiter) ? ", dumped core" : "");
-			log_it("CRON", getpid(), "error", msg);
+		if (log_level & CRON_LOG_JOBFAILED) {
+			if (WIFEXITED(waiter) && WEXITSTATUS(waiter)) {
+				status = waiter;
+				snprintf(msg, 256, "grandchild #%d failed with exit "
+					"status %d", pid, WEXITSTATUS(waiter));
+				log_it("CRON", getpid(), "error", msg);
+			} else if (WIFSIGNALED(waiter)) {
+				status = waiter;
+				snprintf(msg, 256, "grandchild #%d terminated by signal"
+					" %d%s", pid, WTERMSIG(waiter),
+					WCOREDUMP(waiter) ? ", dumped core" : "");
+				log_it("CRON", getpid(), "error", msg);
+			}
 		}
 	}
 
@@ -616,6 +627,19 @@ child_process(e, u)
 mail_finished:
 	fclose(tmpout);
 
+	if (log_level & CRON_LOG_JOBEND) {
+		char *x;
+		if (log_level & CRON_LOG_JOBPID) {
+			char logcmd[MAX_COMMAND + 8];
+			snprintf(logcmd, sizeof(logcmd), "[%d] %s", (int) job_pid, e->cmd);
+			x = mkprints((u_char *)logcmd, strlen(logcmd));
+		} else {
+			x = mkprints((u_char *)e->cmd, strlen(e->cmd));
+		}
+		log_it(usernm, job_pid, "END", x);
+		free(x);
+	}
+
 #if defined(USE_PAM)
 	pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT);
 	retcode = pam_close_session(pamh, PAM_SILENT);