Merge pull request #46 from sdaoden/rotate
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
		@@ -483,6 +483,10 @@ SIGTERM.
 | 
			
		||||
.It USR1
 | 
			
		||||
In debug mode this switches debugging on/off.  In normal operation
 | 
			
		||||
it is ignored.
 | 
			
		||||
.It USR2
 | 
			
		||||
.Nm
 | 
			
		||||
will rotate all files for which rotation is configured when receiving
 | 
			
		||||
this signal.
 | 
			
		||||
.El
 | 
			
		||||
.Pp
 | 
			
		||||
For convenience the PID is by default stored in
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										121
									
								
								src/syslogd.c
									
									
									
									
									
								
							
							
						
						
									
										121
									
								
								src/syslogd.c
									
									
									
									
									
								
							@@ -103,6 +103,7 @@ char  ctty[]    = _PATH_CONSOLE;
 | 
			
		||||
 | 
			
		||||
static volatile sig_atomic_t debugging_on;
 | 
			
		||||
static volatile sig_atomic_t restart;
 | 
			
		||||
static volatile sig_atomic_t rotate_signal;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Intervals at which we flush out "message repeated" messages,
 | 
			
		||||
@@ -169,6 +170,9 @@ static void parsemsg(const char *from, char *msg);
 | 
			
		||||
static int  opensys(const char *file);
 | 
			
		||||
static void printsys(char *msg);
 | 
			
		||||
static void logmsg(struct buf_msg *buffer);
 | 
			
		||||
static void logrotate(struct filed *f);
 | 
			
		||||
static void rotate_file(struct filed *f);
 | 
			
		||||
static void rotate_all_files(void);
 | 
			
		||||
static void fprintlog_first(struct filed *f, struct buf_msg *buffer);
 | 
			
		||||
static void fprintlog_successive(struct filed *f, int flags);
 | 
			
		||||
void        endtty();
 | 
			
		||||
@@ -192,6 +196,7 @@ static void notifier_add(struct notifiers *newn, const char *program);
 | 
			
		||||
static void notifier_invoke(const char *logfile);
 | 
			
		||||
static void notifier_free_all(void);
 | 
			
		||||
void        reload(int);
 | 
			
		||||
static void signal_rotate(int sig);
 | 
			
		||||
static int  validate(struct sockaddr *sa, const char *hname);
 | 
			
		||||
static int	waitdaemon(int);
 | 
			
		||||
static void	timedout(int);
 | 
			
		||||
@@ -589,6 +594,12 @@ no_klogd:
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (rotate_signal > 0) {
 | 
			
		||||
			rotate_signal = 0;
 | 
			
		||||
			logit("\nReceived SIGUSR2, forcing log rotation.\n");
 | 
			
		||||
			rotate_all_files();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (rc < 0 && errno != EINTR)
 | 
			
		||||
			ERR("select()");
 | 
			
		||||
 | 
			
		||||
@@ -1560,7 +1571,7 @@ static void logmsg(struct buf_msg *buffer)
 | 
			
		||||
	sigprocmask(SIG_UNBLOCK, &mask, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void logrotate(struct filed *f)
 | 
			
		||||
static void logrotate(struct filed *f)
 | 
			
		||||
{
 | 
			
		||||
	struct stat statf;
 | 
			
		||||
 | 
			
		||||
@@ -1571,52 +1582,66 @@ void logrotate(struct filed *f)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* bug (mostly harmless): can wrap around if file > 4gb */
 | 
			
		||||
	if (S_ISREG(statf.st_mode) && statf.st_size > f->f_rotatesz) {
 | 
			
		||||
		if (f->f_rotatecount > 0) { /* always 0..999 */
 | 
			
		||||
			int  len = strlen(f->f_un.f_fname) + 10 + 5;
 | 
			
		||||
			int  i;
 | 
			
		||||
			char oldFile[len];
 | 
			
		||||
			char newFile[len];
 | 
			
		||||
	if (S_ISREG(statf.st_mode) && statf.st_size > f->f_rotatesz)
 | 
			
		||||
		rotate_file(f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
			/* First age zipped log files */
 | 
			
		||||
			for (i = f->f_rotatecount; i > 1; i--) {
 | 
			
		||||
				snprintf(oldFile, len, "%s.%d.gz", f->f_un.f_fname, i - 1);
 | 
			
		||||
				snprintf(newFile, len, "%s.%d.gz", f->f_un.f_fname, i);
 | 
			
		||||
static void rotate_file(struct filed *f)
 | 
			
		||||
{
 | 
			
		||||
	if (f->f_rotatecount > 0) { /* always 0..999 */
 | 
			
		||||
		int  len = strlen(f->f_un.f_fname) + 10 + 5;
 | 
			
		||||
		int  i;
 | 
			
		||||
		char oldFile[len];
 | 
			
		||||
		char newFile[len];
 | 
			
		||||
 | 
			
		||||
				/* ignore errors - file might be missing */
 | 
			
		||||
				(void)rename(oldFile, newFile);
 | 
			
		||||
			}
 | 
			
		||||
		/* First age zipped log files */
 | 
			
		||||
		for (i = f->f_rotatecount; i > 1; i--) {
 | 
			
		||||
			snprintf(oldFile, len, "%s.%d.gz", f->f_un.f_fname, i - 1);
 | 
			
		||||
			snprintf(newFile, len, "%s.%d.gz", f->f_un.f_fname, i);
 | 
			
		||||
 | 
			
		||||
			/* rename: f.8 -> f.9; f.7 -> f.8; ... */
 | 
			
		||||
			for (i = 1; i > 0; i--) {
 | 
			
		||||
				snprintf(oldFile, len, "%s.%d", f->f_un.f_fname, i - 1);
 | 
			
		||||
				snprintf(newFile, len, "%s.%d", f->f_un.f_fname, i);
 | 
			
		||||
 | 
			
		||||
				if (!rename(oldFile, newFile) && i > 0) {
 | 
			
		||||
					size_t clen = 18 + strlen(newFile) + 1;
 | 
			
		||||
					char cmd[clen];
 | 
			
		||||
 | 
			
		||||
					snprintf(cmd, sizeof(cmd), "gzip -f %s", newFile);
 | 
			
		||||
					system(cmd);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/* newFile == "f.0" now */
 | 
			
		||||
			snprintf(newFile, len, "%s.0", f->f_un.f_fname);
 | 
			
		||||
			(void)rename(f->f_un.f_fname, newFile);
 | 
			
		||||
			close(f->f_file);
 | 
			
		||||
 | 
			
		||||
			f->f_file = open(f->f_un.f_fname, O_CREATE | O_NONBLOCK | O_NOCTTY, 0644);
 | 
			
		||||
			if (f->f_file < 0) {
 | 
			
		||||
				f->f_type = F_UNUSED;
 | 
			
		||||
				ERR("Failed re-opening log file %s after rotation", f->f_un.f_fname);
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (!SIMPLEQ_EMPTY(¬head))
 | 
			
		||||
				notifier_invoke(f->f_un.f_fname);
 | 
			
		||||
			/* ignore errors - file might be missing */
 | 
			
		||||
			(void)rename(oldFile, newFile);
 | 
			
		||||
		}
 | 
			
		||||
		ftruncate(f->f_file, 0);
 | 
			
		||||
 | 
			
		||||
		/* rename: f.8 -> f.9; f.7 -> f.8; ... */
 | 
			
		||||
		for (i = 1; i > 0; i--) {
 | 
			
		||||
			snprintf(oldFile, len, "%s.%d", f->f_un.f_fname, i - 1);
 | 
			
		||||
			snprintf(newFile, len, "%s.%d", f->f_un.f_fname, i);
 | 
			
		||||
 | 
			
		||||
			if (!rename(oldFile, newFile) && i > 0) {
 | 
			
		||||
				size_t clen = 18 + strlen(newFile) + 1;
 | 
			
		||||
				char cmd[clen];
 | 
			
		||||
 | 
			
		||||
				snprintf(cmd, sizeof(cmd), "gzip -f %s", newFile);
 | 
			
		||||
				system(cmd);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* newFile == "f.0" now */
 | 
			
		||||
		snprintf(newFile, len, "%s.0", f->f_un.f_fname);
 | 
			
		||||
		(void)rename(f->f_un.f_fname, newFile);
 | 
			
		||||
		close(f->f_file);
 | 
			
		||||
 | 
			
		||||
		f->f_file = open(f->f_un.f_fname, O_CREATE | O_NONBLOCK | O_NOCTTY, 0644);
 | 
			
		||||
		if (f->f_file < 0) {
 | 
			
		||||
			f->f_type = F_UNUSED;
 | 
			
		||||
			ERR("Failed re-opening log file %s after rotation", f->f_un.f_fname);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!SIMPLEQ_EMPTY(¬head))
 | 
			
		||||
			notifier_invoke(f->f_un.f_fname);
 | 
			
		||||
	}
 | 
			
		||||
	ftruncate(f->f_file, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void rotate_all_files(void)
 | 
			
		||||
{
 | 
			
		||||
	struct filed *f;
 | 
			
		||||
 | 
			
		||||
	SIMPLEQ_FOREACH(f, &fhead, f_link) {
 | 
			
		||||
		if (f->f_type == F_FILE && f->f_rotatesz)
 | 
			
		||||
			rotate_file(f);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -2443,6 +2468,7 @@ static void signal_init(void)
 | 
			
		||||
	SIGNAL(SIGINT,  Debug ? die : SIG_IGN);
 | 
			
		||||
	SIGNAL(SIGQUIT, Debug ? die : SIG_IGN);
 | 
			
		||||
	SIGNAL(SIGUSR1, Debug ? debug_switch : SIG_IGN);
 | 
			
		||||
	SIGNAL(SIGUSR2, signal_rotate);
 | 
			
		||||
	SIGNAL(SIGXFSZ, SIG_IGN);
 | 
			
		||||
	SIGNAL(SIGHUP,  reload);
 | 
			
		||||
	SIGNAL(SIGCHLD, reapchild);
 | 
			
		||||
@@ -3445,6 +3471,15 @@ void reload(int signo)
 | 
			
		||||
	restart++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * SIGUSR2: forced rotation for so-configured files as soon as possible.
 | 
			
		||||
 */
 | 
			
		||||
static void signal_rotate(int sig)
 | 
			
		||||
{
 | 
			
		||||
	(void)sig;
 | 
			
		||||
	rotate_signal++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 *  indent-tabs-mode: t
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
EXTRA_DIST       = lib.sh opts.sh
 | 
			
		||||
EXTRA_DIST      += api.sh local.sh unicode.sh remote.sh fwd.sh mark.sh notify.sh
 | 
			
		||||
EXTRA_DIST      += api.sh local.sh unicode.sh remote.sh fwd.sh mark.sh \
 | 
			
		||||
			notify.sh rotate_all.sh
 | 
			
		||||
CLEANFILES       = *~ *.trs *.log
 | 
			
		||||
TEST_EXTENSIONS  = .sh
 | 
			
		||||
TESTS_ENVIRONMENT= unshare -mrun
 | 
			
		||||
@@ -18,5 +19,6 @@ TESTS           += api.sh
 | 
			
		||||
TESTS           += fwd.sh
 | 
			
		||||
TESTS           += mark.sh
 | 
			
		||||
TESTS           += notify.sh
 | 
			
		||||
TESTS           += rotate_all.sh
 | 
			
		||||
 | 
			
		||||
programs: $(check_PROGRAMS)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										95
									
								
								test/rotate_all.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										95
									
								
								test/rotate_all.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,95 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
set -x
 | 
			
		||||
 | 
			
		||||
if [ x"${srcdir}" = x ]; then
 | 
			
		||||
    srcdir=.
 | 
			
		||||
fi
 | 
			
		||||
. ${srcdir}/lib.sh
 | 
			
		||||
 | 
			
		||||
[ -x ../src/logger ] || SKIP 'logger missing'
 | 
			
		||||
command -v zgrep >/dev/null 2>&1 || SKIP 'zgrep(1) missing'
 | 
			
		||||
 | 
			
		||||
NOT1=${DIR}/${NM}-1.sh
 | 
			
		||||
NOT1STAMP=${DIR}/${NM}-1.stamp
 | 
			
		||||
NOT2=${DIR}/${NM}-2.sh
 | 
			
		||||
NOT2STAMP=${DIR}/${NM}-2.stamp
 | 
			
		||||
 | 
			
		||||
printf '#!/bin/sh -\necho script 1: $* >> '${NOT1STAMP}'\n' > ${NOT1}
 | 
			
		||||
chmod 0755 ${NOT1}
 | 
			
		||||
 | 
			
		||||
cat <<EOF > ${CONFD}/rotate_all.conf
 | 
			
		||||
notify ${NOT1}
 | 
			
		||||
*.*       -${LOG}    ;rotate=10k:2,RFC5424
 | 
			
		||||
*.*       -${LOG}X   ;rotate=10k:2,RFC5424
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
setup
 | 
			
		||||
 | 
			
		||||
rm -f ${NOT1STAMP}
 | 
			
		||||
../src/logger -u ${SOCK} notrotall-1
 | 
			
		||||
 | 
			
		||||
kill -USR2 `cat ${PID}`
 | 
			
		||||
sleep 3
 | 
			
		||||
if [ -f ${LOG}.0 ] && [ -f ${LOG}X.0 ] &&
 | 
			
		||||
		grep notrotall-1 ${LOG}.0 &&
 | 
			
		||||
		grep notrotall-1 ${LOG}X.0; then
 | 
			
		||||
	:
 | 
			
		||||
else
 | 
			
		||||
	FAIL 'Missing log entries, I.'
 | 
			
		||||
fi
 | 
			
		||||
if [ -f ${NOT1STAMP} ] && grep 'script 1' ${NOT1STAMP} &&
 | 
			
		||||
		grep ${LOG} ${NOT1STAMP} && grep ${LOG}X ${NOT1STAMP}; then
 | 
			
		||||
	:
 | 
			
		||||
else
 | 
			
		||||
	FAIL 'Notifier did not run, I.'
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
rm -f ${NOT1STAMP}
 | 
			
		||||
../src/logger -u ${SOCK} notrotall-2
 | 
			
		||||
 | 
			
		||||
kill -USR2 `cat ${PID}`
 | 
			
		||||
sleep 3
 | 
			
		||||
if [ -f ${LOG}.0 ] && [ -f ${LOG}X.0 ] &&
 | 
			
		||||
		[ -f ${LOG}.1.gz ] && [ -f ${LOG}X.1.gz ] &&
 | 
			
		||||
		grep notrotall-2 ${LOG}.0 &&
 | 
			
		||||
		grep notrotall-2 ${LOG}X.0 &&
 | 
			
		||||
		zgrep notrotall-1 ${LOG}.1.gz &&
 | 
			
		||||
		zgrep notrotall-1 ${LOG}X.1.gz; then
 | 
			
		||||
	:
 | 
			
		||||
else
 | 
			
		||||
	FAIL 'Missing log entries, II.'
 | 
			
		||||
fi
 | 
			
		||||
if [ -f ${NOT1STAMP} ] && grep 'script 1' ${NOT1STAMP} &&
 | 
			
		||||
		grep ${LOG} ${NOT1STAMP} && grep ${LOG}X ${NOT1STAMP}; then
 | 
			
		||||
	:
 | 
			
		||||
else
 | 
			
		||||
	FAIL 'Notifier did not run, II.'
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
cp $NOT1STAMP /tmp/
 | 
			
		||||
rm -f ${NOT1STAMP}
 | 
			
		||||
../src/logger -u ${SOCK} notrotall-3
 | 
			
		||||
 | 
			
		||||
kill -USR2 `cat ${PID}`
 | 
			
		||||
sleep 3
 | 
			
		||||
if [ -f ${LOG}.0 ] && [ -f ${LOG}X.0 ] &&
 | 
			
		||||
		[ -f ${LOG}.1.gz ] && [ -f ${LOG}X.1.gz ] &&
 | 
			
		||||
		[ -f ${LOG}.2.gz ] && [ -f ${LOG}X.2.gz ] &&
 | 
			
		||||
		grep notrotall-3 ${LOG}.0 &&
 | 
			
		||||
		grep notrotall-3 ${LOG}X.0 &&
 | 
			
		||||
		zgrep notrotall-2 ${LOG}.1.gz &&
 | 
			
		||||
		zgrep notrotall-2 ${LOG}X.1.gz &&
 | 
			
		||||
		zgrep notrotall-1 ${LOG}.2.gz &&
 | 
			
		||||
		zgrep notrotall-1 ${LOG}X.2.gz; then
 | 
			
		||||
	:
 | 
			
		||||
else
 | 
			
		||||
	FAIL 'Missing log entries, III.'
 | 
			
		||||
fi
 | 
			
		||||
if [ -f ${NOT1STAMP} ] && grep 'script 1' ${NOT1STAMP} &&
 | 
			
		||||
		grep ${LOG} ${NOT1STAMP} && grep ${LOG}X ${NOT1STAMP}; then
 | 
			
		||||
	:
 | 
			
		||||
else
 | 
			
		||||
	FAIL 'Notifier did not run, III.'
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
OK
 | 
			
		||||
		Reference in New Issue
	
	Block a user