chiark / gitweb /
execute: optionally forward program output to /dev/console in addition to syslog...
authorLennart Poettering <lennart@poettering.net>
Tue, 15 Feb 2011 00:27:53 +0000 (01:27 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 15 Feb 2011 00:27:53 +0000 (01:27 +0100)
TODO
man/systemd.exec.xml
src/execute.c
src/execute.h
src/logger.c
src/unit.c

diff --git a/TODO b/TODO
index 8f9f76e04b051c4108e85559a4dc0d72e2148bf0..5d60bdbbcc658f80810748f4a0e30a33345cd253 100644 (file)
--- 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
index 835ee8153108410ccf8c3fef6d32671746122ee9..e9576e1e7268535a127ed2577329aa9e8794aeda 100644 (file)
                                 <option>null</option>,
                                 <option>tty</option>,
                                 <option>syslog</option>,
-                                <option>kmsg</option> or
+                                <option>kmsg</option>,
+                                <option>kmsg+console</option>,
+                                <option>syslog+console</option> or
                                 <option>socket</option>. If set to
                                 <option>inherit</option> the file
                                 descriptor of standard input is
                                 system logger. <option>kmsg</option>
                                 connects it with the kernel log buffer
                                 which is accessible via
-                                <citerefentry><refentrytitle>dmesg</refentrytitle><manvolnum>1</manvolnum></citerefentry>. <option>socket</option>
-                                connects standard output to a socket
-                                from socket activation, semantics are
+                                <citerefentry><refentrytitle>dmesg</refentrytitle><manvolnum>1</manvolnum></citerefentry>. <option>syslog+console</option>
+                                and <option>kmsg+console</option> work
+                                similarly but copy the output to the
+                                system console as
+                                well. <option>socket</option> connects
+                                standard output to a socket from
+                                socket activation, semantics are
                                 similar to the respective option of
                                 <varname>StandardInput=</varname>.
                                 This setting defaults to
index 10ce951c599fb02ecede8ca9718b9a14b8286956..e01cbde9747d0fdec775f28a57968b16e8ddcb15 100644 (file)
@@ -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"
 };
 
index a6766f9e995b0ed799dc9be37aefdd47636ab0f3..3cdd2ad28459242bfb39ddbb1c9bcbacf7afcf16 100644 (file)
@@ -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
index 482ec41244502298a1b12b877367a00b37a77ece..342c30789921d1245250c608f6842f5149cd8cb1 100644 (file)
@@ -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;
 
index a7e6714c4508a5855d8d1158ab780fa3de06e714..0d5312376c2b547234dafce07349b5cd526ca8d0 100644 (file)
@@ -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