Merge pull request #46 from sdaoden/rotate

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg 2022-03-14 05:53:25 +01:00
commit 0b3d379001
4 changed files with 180 additions and 44 deletions

View File

@ -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

View File

@ -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(&nothead))
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(&nothead))
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

View File

@ -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
View 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