From 28dbc1e80b0db09313f11e44f218138aefd646c8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 15 Feb 2011 01:27:53 +0100 Subject: [PATCH] execute: optionally forward program output to /dev/console in addition to syslog/kmsg --- TODO | 4 ---- man/systemd.exec.xml | 14 ++++++++++---- src/execute.c | 15 +++++++++++++-- src/execute.h | 2 ++ src/logger.c | 25 ++++++++++++++++++++++--- src/unit.c | 6 +++++- 6 files changed, 52 insertions(+), 14 deletions(-) diff --git a/TODO b/TODO index 8f9f76e0..5d60bdbb 100644 --- a/TODO +++ b/TODO @@ -11,8 +11,6 @@ Features: * look up crypto partition mount points via fstab to show to the user when prompting for a password -* prohibit socket activation of sysv services - * Maybe store in unit files whether a service should be enabled by default on package installation * perhaps add "systemctl reenable" as combination of "systemctl disable" and "systemctl enable" @@ -33,8 +31,6 @@ Features: * figure out what happened to bluez patch -* introduce StandardOutput=syslog+console and StandardOutput=kmsg+console to support fsck output at boot - * Patch systemd-fsck to use -C and pass console fd to it * support remote/ssh systemctl/systemadm, and local privileged access diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 835ee815..e9576e1e 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -350,7 +350,9 @@ , , , - or + , + , + or . If set to the file descriptor of standard input is @@ -374,9 +376,13 @@ system logger. connects it with the kernel log buffer which is accessible via - dmesg1. - connects standard output to a socket - from socket activation, semantics are + dmesg1. + and work + similarly but copy the output to the + system console as + well. connects + standard output to a socket from + socket activation, semantics are similar to the respective option of StandardInput=. This setting defaults to diff --git a/src/execute.c b/src/execute.c index 10ce951c..e01cbde9 100644 --- a/src/execute.c +++ b/src/execute.c @@ -198,7 +198,10 @@ static int connect_logger_as(const ExecContext *context, ExecOutput output, cons "%i\n" "%s\n" "%i\n", - output == EXEC_OUTPUT_KMSG ? "kmsg" : "syslog", + output == EXEC_OUTPUT_KMSG ? "kmsg" : + output == EXEC_OUTPUT_KMSG_AND_CONSOLE ? "kmsg+console" : + output == EXEC_OUTPUT_SYSLOG ? "syslog" : + "syslog+console", context->syslog_priority, context->syslog_identifier ? context->syslog_identifier : ident, context->syslog_level_prefix); @@ -338,7 +341,9 @@ static int setup_output(const ExecContext *context, int socket_fd, const char *i return open_terminal_as(tty_path(context), O_WRONLY, STDOUT_FILENO); case EXEC_OUTPUT_SYSLOG: + case EXEC_OUTPUT_SYSLOG_AND_CONSOLE: case EXEC_OUTPUT_KMSG: + case EXEC_OUTPUT_KMSG_AND_CONSOLE: return connect_logger_as(context, o, ident, STDOUT_FILENO); case EXEC_OUTPUT_SOCKET: @@ -389,7 +394,9 @@ static int setup_error(const ExecContext *context, int socket_fd, const char *id return open_terminal_as(tty_path(context), O_WRONLY, STDERR_FILENO); case EXEC_OUTPUT_SYSLOG: + case EXEC_OUTPUT_SYSLOG_AND_CONSOLE: case EXEC_OUTPUT_KMSG: + case EXEC_OUTPUT_KMSG_AND_CONSOLE: return connect_logger_as(context, e, ident, STDERR_FILENO); case EXEC_OUTPUT_SOCKET: @@ -1543,7 +1550,9 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { prefix, c->tty_path); if (c->std_output == EXEC_OUTPUT_SYSLOG || c->std_output == EXEC_OUTPUT_KMSG || - c->std_error == EXEC_OUTPUT_SYSLOG || c->std_error == EXEC_OUTPUT_KMSG) + c->std_output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || c->std_output == EXEC_OUTPUT_KMSG_AND_CONSOLE || + c->std_error == EXEC_OUTPUT_SYSLOG || c->std_error == EXEC_OUTPUT_KMSG || + c->std_error == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || c->std_error == EXEC_OUTPUT_KMSG_AND_CONSOLE) fprintf(f, "%sSyslogFacility: %s\n" "%sSyslogLevel: %s\n", @@ -1820,7 +1829,9 @@ static const char* const exec_output_table[_EXEC_OUTPUT_MAX] = { [EXEC_OUTPUT_NULL] = "null", [EXEC_OUTPUT_TTY] = "tty", [EXEC_OUTPUT_SYSLOG] = "syslog", + [EXEC_OUTPUT_SYSLOG_AND_CONSOLE] = "syslog+console", [EXEC_OUTPUT_KMSG] = "kmsg", + [EXEC_OUTPUT_KMSG_AND_CONSOLE] = "kmsg+console", [EXEC_OUTPUT_SOCKET] = "socket" }; diff --git a/src/execute.h b/src/execute.h index a6766f9e..3cdd2ad2 100644 --- a/src/execute.h +++ b/src/execute.h @@ -78,7 +78,9 @@ typedef enum ExecOutput { EXEC_OUTPUT_NULL, EXEC_OUTPUT_TTY, EXEC_OUTPUT_SYSLOG, + EXEC_OUTPUT_SYSLOG_AND_CONSOLE, EXEC_OUTPUT_KMSG, + EXEC_OUTPUT_KMSG_AND_CONSOLE, EXEC_OUTPUT_SOCKET, _EXEC_OUTPUT_MAX, _EXEC_OUTPUT_INVALID = -1 diff --git a/src/logger.c b/src/logger.c index 482ec412..342c3078 100644 --- a/src/logger.c +++ b/src/logger.c @@ -84,7 +84,8 @@ struct Stream { uid_t uid; gid_t gid; - bool prefix; + bool prefix:1; + bool tee_console:1; char buffer[LINE_MAX]; size_t length; @@ -228,6 +229,20 @@ static int stream_log(Stream *s, char *p, usec_t ts) { } else assert_not_reached("Unknown log target"); + if (s->tee_console) { + int console; + + if ((console = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC)) >= 0) { + IOVEC_SET_STRING(iovec[0], s->process); + IOVEC_SET_STRING(iovec[1], header_pid); + IOVEC_SET_STRING(iovec[2], p); + IOVEC_SET_STRING(iovec[3], (char*) "\n"); + + writev(console, iovec, 4); + } + + } + return 0; } @@ -242,9 +257,9 @@ static int stream_line(Stream *s, char *p, usec_t ts) { switch (s->state) { case STREAM_TARGET: - if (streq(p, "syslog")) + if (streq(p, "syslog") || streq(p, "syslog+console")) s->target = STREAM_SYSLOG; - else if (streq(p, "kmsg")) { + else if (streq(p, "kmsg") || streq(p, "kmsg+console")) { if (s->server->kmsg_fd >= 0 && s->uid == 0) s->target = STREAM_KMSG; @@ -256,6 +271,10 @@ static int stream_line(Stream *s, char *p, usec_t ts) { log_warning("Failed to parse log target line."); return -EBADMSG; } + + if (endswith(p, "+console")) + s->tee_console = true; + s->state = STREAM_PRIORITY; return 0; diff --git a/src/unit.c b/src/unit.c index a7e6714c..0d531237 100644 --- a/src/unit.c +++ b/src/unit.c @@ -556,8 +556,12 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) { if (c->std_output != EXEC_OUTPUT_KMSG && c->std_output != EXEC_OUTPUT_SYSLOG && + c->std_output != EXEC_OUTPUT_KMSG_AND_CONSOLE && + c->std_output != EXEC_OUTPUT_SYSLOG_AND_CONSOLE && c->std_error != EXEC_OUTPUT_KMSG && - c->std_error != EXEC_OUTPUT_SYSLOG) + c->std_error != EXEC_OUTPUT_SYSLOG_AND_CONSOLE && + c->std_error != EXEC_OUTPUT_KMSG && + c->std_error != EXEC_OUTPUT_SYSLOG_AND_CONSOLE) return 0; /* If syslog or kernel logging is requested, make sure our own -- 2.39.5