From 29e4fc5607ace15c0be03fab6930acfadda2610a Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Thu, 16 Aug 2018 22:32:34 +0200 Subject: 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 --- services/usyslogd | 2 +- syslogd/backend.h | 24 ++++++++++++++++- syslogd/logfile.c | 31 ++++++++++++++++------ syslogd/main.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 123 insertions(+), 12 deletions(-) diff --git a/services/usyslogd b/services/usyslogd index dccce82..60520c5 100644 --- a/services/usyslogd +++ b/services/usyslogd @@ -1,5 +1,5 @@ description "starting usyslogd" -exec usyslogd +exec usyslogd --rotate-replace --max-size 8192 type respawn limit 5 target boot after vfs diff --git a/syslogd/backend.h b/syslogd/backend.h index b5e238a..5880ee3 100644 --- a/syslogd/backend.h +++ b/syslogd/backend.h @@ -20,8 +20,30 @@ #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 { - 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); diff --git a/syslogd/logfile.c b/syslogd/logfile.c index 2adc136..606db8e 100644 --- a/syslogd/logfile.c +++ b/syslogd/logfile.c @@ -83,6 +83,8 @@ typedef struct logfile_t { typedef struct { log_backend_t base; logfile_t *list; + size_t maxsize; + int flags; } log_backend_file_t; @@ -156,16 +158,20 @@ static int logfile_write(logfile_t *file, const syslog_msg_t *msg) return 0; } -static int logfile_rotate(logfile_t *f) +static int logfile_rotate(logfile_t *f, int flags) { char timebuf[32]; char *filename; struct tm tm; time_t now; - now = time(NULL); - gmtime_r(&now, &tm); - strftime(timebuf, sizeof(timebuf), "%FT%T", &tm); + if (flags & LOG_ROTATE_OVERWRITE) { + strcpy(timebuf, "1"); + } else { + now = time(NULL); + gmtime_r(&now, &tm); + strftime(timebuf, sizeof(timebuf), "%FT%T", &tm); + } filename = alloca(strlen(f->filename) + strlen(timebuf) + 2); 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 (errno != EEXIST) { @@ -198,6 +205,8 @@ static int file_backend_init(log_backend_t *log) return -1; } + log->flags = flags; + log->maxsize = sizelimit; return 0; } @@ -254,7 +263,13 @@ static int file_backend_write(log_backend_t *backend, const syslog_msg_t *msg) 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) @@ -263,7 +278,7 @@ static void file_backend_rotate(log_backend_t *backend) logfile_t *f; for (f = log->list; f != NULL; f = f->next) - logfile_rotate(f); + logfile_rotate(f, log->flags); } log_backend_file_t filebackend = { diff --git a/syslogd/main.c b/syslogd/main.c index 6b4937e..7a466d6 100644 --- a/syslogd/main.c +++ b/syslogd/main.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -32,9 +33,41 @@ #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 Automatically rotate log files bigger than this.\n"; + + static volatile sig_atomic_t syslog_run = 1; static volatile sig_atomic_t syslog_rotate = 0; +static int log_flags = 0; +static size_t max_size = 0; + static void sighandler(int signo) @@ -82,17 +115,58 @@ static int handle_data(int fd) 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; + process_options(argc, argv); + signal_setup(); sfd = mksock(SYSLOG_SOCKET, SOCK_FLAG_EVERYONE | SOCK_FLAG_DGRAM); if (sfd < 0) return EXIT_FAILURE; - if (logmgr->init(logmgr)) + if (logmgr->init(logmgr, log_flags, max_size)) goto out; while (syslog_run) { -- cgit v1.2.3