]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
units: add simple boot check unit
authorLennart Poettering <lennart@poettering.net>
Mon, 25 Jun 2018 14:07:33 +0000 (16:07 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 19 Oct 2018 20:34:50 +0000 (22:34 +0200)
This is might be useful in some cases, but it's primarily an example for
a boot check service that can be plugged before boot-complete.target.

It's disabled by default.

All it does is check whether the failed unit count is zero

meson.build
src/boot/boot-check-no-failures.c [new file with mode: 0644]
units/meson.build
units/systemd-boot-check-no-failures.service.in [new file with mode: 0644]

index 059a261813888b9120a9dab6f49a24ea9985089f..7960e978936ccd11e4f53d7afe383284ee7f297f 100644 (file)
@@ -1815,6 +1815,15 @@ if conf.get('ENABLE_EFI') == 1 and conf.get('HAVE_BLKID') == 1
                    install_dir : systemgeneratordir)
 endif
 
+executable('systemd-boot-check-no-failures',
+           'src/boot/boot-check-no-failures.c',
+           include_directories : includes,
+           link_with : [libshared],
+           dependencies : [libblkid],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : rootlibexecdir)
+
 exe = executable('systemd-socket-activate', 'src/activate/activate.c',
                  include_directories : includes,
                  link_with : [libshared],
diff --git a/src/boot/boot-check-no-failures.c b/src/boot/boot-check-no-failures.c
new file mode 100644 (file)
index 0000000..e788446
--- /dev/null
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "sd-bus.h"
+
+#include "alloc-util.h"
+#include "bus-error.h"
+#include "log.h"
+#include "util.h"
+
+static int help(void) {
+
+        printf("%s [COMMAND] [OPTIONS...]\n"
+               "\n"
+               "Verify system operational state.\n\n"
+               "  -h --help          Show this help\n"
+               "     --version       Print version\n",
+               program_invocation_short_name);
+
+        return 0;
+}
+
+static int parse_argv(int argc, char *argv[]) {
+        enum {
+                ARG_PATH = 0x100,
+                ARG_VERSION,
+        };
+
+        static const struct option options[] = {
+                { "help",         no_argument,       NULL, 'h'              },
+                { "version",      no_argument,       NULL, ARG_VERSION      },
+                {}
+        };
+
+        int c;
+
+        assert(argc >= 0);
+        assert(argv);
+
+        while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
+                switch (c) {
+
+                case 'h':
+                        help();
+                        return 0;
+
+                case ARG_VERSION:
+                        return version();
+
+                case '?':
+                        return -EINVAL;
+
+                default:
+                        assert_not_reached("Unknown option");
+                }
+
+        return 1;
+}
+
+int main(int argc, char *argv[]) {
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+        uint32_t n;
+        int r;
+
+        log_parse_environment();
+        log_open();
+
+        r = parse_argv(argc, argv);
+        if (r <= 0)
+                goto finish;
+
+        r = sd_bus_open_system(&bus);
+        if (r < 0) {
+                log_error_errno(r, "Failed to connect to system bus: %m");
+                goto finish;
+        }
+
+        r = sd_bus_get_property_trivial(
+                        bus,
+                        "org.freedesktop.systemd1",
+                        "/org/freedesktop/systemd1",
+                        "org.freedesktop.systemd1.Manager",
+                        "NFailedUnits",
+                        &error,
+                        'u',
+                        &n);
+        if (r < 0) {
+                log_error_errno(r, "Failed to get failed units counter: %s", bus_error_message(&error, r));
+                goto finish;
+        }
+
+        if (n > 0)
+                log_notice("Health check: %" PRIu32 " units have failed.", n);
+        else
+                log_info("Health check: no failed units.");
+
+        r = n > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+
+finish:
+        return r < 0 ? EXIT_FAILURE : r;
+}
index 26a725b57561f70d0cd1bdf42db577cea3727eec..d69508467fb34666751f3c5f8e010361536f44ac 100644 (file)
@@ -137,6 +137,7 @@ in_units = [
         ['systemd-binfmt.service',               'ENABLE_BINFMT',
          'sysinit.target.wants/'],
         ['systemd-bless-boot.service',           'ENABLE_EFI HAVE_BLKID'],
+        ['systemd-boot-check-no-failures.service', ''],
         ['systemd-coredump@.service',            'ENABLE_COREDUMP'],
         ['systemd-firstboot.service',            'ENABLE_FIRSTBOOT',
          'sysinit.target.wants/'],
diff --git a/units/systemd-boot-check-no-failures.service.in b/units/systemd-boot-check-no-failures.service.in
new file mode 100644 (file)
index 0000000..27e898b
--- /dev/null
@@ -0,0 +1,24 @@
+#  SPDX-License-Identifier: LGPL-2.1+
+#
+#  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=Check if Any System Units Failed
+Documentation=man:systemd-boot-check-no-failures.service(8)
+After=default.target graphical.target multi-user.target
+Before=boot-complete.target
+Conflicts=shutdown.target
+Before=shutdown.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=@rootlibexecdir@/systemd-boot-check-no-failures
+
+[Install]
+RequiredBy=boot-complete.target