mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-04 13:14:05 +00:00
commit
b336ea596b
@ -1697,6 +1697,19 @@ mknod errno 0
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>lxc.syslog</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Send logging info to syslog. It respects the log level defined in
|
||||
<command>lxc.loglevel</command>. The argument should be the syslog
|
||||
facility to use, valid ones are: daemon, local0, local1, local2,
|
||||
local3, local4, local5, local5, local7.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect2>
|
||||
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <net/if.h>
|
||||
#include <time.h>
|
||||
#include <dirent.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "parse.h"
|
||||
#include "config.h"
|
||||
@ -105,6 +106,7 @@ static int config_haltsignal(const char *, const char *, struct lxc_conf *);
|
||||
static int config_rebootsignal(const char *, const char *, struct lxc_conf *);
|
||||
static int config_stopsignal(const char *, const char *, struct lxc_conf *);
|
||||
static int config_start(const char *, const char *, struct lxc_conf *);
|
||||
static int config_syslog(const char *, const char *, struct lxc_conf *);
|
||||
static int config_monitor(const char *, const char *, struct lxc_conf *);
|
||||
static int config_group(const char *, const char *, struct lxc_conf *);
|
||||
static int config_environment(const char *, const char *, struct lxc_conf *);
|
||||
@ -184,6 +186,7 @@ static struct lxc_config_t config[] = {
|
||||
{ "lxc.init_uid", config_init_uid },
|
||||
{ "lxc.init_gid", config_init_gid },
|
||||
{ "lxc.ephemeral", config_ephemeral },
|
||||
{ "lxc.syslog", config_syslog },
|
||||
};
|
||||
|
||||
struct signame {
|
||||
@ -270,6 +273,23 @@ static const struct signame signames[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
struct syslog_facility {
|
||||
const char *name;
|
||||
int facility;
|
||||
};
|
||||
|
||||
static const struct syslog_facility syslog_facilities[] = {
|
||||
{ "daemon", LOG_DAEMON },
|
||||
{ "local0", LOG_LOCAL0 },
|
||||
{ "local1", LOG_LOCAL1 },
|
||||
{ "local2", LOG_LOCAL2 },
|
||||
{ "local3", LOG_LOCAL3 },
|
||||
{ "local4", LOG_LOCAL4 },
|
||||
{ "local5", LOG_LOCAL5 },
|
||||
{ "local6", LOG_LOCAL6 },
|
||||
{ "local7", LOG_LOCAL7 },
|
||||
};
|
||||
|
||||
static const size_t config_size = sizeof(config)/sizeof(struct lxc_config_t);
|
||||
|
||||
extern struct lxc_config_t *lxc_getconfig(const char *key)
|
||||
@ -2919,3 +2939,20 @@ static int config_ephemeral(const char *key, const char *value,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config_syslog(const char *key, const char *value,
|
||||
struct lxc_conf *lxc_conf)
|
||||
{
|
||||
int n;
|
||||
int facility = -1;
|
||||
|
||||
for (n = 0; n < sizeof(syslog_facilities) / sizeof((syslog_facilities)[0]); n++) {
|
||||
if (strcasecmp(syslog_facilities[n].name, value) == 0) {
|
||||
facility = syslog_facilities[n].facility;
|
||||
lxc_log_syslog(facility);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ERROR("Wrong value for lxc.syslog");
|
||||
return -1;
|
||||
}
|
||||
|
106
src/lxc/log.c
106
src/lxc/log.c
@ -33,6 +33,9 @@
|
||||
|
||||
#define __USE_GNU /* for *_CLOEXEC */
|
||||
|
||||
#include <syslog.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@ -43,15 +46,78 @@
|
||||
#define LXC_LOG_DATEFOMAT_SIZE 15
|
||||
|
||||
int lxc_log_fd = -1;
|
||||
static int syslog_enable = 0;
|
||||
int lxc_quiet_specified;
|
||||
int lxc_log_use_global_fd;
|
||||
static int lxc_loglevel_specified;
|
||||
|
||||
static char log_prefix[LXC_LOG_PREFIX_SIZE] = "lxc";
|
||||
static char *log_fname = NULL;
|
||||
static char *log_vmname = NULL;
|
||||
|
||||
lxc_log_define(lxc_log, lxc);
|
||||
|
||||
static int lxc_log_priority_to_syslog(int priority)
|
||||
{
|
||||
switch (priority) {
|
||||
case LXC_LOG_PRIORITY_FATAL:
|
||||
return LOG_EMERG;
|
||||
case LXC_LOG_PRIORITY_ALERT:
|
||||
return LOG_ALERT;
|
||||
case LXC_LOG_PRIORITY_CRIT:
|
||||
return LOG_CRIT;
|
||||
case LXC_LOG_PRIORITY_ERROR:
|
||||
return LOG_ERR;
|
||||
case LXC_LOG_PRIORITY_WARN:
|
||||
return LOG_WARNING;
|
||||
case LXC_LOG_PRIORITY_NOTICE:
|
||||
case LXC_LOG_PRIORITY_NOTSET:
|
||||
return LOG_NOTICE;
|
||||
case LXC_LOG_PRIORITY_INFO:
|
||||
return LOG_INFO;
|
||||
case LXC_LOG_PRIORITY_TRACE:
|
||||
case LXC_LOG_PRIORITY_DEBUG:
|
||||
return LOG_DEBUG;
|
||||
}
|
||||
|
||||
/* Not reached */
|
||||
return LOG_NOTICE;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int log_append_syslog(const struct lxc_log_appender *appender,
|
||||
struct lxc_log_event *event)
|
||||
{
|
||||
char *msg;
|
||||
int rc, len;
|
||||
va_list args;
|
||||
|
||||
if (!syslog_enable)
|
||||
return 0;
|
||||
|
||||
va_copy(args, *event->vap);
|
||||
len = vsnprintf(NULL, 0, event->fmt, args) + 1;
|
||||
va_end(args);
|
||||
msg = malloc(len * sizeof(char));
|
||||
if (msg == NULL)
|
||||
return 0;
|
||||
rc = vsnprintf(msg, len, event->fmt, *event->vap);
|
||||
if (rc == -1 || rc >= len) {
|
||||
free(msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
syslog(lxc_log_priority_to_syslog(event->priority),
|
||||
"%s %s - %s:%s:%d - %s" ,
|
||||
log_vmname ? log_vmname : "",
|
||||
event->category,
|
||||
event->locinfo->file, event->locinfo->func,
|
||||
event->locinfo->line,
|
||||
msg);
|
||||
free(msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int log_append_stderr(const struct lxc_log_appender *appender,
|
||||
struct lxc_log_event *event)
|
||||
@ -59,7 +125,7 @@ static int log_append_stderr(const struct lxc_log_appender *appender,
|
||||
if (event->priority < LXC_LOG_PRIORITY_ERROR)
|
||||
return 0;
|
||||
|
||||
fprintf(stderr, "%s: ", log_prefix);
|
||||
fprintf(stderr, "%s: %s", log_prefix, log_vmname ? log_vmname : "");
|
||||
fprintf(stderr, "%s: %s: %d ", event->locinfo->file, event->locinfo->func, event->locinfo->line);
|
||||
vfprintf(stderr, event->fmt, *event->vap);
|
||||
fprintf(stderr, "\n");
|
||||
@ -92,8 +158,10 @@ static int log_append_logfile(const struct lxc_log_appender *appender,
|
||||
strftime(date, sizeof(date), "%Y%m%d%H%M%S", t);
|
||||
ms = event->timestamp.tv_usec / 1000;
|
||||
n = snprintf(buffer, sizeof(buffer),
|
||||
"%15s %10s.%03d %-8s %s - %s:%s:%d - ",
|
||||
"%15s%s%s %10s.%03d %-8s %s - %s:%s:%d - ",
|
||||
log_prefix,
|
||||
log_vmname ? " " : "",
|
||||
log_vmname ? log_vmname : "",
|
||||
date,
|
||||
ms,
|
||||
lxc_log_priority_to_string(event->priority),
|
||||
@ -115,6 +183,12 @@ static int log_append_logfile(const struct lxc_log_appender *appender,
|
||||
return write(fd_to_use, buffer, n + 1);
|
||||
}
|
||||
|
||||
static struct lxc_log_appender log_appender_syslog = {
|
||||
.name = "syslog",
|
||||
.append = log_append_syslog,
|
||||
.next = NULL,
|
||||
};
|
||||
|
||||
static struct lxc_log_appender log_appender_stderr = {
|
||||
.name = "stderr",
|
||||
.append = log_append_stderr,
|
||||
@ -253,6 +327,9 @@ static char *build_log_path(const char *name, const char *lxcpath)
|
||||
|
||||
extern void lxc_log_close(void)
|
||||
{
|
||||
closelog();
|
||||
free(log_vmname);
|
||||
log_vmname = NULL;
|
||||
if (lxc_log_fd == -1)
|
||||
return;
|
||||
close(lxc_log_fd);
|
||||
@ -317,6 +394,28 @@ static int _lxc_log_set_file(const char *name, const char *lxcpath, int create_d
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern int lxc_log_syslog(int facility)
|
||||
{
|
||||
struct lxc_log_appender *appender;
|
||||
|
||||
openlog(log_prefix, LOG_PID, facility);
|
||||
if (!lxc_log_category_lxc.appender) {
|
||||
lxc_log_category_lxc.appender = &log_appender_syslog;
|
||||
return 0;
|
||||
}
|
||||
appender = lxc_log_category_lxc.appender;
|
||||
while (appender->next != NULL)
|
||||
appender = appender->next;
|
||||
appender->next = &log_appender_syslog;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void lxc_log_enable_syslog(void)
|
||||
{
|
||||
syslog_enable = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* lxc_log_init:
|
||||
* Called from lxc front-end programs (like lxc-create, lxc-start) to
|
||||
@ -350,6 +449,9 @@ extern int lxc_log_init(const char *name, const char *file,
|
||||
if (prefix)
|
||||
lxc_log_set_prefix(prefix);
|
||||
|
||||
if (name)
|
||||
log_vmname = strdup(name);
|
||||
|
||||
if (file) {
|
||||
if (strcmp(file, "none") == 0)
|
||||
return 0;
|
||||
|
@ -314,6 +314,8 @@ extern int lxc_log_init(const char *name, const char *file,
|
||||
const char *lxcpath);
|
||||
|
||||
extern int lxc_log_set_file(int *fd, const char *fname);
|
||||
extern int lxc_log_syslog(int facility);
|
||||
extern void lxc_log_enable_syslog(void);
|
||||
extern int lxc_log_set_level(int *dest, int level);
|
||||
extern void lxc_log_set_prefix(const char *prefix);
|
||||
extern const char *lxc_log_get_file(void);
|
||||
|
@ -255,6 +255,13 @@ restart:
|
||||
WARN("inherited fd %d", fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* only enable syslog at this point to avoid the above logging function
|
||||
* to open a new fd and make the check_inherited function enter an
|
||||
* infinite loop.
|
||||
*/
|
||||
lxc_log_enable_syslog();
|
||||
|
||||
closedir(dir); /* cannot fail */
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user