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:
parent
21b88d9352
commit
29e4fc5607
4 changed files with 123 additions and 12 deletions
|
@ -1,5 +1,5 @@
|
|||
description "starting usyslogd"
|
||||
exec usyslogd
|
||||
exec usyslogd --rotate-replace --max-size 8192
|
||||
type respawn limit 5
|
||||
target boot
|
||||
after vfs
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
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 = {
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@ -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 <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) {
|
||||
|
|
Loading…
Reference in a new issue