]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
mute-console: add simple varlink service that can disable log/status spew to kernel...
authorLennart Poettering <lennart@poettering.net>
Mon, 15 Sep 2025 16:19:22 +0000 (18:19 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 26 Sep 2025 07:42:13 +0000 (09:42 +0200)
For "wizard" style interactive tools it's very annoying if they are
interrupted by kernel log output or PID1's status output. let's add some
infra to disable this temporarily. I decided to implement this as an IPC
service so that we can make this robust: if the client request the
muting dies we can automatically unmute again.

This is hence a tiny varlink service, but it can also be started
directly from the cmdline.

13 files changed:
man/rules/meson.build
man/systemd-mute-console.xml [new file with mode: 0644]
meson.build
src/mute-console/meson.build [new file with mode: 0644]
src/mute-console/mute-console.c [new file with mode: 0644]
src/shared/meson.build
src/shared/varlink-io.systemd.MuteConsole.c [new file with mode: 0644]
src/shared/varlink-io.systemd.MuteConsole.h [new file with mode: 0644]
src/test/test-varlink-idl.c
units/meson.build
units/system-systemd\x2dmute\x2dconsole.slice [new file with mode: 0644]
units/systemd-mute-console.socket [new file with mode: 0644]
units/systemd-mute-console@.service [new file with mode: 0644]

index bb5830eaf6d3d0bed9d868a6033516e029e0dc8a..76aa77ff872ee81fc25311d575a3d7fa6483287f 100644 (file)
@@ -1050,6 +1050,10 @@ manpages = [
  ['systemd-modules-load.service', '8', ['systemd-modules-load'], 'HAVE_KMOD'],
  ['systemd-mount', '1', ['systemd-umount'], ''],
  ['systemd-mountfsd.service', '8', ['systemd-mountfsd'], 'ENABLE_MOUNTFSD'],
+ ['systemd-mute-console',
+  '1',
+  ['systemd-mute-console.socket', 'systemd-mute-console@.service'],
+  ''],
  ['systemd-network-generator.service', '8', ['systemd-network-generator'], ''],
  ['systemd-networkd-wait-online.service',
   '8',
diff --git a/man/systemd-mute-console.xml b/man/systemd-mute-console.xml
new file mode 100644 (file)
index 0000000..cfab5e9
--- /dev/null
@@ -0,0 +1,79 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+  "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
+
+<refentry id="systemd-mute-console"
+    xmlns:xi="http://www.w3.org/2001/XInclude">
+
+  <refentryinfo>
+    <title>systemd-mute-console</title>
+    <productname>systemd</productname>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>systemd-mute-console</refentrytitle>
+    <manvolnum>1</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>systemd-mute-console</refname>
+    <refname>systemd-mute-console@.service</refname>
+    <refname>systemd-mute-console.socket</refname>
+    <refpurpose>Temporarily mute kernel log output and service manager status output to the system console</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <cmdsynopsis>
+      <command>systemd-mute-console</command>
+      <arg choice="opt" rep="repeat">OPTIONS</arg>
+    </cmdsynopsis>
+
+    <para><filename>systemd-mute-console@.service</filename></para>
+    <para><filename>systemd-mute-console.socket</filename></para>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>The <command>systemd-mute-console</command> tool and service may be used to
+    temporarily mute the log output of the kernel as well as the status output of the service manager to
+    the system console. It may be used by tools running on the console to ensure their terminal output is not
+    interrupted by unrelated messages.</para>
+
+    <para>The tool can be invoked directly in which case it will mute the two outputs and then issue an
+    <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    <literal>READY=1</literal> notification once that is completed. On <constant>SIGINT</constant> or
+    <constant>SIGTERM</constant> output is unmuted again. Alternatively it can be invoked via Varlink
+    IPC.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Options</title>
+
+    <para>The following options are understood:</para>
+
+    <variablelist>
+      <varlistentry>
+        <term><option>--kernel=<replaceable>bool</replaceable></option></term>
+        <term><option>--pid1=<replaceable>bool</replaceable></option></term>
+        <listitem><para>Individually controls which output to mute. If true is specified the respective
+        output is muted, if false the output is left as is. Defaults to true.</para>
+
+        <xi:include href="version-info.xml" xpointer="v259"/></listitem>
+      </varlistentry>
+
+      <xi:include href="standard-options.xml" xpointer="help" />
+      <xi:include href="standard-options.xml" xpointer="version" />
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>See Also</title>
+    <para><simplelist type="inline">
+      <member><citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
+      <member><citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
+    </simplelist></para>
+  </refsect1>
+
+</refentry>
index 8ec025c8d6ee49dbc8fe8d478b0b0ef57c7a8b6f..3d728e88a104d531f3048abcc562127a257a6cde 100644 (file)
@@ -2383,6 +2383,7 @@ subdir('src/measure')
 subdir('src/modules-load')
 subdir('src/mount')
 subdir('src/mountfsd')
+subdir('src/mute-console')
 subdir('src/network')
 subdir('src/notify')
 subdir('src/nspawn')
diff --git a/src/mute-console/meson.build b/src/mute-console/meson.build
new file mode 100644 (file)
index 0000000..f0179da
--- /dev/null
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+executables += [
+        executable_template + {
+                'name' : 'systemd-mute-console',
+                'public' : true,
+                'sources' : files('mute-console.c'),
+        },
+]
diff --git a/src/mute-console/mute-console.c b/src/mute-console/mute-console.c
new file mode 100644 (file)
index 0000000..7f0b211
--- /dev/null
@@ -0,0 +1,419 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <getopt.h>
+#include <stdbool.h>
+
+#include "sd-bus.h"
+#include "sd-event.h"
+#include "sd-varlink.h"
+
+#include "alloc-util.h"
+#include "ansi-color.h"
+#include "build.h"
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "bus-util.h"
+#include "daemon-util.h"
+#include "errno-util.h"
+#include "log.h"
+#include "main-func.h"
+#include "parse-argument.h"
+#include "pretty-print.h"
+#include "printk-util.h"
+#include "varlink-io.systemd.MuteConsole.h"
+#include "varlink-util.h"
+#include "virt.h"
+
+static bool arg_mute_pid1 = true;
+static bool arg_mute_kernel = true;
+static bool arg_varlink = false;
+
+static int help(void) {
+        _cleanup_free_ char *link = NULL;
+        int r;
+
+        r = terminal_urlify_man("systemd-mute-console", "1", &link);
+        if (r < 0)
+                return log_oom();
+
+        printf("%s [OPTIONS...]\n"
+               "\n%sMute status output to the console.%s\n\n"
+               "  -h --help            Show this help\n"
+               "     --version         Show package version\n"
+               "     --kernel=BOOL     Mute kernel log output\n"
+               "     --pid1=BOOL       Mute PID 1 status output\n"
+               "\nSee the %s for details.\n",
+               program_invocation_short_name,
+               ansi_highlight(),
+               ansi_normal(),
+               link);
+
+        return 0;
+}
+
+static int parse_argv(int argc, char *argv[]) {
+
+        enum {
+                ARG_VERSION = 0x100,
+                ARG_KERNEL,
+                ARG_PID1,
+        };
+
+        static const struct option options[] = {
+                { "help",    no_argument,       NULL, 'h'           },
+                { "version", no_argument,       NULL, ARG_VERSION   },
+                { "kernel",  required_argument, NULL, ARG_KERNEL    },
+                { "pid1",    required_argument, NULL, ARG_PID1      },
+                {}
+        };
+
+        int c, r;
+
+        assert(argc >= 0);
+        assert(argv);
+
+        while ((c = getopt_long(argc, argv, "hq", options, NULL)) >= 0) {
+
+                switch (c) {
+
+                case 'h':
+                        return help();
+
+                case ARG_VERSION:
+                        return version();
+
+                case ARG_PID1:
+                        r = parse_boolean_argument("--pid1=", optarg, &arg_mute_pid1);
+                        if (r < 0)
+                                return r;
+
+                        break;
+
+                case ARG_KERNEL:
+                        r = parse_boolean_argument("--kernel=", optarg, &arg_mute_kernel);
+                        if (r < 0)
+                                return r;
+
+                        break;
+
+                case '?':
+                        return -EINVAL;
+
+                default:
+                        assert_not_reached();
+                }
+        }
+
+        r = sd_varlink_invocation(SD_VARLINK_ALLOW_ACCEPT);
+        if (r < 0)
+                return log_error_errno(r, "Failed to check if invoked in Varlink mode: %m");
+        if (r > 0)
+                arg_varlink = true;
+
+        return 1;
+}
+
+static int set_show_status(const char *value) {
+        int r;
+        assert(value);
+
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+        r = bus_connect_system_systemd(&bus);
+        if (r < 0)
+                return log_error_errno(r, "Failed to connect to systemd: %m");
+
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        r = bus_call_method(bus, bus_systemd_mgr, "SetShowStatus", &error, /* ret_reply= */ NULL, "s", value);
+        if (r < 0)
+                return log_error_errno(r, "Failed to issue SetShowStatus() method call: %s", bus_error_message(&error, r));
+
+        return 0;
+}
+
+typedef struct Context {
+        bool mute_pid1;
+        bool mute_kernel;
+
+        bool muted_pid1;
+        int saved_kernel;
+
+        sd_varlink *link;
+} Context;
+
+static int mute_pid1(Context *c) {
+        int r;
+
+        assert(c);
+
+        if (!c->mute_pid1) {
+                log_debug("Muting of PID 1 status console output disabled.");
+                c->muted_pid1 = false;
+                return 0;
+        }
+
+        r = set_show_status("no");
+        if (r < 0)
+                return r;
+
+        log_debug("Successfully muted PID 1 status console output.");
+
+        c->muted_pid1 = true;
+        return 0;
+}
+
+static int unmute_pid1(Context *c) {
+        int r;
+
+        assert(c);
+
+        if (!c->muted_pid1) {
+                log_debug("Not restoring PID 1 status console output level.");
+                return 0;
+        }
+
+        r = set_show_status("");
+        if (r < 0)
+                return r;
+
+        log_debug("Successfully unmuted PID 1 status console output.");
+        c->muted_pid1 = false;
+        return 0;
+}
+
+static int mute_kernel(Context *c) {
+        int r;
+
+        assert(c);
+
+        if (!arg_mute_kernel) {
+                log_debug("Muting of kernel printk() console output disabled.");
+                c->saved_kernel = -1;
+                return 0;
+        }
+
+        if (detect_container() > 0) {
+                log_debug("Skipping muting of print() console output, because running in a container.");
+                c->saved_kernel = -1;
+                return 0;
+        }
+
+        int level = sysctl_printk_read();
+        if (level < 0)
+                return log_error_errno(level, "Failed to read kernel printk() console output level: %m");
+
+        if (level == 0) {
+                log_info("Not muting kernel printk() console output, since it is already disabled.");
+                c->saved_kernel = -1; /* don't bother with restoring */
+        } else {
+                r = sysctl_printk_write(0);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to change kernel printk() console output level: %m");
+
+                log_debug("Successfully muted kernel printk() console output.");
+                c->saved_kernel = level;
+        }
+
+        return 0;
+}
+
+static int unmute_kernel(Context *c) {
+        int r;
+
+        assert(c);
+
+        if (c->saved_kernel < 0) {
+                log_debug("Not restoring kernel printk() console output level.");
+                return 0;
+        }
+
+        int level = sysctl_printk_read();
+        if (level < 0)
+                return log_error_errno(level, "Failed to read kernel printk() console output level: %m");
+
+        if (level != 0) {
+                log_info("Not unmuting kernel printk() console output, since it has been changed externally in the meantime.");
+                return 0;
+        }
+
+        r = sysctl_printk_write(c->saved_kernel);
+        if (r < 0)
+                return log_error_errno(r, "Failed to unmute kernel printk() console output level: %m");
+
+        log_debug("Successfully unmuted kernel printk() console output.");
+        c->saved_kernel = -1;
+        return 0;
+}
+
+static void context_done(Context *c) {
+        assert(c);
+
+        (void) unmute_pid1(c);
+        (void) unmute_kernel(c);
+
+        if (c->link) {
+                (void) sd_varlink_set_userdata(c->link, NULL);
+                c->link = sd_varlink_flush_close_unref(c->link);
+        }
+}
+
+static Context* context_free(Context *c) {
+        if (!c)
+                return NULL;
+
+        context_done(c);
+        return mfree(c);
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(Context*, context_free);
+
+static void vl_on_disconnect(sd_varlink_server *server, sd_varlink *link, void *userdata) {
+        assert(link);
+
+        Context *c = sd_varlink_get_userdata(link);
+        if (!c)
+                return;
+
+        context_free(c);
+}
+
+static int vl_method_mute(
+                sd_varlink *link,
+                sd_json_variant *parameters,
+                sd_varlink_method_flags_t flags,
+                void *userdata) {
+
+        int r;
+
+        assert(link);
+
+        _cleanup_(context_freep) Context *nc = new(Context, 1);
+        if (!nc)
+                return -ENOMEM;
+
+        *nc = (Context) {
+                .mute_pid1 = true,
+                .mute_kernel = true,
+                .saved_kernel = -1,
+        };
+
+        static const sd_json_dispatch_field dispatch_table[] = {
+                { "kernel", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(Context, mute_kernel), 0 },
+                { "pid1",   SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(Context, mute_pid1),   0 },
+                {}
+        };
+
+        r = sd_varlink_dispatch(link, parameters, dispatch_table, nc);
+        if (r != 0)
+                return r;
+
+        if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
+                return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
+
+        r = sd_varlink_server_bind_disconnect(sd_varlink_get_server(link), vl_on_disconnect);
+        if (r < 0)
+                return r;
+
+        (void) sd_varlink_set_userdata(link, nc);
+        nc->link = sd_varlink_ref(link);
+        Context *c = TAKE_PTR(nc); /* the Context object is now managed by the disconnect handler, not us anymore */
+
+        r = 0;
+        RET_GATHER(r, mute_pid1(c));
+        RET_GATHER(r, mute_kernel(c));
+        if (r < 0)
+                return r;
+
+        /* Let client know we are muted now. We use sd_varlink_notify() here (rather than sd_varlink_reply())
+         * because we want to keep the method call open, as we want that the lifetime of the
+         * connection/method call to determine how long we keep the console muted. */
+        r = sd_varlink_notify(link, /* parameters= */ NULL);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
+static int vl_server(void) {
+        _cleanup_(sd_varlink_server_unrefp) sd_varlink_server *varlink_server = NULL;
+        int r;
+
+        /* Invocation as Varlink service */
+
+        r = varlink_server_new(
+                        &varlink_server,
+                        SD_VARLINK_SERVER_ROOT_ONLY|
+                        SD_VARLINK_SERVER_HANDLE_SIGINT|
+                        SD_VARLINK_SERVER_HANDLE_SIGTERM,
+                        /* userdata= */ NULL);
+        if (r < 0)
+                return log_error_errno(r, "Failed to allocate Varlink server: %m");
+
+        r = sd_varlink_server_add_interface(varlink_server, &vl_interface_io_systemd_MuteConsole);
+        if (r < 0)
+                return log_error_errno(r, "Failed to add Varlink interface: %m");
+
+        r = sd_varlink_server_bind_method_many(
+                        varlink_server,
+                        "io.systemd.MuteConsole.Mute", vl_method_mute);
+        if (r < 0)
+                return log_error_errno(r, "Failed to bind Varlink methods: %m");
+
+        r = sd_varlink_server_loop_auto(varlink_server);
+        if (r < 0)
+                return log_error_errno(r, "Failed to run Varlink event loop: %m");
+
+        return 0;
+}
+
+static int run(int argc, char* argv[]) {
+        int r;
+
+        log_setup();
+
+        r = parse_argv(argc, argv);
+        if (r <= 0)
+                return r;
+
+        if (arg_varlink)
+                return vl_server();
+
+        if (!arg_mute_pid1 && !arg_mute_kernel)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Not asked to mute anything, refusing.");
+
+        _cleanup_(context_done) Context c = {
+                .mute_pid1 = arg_mute_pid1,
+                .mute_kernel = arg_mute_kernel,
+                .saved_kernel = -1,
+        };
+
+        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
+        r = sd_event_new(&event);
+        if (r < 0)
+                return log_error_errno(r, "Failed to get default event source: %m");
+
+        (void) sd_event_set_watchdog(event, true);
+        (void) sd_event_set_signal_exit(event, true);
+
+        int ret = 0;
+        RET_GATHER(ret, mute_pid1(&c));
+        RET_GATHER(ret, mute_kernel(&c));
+
+        /* Now tell service manager we area ready to go */
+        _unused_ _cleanup_(notify_on_cleanup) const char *notify_message =
+                notify_start("READY=1\n"
+                             "STATUS=Console status output muted temporarily.",
+                             "STOPPING=1\n"
+                             "STATUS=Console status output unmuted.");
+
+        /* Now wait for SIGINT/SIGTERM */
+        r = sd_event_loop(event);
+        if (r < 0)
+                RET_GATHER(ret, log_error_errno(r, "Failed to run event loop: %m"));
+
+        RET_GATHER(ret, unmute_pid1(&c));
+        RET_GATHER(ret, unmute_kernel(&c));
+
+        return ret;
+}
+
+DEFINE_MAIN_FUNCTION(run);
index 71735aaaa243819f4443415e75b4cdb32ceee3d6..10fc6742a2ea5dd4b69bfef3b90e1dca6020726b 100644 (file)
@@ -202,6 +202,7 @@ shared_sources = files(
         'varlink-io.systemd.ManagedOOM.c',
         'varlink-io.systemd.Manager.c',
         'varlink-io.systemd.MountFileSystem.c',
+        'varlink-io.systemd.MuteConsole.c',
         'varlink-io.systemd.NamespaceResource.c',
         'varlink-io.systemd.Network.c',
         'varlink-io.systemd.PCRExtend.c',
diff --git a/src/shared/varlink-io.systemd.MuteConsole.c b/src/shared/varlink-io.systemd.MuteConsole.c
new file mode 100644 (file)
index 0000000..0cea5b8
--- /dev/null
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "sd-varlink-idl.h"
+
+#include "varlink-io.systemd.MuteConsole.h"
+
+static SD_VARLINK_DEFINE_METHOD(
+                Mute,
+                SD_VARLINK_FIELD_COMMENT("Whether to mute the kernel's output to the console (defaults to true)."),
+                SD_VARLINK_DEFINE_INPUT(kernel, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("Whether to mute PID1's output to the console (defaults to true)."),
+                SD_VARLINK_DEFINE_INPUT(pid1, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE));
+
+SD_VARLINK_DEFINE_INTERFACE(
+                io_systemd_MuteConsole,
+                "io.systemd.MuteConsole",
+                SD_VARLINK_INTERFACE_COMMENT("API for temporarily muting noisy output to the main kernel console"),
+                SD_VARLINK_SYMBOL_COMMENT("Mute kernel and PID 1 output to the main kernel console"),
+                &vl_method_Mute);
diff --git a/src/shared/varlink-io.systemd.MuteConsole.h b/src/shared/varlink-io.systemd.MuteConsole.h
new file mode 100644 (file)
index 0000000..9957ed1
--- /dev/null
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "sd-varlink-idl.h"
+
+extern const sd_varlink_interface vl_interface_io_systemd_MuteConsole;
index 6b3449f7772d36f6c35ff552b97738c2ce36631c..1d328bd3e28bca2b597ffdffd0cfe0563d12cae7 100644 (file)
@@ -24,6 +24,7 @@
 #include "varlink-io.systemd.Manager.h"
 #include "varlink-io.systemd.ManagedOOM.h"
 #include "varlink-io.systemd.MountFileSystem.h"
+#include "varlink-io.systemd.MuteConsole.h"
 #include "varlink-io.systemd.NamespaceResource.h"
 #include "varlink-io.systemd.Network.h"
 #include "varlink-io.systemd.PCRExtend.h"
@@ -166,6 +167,8 @@ TEST(parse_format) {
         print_separator();
         test_parse_format_one(&vl_interface_io_systemd_UserDatabase);
         print_separator();
+        test_parse_format_one(&vl_interface_io_systemd_MuteConsole);
+        print_separator();
         test_parse_format_one(&vl_interface_io_systemd_NamespaceResource);
         print_separator();
         test_parse_format_one(&vl_interface_io_systemd_Journal);
index c5b99e4e04c35092acfdd79effe5c36db3fa3a8e..ba2dfcab065f71d35ada92807ccd227e8cd5c12d 100644 (file)
@@ -143,6 +143,12 @@ units = [
         },
         { 'file' : 'modprobe@.service' },
         { 'file' : 'multi-user.target' },
+        {
+          'file' : 'systemd-mute-console.socket',
+          'symlinks' : ['sockets.target.wants/']
+        },
+        { 'file' : 'systemd-mute-console@.service' },
+        { 'file' : 'system-systemd\\x2dmute\\x2dconsole.slice' },
         { 'file' : 'network-online.target' },
         { 'file' : 'network-pre.target' },
         { 'file' : 'network.target' },
diff --git a/units/system-systemd\x2dmute\x2dconsole.slice b/units/system-systemd\x2dmute\x2dconsole.slice
new file mode 100644 (file)
index 0000000..7819eb9
--- /dev/null
@@ -0,0 +1,19 @@
+#  SPDX-License-Identifier: LGPL-2.1-or-later
+#
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=Console Output Muting Service Slice
+Documentation=man:systemd-mute-console(8)
+DefaultDependencies=no
+Conflicts=shutdown.target
+Before=shutdown.target
+
+[Slice]
+# Serialize requests to mute the console.
+ConcurrencySoftMax=1
diff --git a/units/systemd-mute-console.socket b/units/systemd-mute-console.socket
new file mode 100644 (file)
index 0000000..6223dc0
--- /dev/null
@@ -0,0 +1,22 @@
+#  SPDX-License-Identifier: LGPL-2.1-or-later
+#
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=Console Output Muting Service Socket
+Documentation=man:systemd-mute-console(8)
+DefaultDependencies=no
+Before=sockets.target
+Conflicts=shutdown.target
+Before=shutdown.target
+
+[Socket]
+ListenStream=/run/systemd/io.systemd.MuteConsole
+FileDescriptorName=varlink
+SocketMode=0600
+Accept=yes
diff --git a/units/systemd-mute-console@.service b/units/systemd-mute-console@.service
new file mode 100644 (file)
index 0000000..d43766c
--- /dev/null
@@ -0,0 +1,18 @@
+#  SPDX-License-Identifier: LGPL-2.1-or-later
+#
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=Console Output Muting Service
+Documentation=man:systemd-mute-console(8)
+DefaultDependencies=no
+Conflicts=shutdown.target
+Before=shutdown.target
+
+[Service]
+ExecStart=systemd-mute-console