When rebooting with systemctl, an optional argument can be passed to the reboot system call. This makes it possible the specify the argument in a service file and use it when the service triggers a restart. This is useful to distinguish between manual reboots and reboots caused by failing services. --- man/systemd.service.xml | 13 +++++++++++++ src/core/dbus-service.c | 1 + src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/service.c | 23 ++++++++++++++++++++++- src/core/service.h | 1 + 5 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/man/systemd.service.xml b/man/systemd.service.xml index 5b3afb8..a2a1b6b 100644 --- a/man/systemd.service.xml +++ b/man/systemd.service.xml @@ -1017,6 +1017,19 @@ ExecStart=/bin/echo $ONE $TWO ${TWO}</programlisting> <option>none</option>.</para></listitem> </varlistentry> + <varlistentry> + <term><varname>RebootArgument=</varname></term> + <listitem><para>Configure the optional + argument for the + <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry> + system call if + <varname>StartLimitAction=</varname> + is a reboot action. This works just + like the optional argument to + <command>systemctl reboot</command> + command.</para></listitem> + </varlistentry> + </variablelist> <para>Check diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c index 0451790..45bfecf 100644 --- a/src/core/dbus-service.c +++ b/src/core/dbus-service.c @@ -50,6 +50,7 @@ const sd_bus_vtable bus_service_vtable[] = { SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Service, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Service, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StartLimitAction", "s", property_get_start_limit_action, offsetof(Service, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Service, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool, offsetof(Service, remain_after_exit), SD_BUS_VTABLE_PROPERTY_CONST), diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 55fd3da..defd66e 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -183,6 +183,7 @@ Service.WatchdogSec, config_parse_sec, 0, Service.StartLimitInterval, config_parse_sec, 0, offsetof(Service, start_limit.interval) Service.StartLimitBurst, config_parse_unsigned, 0, offsetof(Service, start_limit.burst) Service.StartLimitAction, config_parse_start_limit_action, 0, offsetof(Service, start_limit_action) +Service.RebootArgument, config_parse_string, 0, offsetof(Service, reboot_arg) Service.Type, config_parse_service_type, 0, offsetof(Service, type) Service.Restart, config_parse_service_restart, 0, offsetof(Service, restart) Service.PermissionsStartOnly, config_parse_bool, 0, offsetof(Service, permissions_start_only) diff --git a/src/core/service.c b/src/core/service.c index 78a2e06..9026dc5 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -24,6 +24,8 @@ #include <dirent.h> #include <unistd.h> #include <sys/reboot.h> +#include <linux/reboot.h> +#include <sys/syscall.h> #include "manager.h" #include "unit.h" @@ -2369,6 +2371,18 @@ static int service_start_limit_test(Service *s) { if (ratelimit_test(&s->start_limit)) return 0; + if ((s->start_limit_action == SERVICE_START_LIMIT_REBOOT || + s->start_limit_action == SERVICE_START_LIMIT_REBOOT_FORCE) && s->reboot_arg) { + int r; + + r = write_string_file(REBOOT_PARAM_FILE, s->reboot_arg); + if (r < 0) { + log_error("Failed to write reboot param to " + REBOOT_PARAM_FILE": %s", strerror(-r)); + return r; + } + } + switch (s->start_limit_action) { case SERVICE_START_LIMIT_NONE: @@ -2404,7 +2418,14 @@ static int service_start_limit_test(Service *s) { log_warning_unit(UNIT(s)->id, "%s start request repeated too quickly, rebooting immediately.", UNIT(s)->id); sync(); - reboot(RB_AUTOBOOT); + if (s->reboot_arg) { + log_info("Rebooting with arg '%s'.", s->reboot_arg); + syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, + LINUX_REBOOT_CMD_RESTART2, s->reboot_arg); + } else { + log_info("Rebooting."); + reboot(RB_AUTOBOOT); + } break; default: diff --git a/src/core/service.h b/src/core/service.h index 1992926..fd05e9b 100644 --- a/src/core/service.h +++ b/src/core/service.h @@ -189,6 +189,7 @@ struct Service { RateLimit start_limit; StartLimitAction start_limit_action; + char *reboot_arg; UnitRef accept_socket; -- 1.9.1 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel