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"
|
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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
now = time(NULL);
|
if (flags & LOG_ROTATE_OVERWRITE) {
|
||||||
gmtime_r(&now, &tm);
|
strcpy(timebuf, "1");
|
||||||
strftime(timebuf, sizeof(timebuf), "%FT%T", &tm);
|
} else {
|
||||||
|
now = time(NULL);
|
||||||
|
gmtime_r(&now, &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 = {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue