1
0
Fork 0
mirror of https://github.com/pygos/init.git synced 2024-11-22 19:19:47 +01:00

usyslogd: more control over log rotate behaviour, command line processing

- Add more fine grained control over how log rotation is supposed to behave
 - Add command line option processing to usyslogd
 - Expose log rotation control via command line switches
 - Add default values to usyslogd service for pygos use case

Signed-off-by: David Oberhollenzer <david.oberhollenzer@tele2.at>
This commit is contained in:
David Oberhollenzer 2018-08-16 22:32:34 +02:00
parent 21b88d9352
commit 29e4fc5607
4 changed files with 123 additions and 12 deletions

View file

@ -1,5 +1,5 @@
description "starting usyslogd" description "starting usyslogd"
exec usyslogd exec usyslogd --rotate-replace --max-size 8192
type respawn limit 5 type respawn limit 5
target boot target boot
after vfs after vfs

View file

@ -20,8 +20,30 @@
#include "proto.h" #include "proto.h"
enum {
/*
Rotate log data in a way that we still generate a continuous stream
of log data. E.g. in the case of log files, move the current log file
to one suffixed with a timestamp. We don't lose any log data.
*/
LOG_ROTATE_CONTINUOUS = 0x00,
/*
Rotate log data by overwriting old data with more recent data.
E.g. in the case of log files, move the current log file to one
with a constant prefix, overwriting any existing data.
*/
LOG_ROTATE_OVERWRITE = 0x01,
/*
Automatically do a log rotatation if a log stream reaches a preset
size limit.
*/
LOG_ROTATE_SIZE_LIMIT = 0x10,
};
typedef struct log_backend_t { typedef struct log_backend_t {
int (*init)(struct log_backend_t *log); int (*init)(struct log_backend_t *log, int flags, size_t sizelimit);
void (*cleanup)(struct log_backend_t *log); void (*cleanup)(struct log_backend_t *log);

View file

@ -83,6 +83,8 @@ typedef struct logfile_t {
typedef struct { typedef struct {
log_backend_t base; log_backend_t base;
logfile_t *list; logfile_t *list;
size_t maxsize;
int flags;
} log_backend_file_t; } log_backend_file_t;
@ -156,16 +158,20 @@ static int logfile_write(logfile_t *file, const syslog_msg_t *msg)
return 0; return 0;
} }
static int logfile_rotate(logfile_t *f) static int logfile_rotate(logfile_t *f, int flags)
{ {
char timebuf[32]; char timebuf[32];
char *filename; char *filename;
struct tm tm; struct tm tm;
time_t now; time_t now;
if (flags & LOG_ROTATE_OVERWRITE) {
strcpy(timebuf, "1");
} else {
now = time(NULL); now = time(NULL);
gmtime_r(&now, &tm); gmtime_r(&now, &tm);
strftime(timebuf, sizeof(timebuf), "%FT%T", &tm); strftime(timebuf, sizeof(timebuf), "%FT%T", &tm);
}
filename = alloca(strlen(f->filename) + strlen(timebuf) + 2); filename = alloca(strlen(f->filename) + strlen(timebuf) + 2);
sprintf(filename, "%s.%s", f->filename, timebuf); sprintf(filename, "%s.%s", f->filename, timebuf);
@ -182,9 +188,10 @@ static int logfile_rotate(logfile_t *f)
/*****************************************************************************/ /*****************************************************************************/
static int file_backend_init(log_backend_t *log) static int file_backend_init(log_backend_t *backend, int flags,
size_t sizelimit)
{ {
(void)log; log_backend_file_t *log = (log_backend_file_t *)backend;
if (mkdir(SYSLOG_PATH, 0755)) { if (mkdir(SYSLOG_PATH, 0755)) {
if (errno != EEXIST) { if (errno != EEXIST) {
@ -198,6 +205,8 @@ static int file_backend_init(log_backend_t *log)
return -1; return -1;
} }
log->flags = flags;
log->maxsize = sizelimit;
return 0; return 0;
} }
@ -254,7 +263,13 @@ static int file_backend_write(log_backend_t *backend, const syslog_msg_t *msg)
log->list = f; log->list = f;
} }
return logfile_write(f, msg); if (logfile_write(f, msg))
return -1;
if ((log->flags & LOG_ROTATE_SIZE_LIMIT) && f->size >= log->maxsize)
logfile_rotate(f, log->flags);
return 0;
} }
static void file_backend_rotate(log_backend_t *backend) static void file_backend_rotate(log_backend_t *backend)
@ -263,7 +278,7 @@ static void file_backend_rotate(log_backend_t *backend)
logfile_t *f; logfile_t *f;
for (f = log->list; f != NULL; f = f->next) for (f = log->list; f != NULL; f = f->next)
logfile_rotate(f); logfile_rotate(f, log->flags);
} }
log_backend_file_t filebackend = { log_backend_file_t filebackend = {

View file

@ -22,6 +22,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <signal.h> #include <signal.h>
#include <string.h> #include <string.h>
#include <getopt.h>
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
@ -32,9 +33,41 @@
#define SYSLOG_SOCKET "/dev/log" #define SYSLOG_SOCKET "/dev/log"
#define GPL_URL "https://gnu.org/licenses/gpl.html"
static const struct option long_opts[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ "rotate-replace", no_argument, NULL, 'r' },
{ "max-size", required_argument, NULL, 'm' },
{ NULL, 0, NULL, 0 },
};
const char *short_opts = "hVrm:";
const char *version_string =
"usyslogd (pygos init) " PACKAGE_VERSION "\n"
"Copyright (C) 2018 David Oberhollenzer\n\n"
"License GPLv3+: GNU GPL version 3 or later <" GPL_URL ">.\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n";
const char *usage_string =
"Usage: usyslogd [OPTIONS..]\n\n"
"The following options are supported:\n"
" -h, --help Print this help text and exit\n"
" -V, --version Print version information and exit\n"
" -r, --rotate-replace Replace old log files when doing log rotation.\n"
" -m, --max-size <size> Automatically rotate log files bigger than this.\n";
static volatile sig_atomic_t syslog_run = 1; static volatile sig_atomic_t syslog_run = 1;
static volatile sig_atomic_t syslog_rotate = 0; static volatile sig_atomic_t syslog_rotate = 0;
static int log_flags = 0;
static size_t max_size = 0;
static void sighandler(int signo) static void sighandler(int signo)
@ -82,17 +115,58 @@ static int handle_data(int fd)
return logmgr->write(logmgr, &msg); return logmgr->write(logmgr, &msg);
} }
int main(void) static void process_options(int argc, char **argv)
{
char *end;
int i;
for (;;) {
i = getopt_long(argc, argv, short_opts, long_opts, NULL);
if (i == -1)
break;
switch (i) {
case 'r':
log_flags |= LOG_ROTATE_OVERWRITE;
break;
case 'm':
log_flags |= LOG_ROTATE_SIZE_LIMIT;
max_size = strtol(optarg, &end, 10);
if (max_size == 0 || *end != '\0') {
fputs("Numeric argument > 0 expected for -m\n",
stderr);
goto fail;
}
break;
case 'h':
fputs(usage_string, stdout);
exit(EXIT_SUCCESS);
case 'V':
fputs(version_string, stdout);
exit(EXIT_SUCCESS);
default:
goto fail;
}
}
return;
fail:
fputs("Try `usyslogd --help' for more information\n", stderr);
exit(EXIT_FAILURE);
}
int main(int argc, char **argv)
{ {
int sfd, status = EXIT_FAILURE; int sfd, status = EXIT_FAILURE;
process_options(argc, argv);
signal_setup(); signal_setup();
sfd = mksock(SYSLOG_SOCKET, SOCK_FLAG_EVERYONE | SOCK_FLAG_DGRAM); sfd = mksock(SYSLOG_SOCKET, SOCK_FLAG_EVERYONE | SOCK_FLAG_DGRAM);
if (sfd < 0) if (sfd < 0)
return EXIT_FAILURE; return EXIT_FAILURE;
if (logmgr->init(logmgr)) if (logmgr->init(logmgr, log_flags, max_size))
goto out; goto out;
while (syslog_run) { while (syslog_run) {