[systemd-devel] [PATCH] allow explicit stdout/stderr configuration for SysV services

Andrey Borzenkov arvidjaar at gmail.com
Sat Feb 26 14:05:28 PST 2011


Currently it is possible to either output legacy initscripts on
console which often messes it up completely, or suppress output
alltogether which makes it hard to debug boot issues.

While DefaultStandardOutput could be used to force syslog, it will
affect *all* services, also those that set stdin to tty and rely
on inheriting it. So make it possible for SysV to explicitly control
output.

Signed-off-by: Andrey Borzenkov <arvidjaar at gmail.com>

---
 man/systemd.conf.xml |    2 +
 man/systemd.xml      |   39 +++++++++++++++++++++++++++++++++++-
 src/dbus-manager.c   |    4 +++
 src/main.c           |   52 +++++++++++++++++++++++++++++++++++++++++++++++++-
 src/manager.h        |    1 +
 src/service.c        |    5 +++-
 src/system.conf      |    2 +
 7 files changed, 101 insertions(+), 4 deletions(-)

diff --git a/man/systemd.conf.xml b/man/systemd.conf.xml
index 8faedda..2d73d6e 100644
--- a/man/systemd.conf.xml
+++ b/man/systemd.conf.xml
@@ -80,6 +80,8 @@
                                 <term><varname>CrashShell=no</varname></term>
                                 <term><varname>ShowStatus=yes</varname></term>
                                 <term><varname>SysVConsole=yes</varname></term>
+                                <term><varname>SysVStandardOutput=inherit</varname></term>
+                                <term><varname>SysVStandardError=inherit</varname></term>
                                 <term><varname>CrashChVT=1</varname></term>
                                 <term><varname>DefaultStandardOutput=null</varname></term>
                                 <term><varname>DefaultStandardError=inherit</varname></term>
diff --git a/man/systemd.xml b/man/systemd.xml
index 2c42a02..7f97d39 100644
--- a/man/systemd.xml
+++ b/man/systemd.xml
@@ -194,8 +194,8 @@
                         <varlistentry>
                                 <term><option>--sysv-console=</option></term>
 
-                                <listitem><para>Controls whether
-                                output of SysV init scripts will be
+                                <listitem><para>Forces
+                                output of SysV init scripts to be
                                 directed to the console. This switch
                                 has no effect when run as user
                                 instance. Takes a boolean argument
@@ -204,6 +204,29 @@
                                 <option>true</option>.</para></listitem>
                         </varlistentry>
                         <varlistentry>
+                                <term><option>--sysv-standard-output=</option></term>
+                                <term><option>--sysv-standard-error=</option></term>
+
+                                <listitem><para>Sets the default
+                                output resp. error output for SysV
+                                init scripts, i.e. controls
+                                the default for
+                                <option>StandardOutput=</option>
+                                resp. <option>StandardExecute=</option>
+                                (see
+                                <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+                                for details). Takes one of
+                                <option>inherit</option>,
+                                <option>null</option>,
+                                <option>tty</option>,
+                                <option>syslog</option>,
+                                <option>syslog+console</option>,
+                                <option>kmsg</option>,
+                                <option>kmsg-console</option>.  If the
+                                argument is omitted it defaults to
+                                <option>inherit</option>.</para></listitem>
+                        </varlistentry>
+                        <varlistentry>
                                 <term><option>--log-target=</option></term>
 
                                 <listitem><para>Set log
@@ -993,6 +1016,18 @@
                         </varlistentry>
 
                         <varlistentry>
+                                <term><varname>systemd.sysv_standard_output=</varname></term>
+                                <term><varname>systemd.sysv_standard_error=</varname></term>
+                                <listitem><para>Controls default
+                                standard output/error output for
+                                SysV init scripts, with the same effect as the
+                                <option>--sysv-standard-output=</option>
+                                resp. <option>--sysv-standard-error=</option>
+                                command line arguments described
+                                above.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
                                 <term><varname>systemd.log_target=</varname></term>
                                 <term><varname>systemd.log_level=</varname></term>
                                 <term><varname>systemd.log_color=</varname></term>
diff --git a/src/dbus-manager.c b/src/dbus-manager.c
index 6f98aa7..d1cdcb1 100644
--- a/src/dbus-manager.c
+++ b/src/dbus-manager.c
@@ -175,6 +175,8 @@
 #ifdef HAVE_SYSV_COMPAT
 #define BUS_MANAGER_INTERFACE_PROPERTIES_SYSV                           \
         "  <property name=\"SysVConsole\" type=\"b\" access=\"read\"/>\n" \
+        "  <property name=\"SysVStandardOutput\" type=\"s\" access=\"read\"/>\n" \
+        "  <property name=\"SysVStandardError\" type=\"s\" access=\"read\"/>\n" \
         "  <property name=\"SysVInitPath\" type=\"as\" access=\"read\"/>\n" \
         "  <property name=\"SysVRcndPath\" type=\"as\" access=\"read\"/>\n"
 #else
@@ -329,6 +331,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
                 { "org.freedesktop.systemd1.Manager", "DefaultStandardError",  bus_manager_append_exec_output, "s", &m->default_std_error  },
 #ifdef HAVE_SYSV_COMPAT
                 { "org.freedesktop.systemd1.Manager", "SysVConsole",   bus_property_append_bool,      "b",  &m->sysv_console   },
+                { "org.freedesktop.systemd1.Manager", "SysVStandardOutput", bus_manager_append_exec_output, "s", &m->sysv_std_output   },
+                { "org.freedesktop.systemd1.Manager", "SysVStandardError", bus_manager_append_exec_output, "s", &m->sysv_std_error   },
                 { "org.freedesktop.systemd1.Manager", "SysVInitPath",  bus_property_append_strv,      "as", m->lookup_paths.sysvinit_path },
                 { "org.freedesktop.systemd1.Manager", "SysVRcndPath",  bus_property_append_strv,      "as", m->lookup_paths.sysvrcnd_path },
 #endif
diff --git a/src/main.c b/src/main.c
index 96a282a..13fc069 100644
--- a/src/main.c
+++ b/src/main.c
@@ -69,6 +69,8 @@ static bool arg_confirm_spawn = false;
 static bool arg_show_status = true;
 #ifdef HAVE_SYSV_COMPAT
 static bool arg_sysv_console = true;
+static ExecOutput arg_sysv_std_output = EXEC_OUTPUT_INHERIT;
+static ExecOutput arg_sysv_std_error = EXEC_OUTPUT_INHERIT;
 #endif
 static bool arg_mount_auto = true;
 static bool arg_swap_auto = true;
@@ -322,6 +324,20 @@ static int parse_proc_cmdline_word(const char *word) {
                         log_warning("Failed to parse SysV console switch %s, Ignoring.", word + 20);
                 else
                         arg_sysv_console = r;
+        } else if (startswith(word, "systemd.sysv_std_output=")) {
+                int r;
+
+                if ((r = exec_output_from_string(word + 24)) < 0)
+                        log_warning("Failed to parse SysV standard output switch %s, Ignoring.", word + 24);
+                else
+                        arg_sysv_std_output = r;
+        } else if (startswith(word, "systemd.sysv_std_error=")) {
+                int r;
+
+                if ((r = exec_output_from_string(word + 23)) < 0)
+                        log_warning("Failed to parse SysV standard error switch %s, Ignoring.", word + 23);
+                else
+                        arg_sysv_std_error = r;
 #endif
 
         } else if (startswith(word, "systemd.")) {
@@ -500,6 +516,8 @@ static int parse_config_file(void) {
                 { "ShowStatus",            config_parse_bool,         &arg_show_status,         "Manager" },
 #ifdef HAVE_SYSV_COMPAT
                 { "SysVConsole",           config_parse_bool,         &arg_sysv_console,        "Manager" },
+                { "SysVStandardOutput",    config_parse_output,       &arg_sysv_std_output,     "Manager" },
+                { "SysVStandardError",     config_parse_output,       &arg_sysv_std_error,      "Manager" },
 #endif
                 { "CrashChVT",             config_parse_int,          &arg_crash_chvt,          "Manager" },
                 { "CPUAffinity",           config_parse_cpu_affinity, NULL,                     "Manager" },
@@ -586,7 +604,11 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_CRASH_SHELL,
                 ARG_CONFIRM_SPAWN,
                 ARG_SHOW_STATUS,
+#ifdef HAVE_SYSV_COMPAT
                 ARG_SYSV_CONSOLE,
+                ARG_SYSV_STD_OUTPUT,
+                ARG_SYSV_STD_ERROR,
+#endif
                 ARG_DESERIALIZE,
                 ARG_INTROSPECT,
                 ARG_DEFAULT_STD_OUTPUT,
@@ -610,6 +632,8 @@ static int parse_argv(int argc, char *argv[]) {
                 { "show-status",              optional_argument, NULL, ARG_SHOW_STATUS              },
 #ifdef HAVE_SYSV_COMPAT
                 { "sysv-console",             optional_argument, NULL, ARG_SYSV_CONSOLE             },
+                { "sysv-std-output",          required_argument, NULL, ARG_SYSV_STD_OUTPUT          },
+                { "sysv-std-error",           required_argument, NULL, ARG_SYSV_STD_ERROR           },
 #endif
                 { "deserialize",              required_argument, NULL, ARG_DESERIALIZE              },
                 { "introspect",               optional_argument, NULL, ARG_INTROSPECT               },
@@ -746,6 +770,22 @@ static int parse_argv(int argc, char *argv[]) {
                         } else
                                 arg_sysv_console = true;
                         break;
+                case ARG_SYSV_STD_OUTPUT:
+
+                        if ((r = exec_output_from_string(optarg)) < 0) {
+                                log_error("Failed to parse SysV standard output setting %s.", optarg);
+                                return r;
+                        } else
+                                arg_sysv_std_output = r;
+                        break;
+                case ARG_SYSV_STD_ERROR:
+
+                        if ((r = exec_output_from_string(optarg)) < 0) {
+                                log_error("Failed to parse SysV standard error setting %s.", optarg);
+                                return r;
+                        } else
+                                arg_sysv_std_error = r;
+                        break;
 #endif
 
                 case ARG_DESERIALIZE: {
@@ -836,6 +876,8 @@ static int help(void) {
                "     --show-status[=0|1]         Show status updates on the console during bootup\n"
 #ifdef HAVE_SYSV_COMPAT
                "     --sysv-console[=0|1]        Connect output of SysV scripts to console\n"
+               "     --sysv-std-output=          Set default standard output of SysV scripts\n"
+               "     --sysv-std-error=           Set default standard error of SysV scripts\n"
 #endif
                "     --log-target=TARGET         Set log target (console, syslog, kmsg, syslog-or-kmsg, null)\n"
                "     --log-level=LEVEL           Set log level (debug, info, notice, warning, err, crit, alert, emerg)\n"
@@ -1114,6 +1156,8 @@ int main(int argc, char *argv[]) {
         m->show_status = arg_show_status;
 #ifdef HAVE_SYSV_COMPAT
         m->sysv_console = arg_sysv_console;
+        m->sysv_std_output = arg_sysv_std_output;
+        m->sysv_std_error = arg_sysv_std_error;
 #endif
         m->mount_auto = arg_mount_auto;
         m->swap_auto = arg_swap_auto;
@@ -1254,7 +1298,7 @@ finish:
         label_finish();
 
         if (reexecute) {
-                const char *args[15];
+                const char *args[19];
                 unsigned i = 0;
                 char sfd[16];
 
@@ -1293,6 +1337,12 @@ finish:
                         args[i++] = "--sysv-console=1";
                 else
                         args[i++] = "--sysv-console=0";
+
+                args[i++] = "--sysv-std-output";
+                args[i++] = exec_output_to_string(arg_sysv_std_output);
+
+                args[i++] = "--sysv-std-error";
+                args[i++] = exec_output_to_string(arg_sysv_std_error);
 #endif
 
                 snprintf(sfd, sizeof(sfd), "%i", fileno(serialization));
diff --git a/src/manager.h b/src/manager.h
index 1967968..be9f3c9 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -215,6 +215,7 @@ struct Manager {
         bool confirm_spawn;
 #ifdef HAVE_SYSV_COMPAT
         bool sysv_console;
+        ExecOutput sysv_std_output, sysv_std_error;
 #endif
         bool mount_auto;
         bool swap_auto;
diff --git a/src/service.c b/src/service.c
index e928d1a..94603dc 100644
--- a/src/service.c
+++ b/src/service.c
@@ -819,7 +819,10 @@ static int service_load_sysv_path(Service *s, const char *path) {
         s->restart = SERVICE_RESTART_NO;
         s->exec_context.std_output =
                 (s->meta.manager->sysv_console || s->exec_context.std_input == EXEC_INPUT_TTY)
-                ? EXEC_OUTPUT_TTY : s->meta.manager->default_std_output;
+                ? EXEC_OUTPUT_TTY : s->meta.manager->sysv_std_output;
+        s->exec_context.std_error =
+                (s->meta.manager->sysv_console || s->exec_context.std_input == EXEC_INPUT_TTY)
+                ? EXEC_OUTPUT_TTY : s->meta.manager->sysv_std_error;
         s->exec_context.kill_mode = KILL_PROCESS_GROUP;
 
         /* We use the long description only if
diff --git a/src/system.conf b/src/system.conf
index 4e06319..22195eb 100644
--- a/src/system.conf
+++ b/src/system.conf
@@ -16,6 +16,8 @@
 #CrashShell=no
 #ShowStatus=yes
 #SysVConsole=yes
+#SysVStandardOutput=inherit
+#SysVStandardError=inherit
 #CrashChVT=1
 #CPUAffinity=1 2
 #MountAuto=yes
-- 
tg: (2588ff0..) upstream/sysv-stdout (depends on: v18)


More information about the systemd-devel mailing list