Merge pull request #46 from sdaoden/rotate
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
commit
0b3d379001
@ -483,6 +483,10 @@ SIGTERM.
|
|||||||
.It USR1
|
.It USR1
|
||||||
In debug mode this switches debugging on/off. In normal operation
|
In debug mode this switches debugging on/off. In normal operation
|
||||||
it is ignored.
|
it is ignored.
|
||||||
|
.It USR2
|
||||||
|
.Nm
|
||||||
|
will rotate all files for which rotation is configured when receiving
|
||||||
|
this signal.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
For convenience the PID is by default stored in
|
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 debugging_on;
|
||||||
static volatile sig_atomic_t restart;
|
static volatile sig_atomic_t restart;
|
||||||
|
static volatile sig_atomic_t rotate_signal;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Intervals at which we flush out "message repeated" messages,
|
* 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 int opensys(const char *file);
|
||||||
static void printsys(char *msg);
|
static void printsys(char *msg);
|
||||||
static void logmsg(struct buf_msg *buffer);
|
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_first(struct filed *f, struct buf_msg *buffer);
|
||||||
static void fprintlog_successive(struct filed *f, int flags);
|
static void fprintlog_successive(struct filed *f, int flags);
|
||||||
void endtty();
|
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_invoke(const char *logfile);
|
||||||
static void notifier_free_all(void);
|
static void notifier_free_all(void);
|
||||||
void reload(int);
|
void reload(int);
|
||||||
|
static void signal_rotate(int sig);
|
||||||
static int validate(struct sockaddr *sa, const char *hname);
|
static int validate(struct sockaddr *sa, const char *hname);
|
||||||
static int waitdaemon(int);
|
static int waitdaemon(int);
|
||||||
static void timedout(int);
|
static void timedout(int);
|
||||||
@ -589,6 +594,12 @@ no_klogd:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rotate_signal > 0) {
|
||||||
|
rotate_signal = 0;
|
||||||
|
logit("\nReceived SIGUSR2, forcing log rotation.\n");
|
||||||
|
rotate_all_files();
|
||||||
|
}
|
||||||
|
|
||||||
if (rc < 0 && errno != EINTR)
|
if (rc < 0 && errno != EINTR)
|
||||||
ERR("select()");
|
ERR("select()");
|
||||||
|
|
||||||
@ -1560,7 +1571,7 @@ static void logmsg(struct buf_msg *buffer)
|
|||||||
sigprocmask(SIG_UNBLOCK, &mask, NULL);
|
sigprocmask(SIG_UNBLOCK, &mask, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void logrotate(struct filed *f)
|
static void logrotate(struct filed *f)
|
||||||
{
|
{
|
||||||
struct stat statf;
|
struct stat statf;
|
||||||
|
|
||||||
@ -1571,52 +1582,66 @@ void logrotate(struct filed *f)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* bug (mostly harmless): can wrap around if file > 4gb */
|
/* bug (mostly harmless): can wrap around if file > 4gb */
|
||||||
if (S_ISREG(statf.st_mode) && statf.st_size > f->f_rotatesz) {
|
if (S_ISREG(statf.st_mode) && statf.st_size > f->f_rotatesz)
|
||||||
if (f->f_rotatecount > 0) { /* always 0..999 */
|
rotate_file(f);
|
||||||
int len = strlen(f->f_un.f_fname) + 10 + 5;
|
}
|
||||||
int i;
|
|
||||||
char oldFile[len];
|
|
||||||
char newFile[len];
|
|
||||||
|
|
||||||
/* First age zipped log files */
|
static void rotate_file(struct filed *f)
|
||||||
for (i = f->f_rotatecount; i > 1; i--) {
|
{
|
||||||
snprintf(oldFile, len, "%s.%d.gz", f->f_un.f_fname, i - 1);
|
if (f->f_rotatecount > 0) { /* always 0..999 */
|
||||||
snprintf(newFile, len, "%s.%d.gz", f->f_un.f_fname, i);
|
int len = strlen(f->f_un.f_fname) + 10 + 5;
|
||||||
|
int i;
|
||||||
|
char oldFile[len];
|
||||||
|
char newFile[len];
|
||||||
|
|
||||||
/* ignore errors - file might be missing */
|
/* First age zipped log files */
|
||||||
(void)rename(oldFile, newFile);
|
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; ... */
|
/* ignore errors - file might be missing */
|
||||||
for (i = 1; i > 0; i--) {
|
(void)rename(oldFile, newFile);
|
||||||
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);
|
|
||||||
|
/* 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(SIGINT, Debug ? die : SIG_IGN);
|
||||||
SIGNAL(SIGQUIT, Debug ? die : SIG_IGN);
|
SIGNAL(SIGQUIT, Debug ? die : SIG_IGN);
|
||||||
SIGNAL(SIGUSR1, Debug ? debug_switch : SIG_IGN);
|
SIGNAL(SIGUSR1, Debug ? debug_switch : SIG_IGN);
|
||||||
|
SIGNAL(SIGUSR2, signal_rotate);
|
||||||
SIGNAL(SIGXFSZ, SIG_IGN);
|
SIGNAL(SIGXFSZ, SIG_IGN);
|
||||||
SIGNAL(SIGHUP, reload);
|
SIGNAL(SIGHUP, reload);
|
||||||
SIGNAL(SIGCHLD, reapchild);
|
SIGNAL(SIGCHLD, reapchild);
|
||||||
@ -3445,6 +3471,15 @@ void reload(int signo)
|
|||||||
restart++;
|
restart++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SIGUSR2: forced rotation for so-configured files as soon as possible.
|
||||||
|
*/
|
||||||
|
static void signal_rotate(int sig)
|
||||||
|
{
|
||||||
|
(void)sig;
|
||||||
|
rotate_signal++;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Local Variables:
|
* Local Variables:
|
||||||
* indent-tabs-mode: t
|
* indent-tabs-mode: t
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
EXTRA_DIST = lib.sh opts.sh
|
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
|
CLEANFILES = *~ *.trs *.log
|
||||||
TEST_EXTENSIONS = .sh
|
TEST_EXTENSIONS = .sh
|
||||||
TESTS_ENVIRONMENT= unshare -mrun
|
TESTS_ENVIRONMENT= unshare -mrun
|
||||||
@ -18,5 +19,6 @@ TESTS += api.sh
|
|||||||
TESTS += fwd.sh
|
TESTS += fwd.sh
|
||||||
TESTS += mark.sh
|
TESTS += mark.sh
|
||||||
TESTS += notify.sh
|
TESTS += notify.sh
|
||||||
|
TESTS += rotate_all.sh
|
||||||
|
|
||||||
programs: $(check_PROGRAMS)
|
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
|
Loading…
Reference in New Issue
Block a user