mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-07-27 12:37:35 +00:00
Merge pull request #2694 from brauner/2018-10-14/lxc_init_logging
lxc-init: log to /dev/console
This commit is contained in:
commit
a542f5a713
@ -344,7 +344,6 @@ init_lxc_SOURCES = cmd/lxc_init.c \
|
|||||||
compiler.h \
|
compiler.h \
|
||||||
error.h \
|
error.h \
|
||||||
initutils.c initutils.h \
|
initutils.c initutils.h \
|
||||||
log.c log.h \
|
|
||||||
parse.c parse.h \
|
parse.c parse.h \
|
||||||
raw_syscalls.c raw_syscalls.h \
|
raw_syscalls.c raw_syscalls.h \
|
||||||
string_utils.c string_utils.h
|
string_utils.c string_utils.h
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
@ -46,7 +47,6 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "initutils.h"
|
#include "initutils.h"
|
||||||
#include "log.h"
|
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
#include "raw_syscalls.h"
|
#include "raw_syscalls.h"
|
||||||
#include "string_utils.h"
|
#include "string_utils.h"
|
||||||
@ -58,8 +58,6 @@
|
|||||||
#define QUOTE(macro) #macro
|
#define QUOTE(macro) #macro
|
||||||
#define QUOTEVAL(macro) QUOTE(macro)
|
#define QUOTEVAL(macro) QUOTE(macro)
|
||||||
|
|
||||||
lxc_log_define(lxc_init, lxc);
|
|
||||||
|
|
||||||
static sig_atomic_t was_interrupted;
|
static sig_atomic_t was_interrupted;
|
||||||
|
|
||||||
static void interrupt_handler(int sig)
|
static void interrupt_handler(int sig)
|
||||||
@ -74,8 +72,6 @@ static struct option long_options[] = {
|
|||||||
{ "usage", no_argument, 0, OPT_USAGE },
|
{ "usage", no_argument, 0, OPT_USAGE },
|
||||||
{ "version", no_argument, 0, OPT_VERSION },
|
{ "version", no_argument, 0, OPT_VERSION },
|
||||||
{ "quiet", no_argument, 0, 'q' },
|
{ "quiet", no_argument, 0, 'q' },
|
||||||
{ "logfile", required_argument, 0, 'o' },
|
|
||||||
{ "logpriority", required_argument, 0, 'l' },
|
|
||||||
{ "lxcpath", required_argument, 0, 'P' },
|
{ "lxcpath", required_argument, 0, 'P' },
|
||||||
{ 0, 0, 0, 0 }
|
{ 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
@ -86,8 +82,6 @@ struct arguments {
|
|||||||
const char *shortopts;
|
const char *shortopts;
|
||||||
|
|
||||||
const char *name;
|
const char *name;
|
||||||
char *log_file;
|
|
||||||
char *log_priority;
|
|
||||||
bool quiet;
|
bool quiet;
|
||||||
const char *lxcpath;
|
const char *lxcpath;
|
||||||
|
|
||||||
@ -142,19 +136,21 @@ static void prevent_forking(void)
|
|||||||
ret = snprintf(path, sizeof(path),
|
ret = snprintf(path, sizeof(path),
|
||||||
"/sys/fs/cgroup/pids/%s/pids.max", p2);
|
"/sys/fs/cgroup/pids/%s/pids.max", p2);
|
||||||
if (ret < 0 || (size_t)ret >= sizeof(path)) {
|
if (ret < 0 || (size_t)ret >= sizeof(path)) {
|
||||||
ERROR("Failed to create string");
|
if (my_args.quiet)
|
||||||
|
fprintf(stderr, "Failed to create string\n");
|
||||||
goto on_error;
|
goto on_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = open(path, O_WRONLY);
|
fd = open(path, O_WRONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
SYSERROR("Failed to open \"%s\"", path);
|
if (my_args.quiet)
|
||||||
|
fprintf(stderr, "Failed to open \"%s\"\n", path);
|
||||||
goto on_error;
|
goto on_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = write(fd, "1", 1);
|
ret = write(fd, "1", 1);
|
||||||
if (ret != 1)
|
if (ret != 1 && !my_args.quiet)
|
||||||
SYSERROR("Failed to write to \"%s\"", path);
|
fprintf(stderr, "Failed to write to \"%s\"\n", path);
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
break;
|
break;
|
||||||
@ -173,13 +169,15 @@ static void kill_children(pid_t pid)
|
|||||||
|
|
||||||
ret = snprintf(path, sizeof(path), "/proc/%d/task/%d/children", pid, pid);
|
ret = snprintf(path, sizeof(path), "/proc/%d/task/%d/children", pid, pid);
|
||||||
if (ret < 0 || (size_t)ret >= sizeof(path)) {
|
if (ret < 0 || (size_t)ret >= sizeof(path)) {
|
||||||
ERROR("Failed to create string");
|
if (my_args.quiet)
|
||||||
|
fprintf(stderr, "Failed to create string\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
f = fopen(path, "r");
|
f = fopen(path, "r");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
SYSERROR("Failed to open %s", path);
|
if (my_args.quiet)
|
||||||
|
fprintf(stderr, "Failed to open %s\n", path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +185,8 @@ static void kill_children(pid_t pid)
|
|||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
if (fscanf(f, "%d ", &pid) != 1) {
|
if (fscanf(f, "%d ", &pid) != 1) {
|
||||||
ERROR("Failed to retrieve pid");
|
if (my_args.quiet)
|
||||||
|
fprintf(stderr, "Failed to retrieve pid\n");
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -206,51 +205,33 @@ static void remove_self(void)
|
|||||||
char path[PATH_MAX] = {0};
|
char path[PATH_MAX] = {0};
|
||||||
|
|
||||||
n = readlink("/proc/self/exe", path, sizeof(path));
|
n = readlink("/proc/self/exe", path, sizeof(path));
|
||||||
if (n < 0 || n >= PATH_MAX) {
|
if (n < 0 || n >= PATH_MAX)
|
||||||
SYSDEBUG("Failed to readlink \"/proc/self/exe\"");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
path[n] = '\0';
|
path[n] = '\0';
|
||||||
|
|
||||||
ret = umount2(path, MNT_DETACH);
|
ret = umount2(path, MNT_DETACH);
|
||||||
if (ret < 0) {
|
if (ret < 0)
|
||||||
SYSDEBUG("Failed to unmount \"%s\"", path);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
ret = unlink(path);
|
ret = unlink(path);
|
||||||
if (ret < 0) {
|
if (ret < 0)
|
||||||
SYSDEBUG("Failed to unlink \"%s\"", path);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int i, ret;
|
int i, logfd, ret;
|
||||||
pid_t pid, sid;
|
pid_t pid;
|
||||||
struct sigaction act;
|
struct sigaction act;
|
||||||
struct lxc_log log;
|
|
||||||
sigset_t mask, omask;
|
sigset_t mask, omask;
|
||||||
int have_status = 0, exit_with = 1, shutdown = 0;
|
int have_status = 0, exit_with = 1, shutdown = 0;
|
||||||
|
|
||||||
if (arguments_parse(&my_args, argc, argv))
|
if (arguments_parse(&my_args, argc, argv))
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
log.prefix = "lxc-init";
|
|
||||||
log.name = my_args.name;
|
|
||||||
log.file = my_args.log_file;
|
|
||||||
log.level = my_args.log_priority;
|
|
||||||
log.quiet = my_args.quiet;
|
|
||||||
log.lxcpath = my_args.lxcpath;
|
|
||||||
|
|
||||||
ret = lxc_log_init(&log);
|
|
||||||
if (ret < 0)
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
lxc_log_options_no_override();
|
|
||||||
|
|
||||||
if (!my_args.argc) {
|
if (!my_args.argc) {
|
||||||
ERROR("Please specify a command to execute");
|
if (my_args.quiet)
|
||||||
|
fprintf(stderr, "Please specify a command to execute\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +300,8 @@ int main(int argc, char *argv[])
|
|||||||
if (errno == EINVAL)
|
if (errno == EINVAL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
SYSERROR("Failed to change signal action");
|
if (my_args.quiet)
|
||||||
|
fprintf(stderr, "Failed to change signal action\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -340,34 +322,34 @@ int main(int argc, char *argv[])
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
sigerr = signal(i, SIG_DFL);
|
sigerr = signal(i, SIG_DFL);
|
||||||
if (sigerr == SIG_ERR) {
|
if (sigerr == SIG_ERR && !my_args.quiet)
|
||||||
SYSDEBUG("Failed to reset to default action "
|
fprintf(stderr, "Failed to reset to default action for signal \"%d\": %d\n", i, pid);
|
||||||
"for signal \"%d\": %d", i, pid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = pthread_sigmask(SIG_SETMASK, &omask, NULL);
|
ret = pthread_sigmask(SIG_SETMASK, &omask, NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
SYSERROR("Failed to set signal mask");
|
if (my_args.quiet)
|
||||||
|
fprintf(stderr, "Failed to set signal mask\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
sid = setsid();
|
(void)setsid();
|
||||||
if (sid < 0)
|
|
||||||
DEBUG("Failed to make child session leader");
|
|
||||||
|
|
||||||
if (ioctl(STDIN_FILENO, TIOCSCTTY, 0) < 0)
|
(void)ioctl(STDIN_FILENO, TIOCSCTTY, 0);
|
||||||
DEBUG("Failed to set controlling terminal");
|
|
||||||
|
|
||||||
NOTICE("Exec'ing \"%s\"", my_args.argv[0]);
|
|
||||||
|
|
||||||
ret = execvp(my_args.argv[0], my_args.argv);
|
ret = execvp(my_args.argv[0], my_args.argv);
|
||||||
SYSERROR("Failed to exec \"%s\"", my_args.argv[0]);
|
if (my_args.quiet)
|
||||||
|
fprintf(stderr, "Failed to exec \"%s\"\n", my_args.argv[0]);
|
||||||
exit(ret);
|
exit(ret);
|
||||||
}
|
}
|
||||||
|
logfd = open("/dev/console", O_WRONLY | O_NOCTTY | O_CLOEXEC);
|
||||||
|
if (logfd >= 0) {
|
||||||
|
ret = dup3(logfd, STDERR_FILENO, O_CLOEXEC);
|
||||||
|
if (ret < 0)
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
INFO("Attempting to set proc title to \"init\"");
|
(void)setproctitle("init");
|
||||||
setproctitle("init");
|
|
||||||
|
|
||||||
/* Let's process the signals now. */
|
/* Let's process the signals now. */
|
||||||
ret = sigdelset(&omask, SIGALRM);
|
ret = sigdelset(&omask, SIGALRM);
|
||||||
@ -376,7 +358,8 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
ret = pthread_sigmask(SIG_SETMASK, &omask, NULL);
|
ret = pthread_sigmask(SIG_SETMASK, &omask, NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
SYSERROR("Failed to set signal mask");
|
if (my_args.quiet)
|
||||||
|
fprintf(stderr, "Failed to set signal mask\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,8 +396,8 @@ int main(int argc, char *argv[])
|
|||||||
kill_children(mypid);
|
kill_children(mypid);
|
||||||
} else {
|
} else {
|
||||||
ret = kill(-1, SIGTERM);
|
ret = kill(-1, SIGTERM);
|
||||||
if (ret < 0)
|
if (ret < 0 && !my_args.quiet)
|
||||||
SYSDEBUG("Failed to send SIGTERM to all children");
|
fprintf(stderr, "Failed to send SIGTERM to all children\n");
|
||||||
}
|
}
|
||||||
alarm(1);
|
alarm(1);
|
||||||
}
|
}
|
||||||
@ -427,15 +410,13 @@ int main(int argc, char *argv[])
|
|||||||
kill_children(mypid);
|
kill_children(mypid);
|
||||||
} else {
|
} else {
|
||||||
ret = kill(-1, SIGKILL);
|
ret = kill(-1, SIGKILL);
|
||||||
if (ret < 0)
|
if (ret < 0 && !my_args.quiet)
|
||||||
SYSDEBUG("Failed to send SIGTERM to all children");
|
fprintf(stderr, "Failed to send SIGTERM to all children\n");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
ret = kill(pid, was_interrupted);
|
ret = kill(pid, was_interrupted);
|
||||||
if (ret < 0)
|
|
||||||
SYSDEBUG("Failed to send signal \"%d\" to %d", was_interrupted, pid);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret = EXIT_SUCCESS;
|
ret = EXIT_SUCCESS;
|
||||||
@ -449,7 +430,8 @@ int main(int argc, char *argv[])
|
|||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
SYSERROR("Failed to wait on child %d", pid);
|
if (my_args.quiet)
|
||||||
|
fprintf(stderr, "Failed to wait on child %d\n", pid);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,7 +457,7 @@ __noreturn static void print_usage_exit(const struct option longopts[])
|
|||||||
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: lxc-init [-n|--name=NAME] [-h|--help] [--usage] [--version]\n\
|
fprintf(stderr, "Usage: lxc-init [-n|--name=NAME] [-h|--help] [--usage] [--version]\n\
|
||||||
[-q|--quiet] [-o|--logfile=LOGFILE] [-l|--logpriority=LOGPRIORITY] [-P|--lxcpath=LXCPATH]\n");
|
[-q|--quiet] [-P|--lxcpath=LXCPATH]\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,8 +476,6 @@ Usage: lxc-init --name=NAME -- COMMAND\n\
|
|||||||
\n\
|
\n\
|
||||||
Options :\n\
|
Options :\n\
|
||||||
-n, --name=NAME NAME of the container\n\
|
-n, --name=NAME NAME of the container\n\
|
||||||
-o, --logfile=FILE Output log to FILE instead of stderr\n\
|
|
||||||
-l, --logpriority=LEVEL Set log priority to LEVEL\n\
|
|
||||||
-q, --quiet Don't produce any output\n\
|
-q, --quiet Don't produce any output\n\
|
||||||
-P, --lxcpath=PATH Use specified container path\n\
|
-P, --lxcpath=PATH Use specified container path\n\
|
||||||
-?, --help Give this help list\n\
|
-?, --help Give this help list\n\
|
||||||
@ -523,10 +503,8 @@ static int arguments_parse(struct arguments *args, int argc,
|
|||||||
args->name = optarg;
|
args->name = optarg;
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
args->log_file = optarg;
|
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
args->log_priority = optarg;
|
|
||||||
break;
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
args->quiet = true;
|
args->quiet = true;
|
||||||
|
@ -44,10 +44,8 @@ static int execute_start(struct lxc_handler *handler, void* data)
|
|||||||
{
|
{
|
||||||
int argc_add, j;
|
int argc_add, j;
|
||||||
char **argv;
|
char **argv;
|
||||||
int argc = 0, i = 0, logfd = -1;
|
int argc = 0, i = 0;
|
||||||
struct execute_args *my_args = data;
|
struct execute_args *my_args = data;
|
||||||
char logfile[LXC_PROC_PID_FD_LEN];
|
|
||||||
bool is_privileged = lxc_list_empty(&handler->conf->id_map);
|
|
||||||
|
|
||||||
while (my_args->argv[argc++]);
|
while (my_args->argv[argc++]);
|
||||||
|
|
||||||
@ -59,14 +57,6 @@ static int execute_start(struct lxc_handler *handler, void* data)
|
|||||||
if (!handler->conf->rootfs.path)
|
if (!handler->conf->rootfs.path)
|
||||||
argc_add += 2;
|
argc_add += 2;
|
||||||
|
|
||||||
if (is_privileged) {
|
|
||||||
if (lxc_log_has_valid_level())
|
|
||||||
argc_add += 2;
|
|
||||||
|
|
||||||
if (current_config->logfd != -1 || lxc_log_fd != -1)
|
|
||||||
argc_add += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
argv = malloc((argc + argc_add) * sizeof(*argv));
|
argv = malloc((argc + argc_add) * sizeof(*argv));
|
||||||
if (!argv) {
|
if (!argv) {
|
||||||
SYSERROR("Allocating init args failed");
|
SYSERROR("Allocating init args failed");
|
||||||
@ -81,32 +71,6 @@ static int execute_start(struct lxc_handler *handler, void* data)
|
|||||||
argv[i++] = "-n";
|
argv[i++] = "-n";
|
||||||
argv[i++] = (char *)handler->name;
|
argv[i++] = (char *)handler->name;
|
||||||
|
|
||||||
if (lxc_log_has_valid_level()) {
|
|
||||||
argv[i++] = "-l";
|
|
||||||
argv[i++] = (char *)lxc_log_priority_to_string(lxc_log_get_level());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_privileged && (current_config->logfd != -1 || lxc_log_fd != -1)) {
|
|
||||||
int ret;
|
|
||||||
int to_dup = current_config->logfd;
|
|
||||||
|
|
||||||
if (current_config->logfd == -1)
|
|
||||||
to_dup = lxc_log_fd;
|
|
||||||
|
|
||||||
logfd = dup(to_dup);
|
|
||||||
if (logfd < 0) {
|
|
||||||
SYSERROR("Failed to duplicate log file descriptor");
|
|
||||||
goto out2;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = snprintf(logfile, sizeof(logfile), "/proc/self/fd/%d", logfd);
|
|
||||||
if (ret < 0 || (size_t)ret >= sizeof(logfile))
|
|
||||||
goto out3;
|
|
||||||
|
|
||||||
argv[i++] = "-o";
|
|
||||||
argv[i++] = logfile;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (my_args->quiet)
|
if (my_args->quiet)
|
||||||
argv[i++] = "--quiet";
|
argv[i++] = "--quiet";
|
||||||
|
|
||||||
@ -128,9 +92,6 @@ static int execute_start(struct lxc_handler *handler, void* data)
|
|||||||
execvp(argv[0], argv);
|
execvp(argv[0], argv);
|
||||||
SYSERROR("Failed to exec %s", argv[0]);
|
SYSERROR("Failed to exec %s", argv[0]);
|
||||||
|
|
||||||
out3:
|
|
||||||
close(logfd);
|
|
||||||
out2:
|
|
||||||
free(argv);
|
free(argv);
|
||||||
out1:
|
out1:
|
||||||
return 1;
|
return 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user