mirror of
https://github.com/systemd/systemd.git
synced 2025-03-09 12:58:26 +03:00
systemctl: add support for --wait to is-system-running
This makes it possible to wait until boot is finished without having to poll for this command repeatedly, instead using the syntax: $ systemctl is-system-running --wait Waiting is implemented by waiting for the StartupFinished signal to be posted on the bus. Register the matcher before checking for the property to avoid race conditions. Tested by artificially delaying startup with a oneshot service and calling this command, checked that it emitted `running` and exited with a 0 return code as soon as the delay service completed startup. Also tested that booting to degraded state unblocks the command. Inserted a delay between getting the property and waiting for the signal and confirmed this seems to work free of race conditions. Updated the --help text (under --wait) and the man page to document the new feature.
This commit is contained in:
parent
4027f96aa0
commit
adb6cd9be2
@ -372,6 +372,9 @@
|
||||
Note that this will wait forever if any given unit never terminates
|
||||
(by itself or by getting stopped explicitly); particularly services
|
||||
which use <literal>RemainAfterExit=yes</literal>.</para>
|
||||
|
||||
<para>When used with <command>is-system-running</command>, wait
|
||||
until the boot process is completed before returning.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@ -1636,6 +1639,15 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
||||
output, see the table below. Use <option>--quiet</option> to
|
||||
suppress this output.</para>
|
||||
|
||||
<para>Use <option>--wait</option> to wait until the boot
|
||||
process is completed before printing the current state and
|
||||
returning the appropriate error status. If <option>--wait</option>
|
||||
is in use, states <varname>initializing</varname> or
|
||||
<varname>starting</varname> will not be reported, instead
|
||||
the command will block until a later state (such as
|
||||
<varname>running</varname> or <varname>degraded</varname>)
|
||||
is reached.</para>
|
||||
|
||||
<table>
|
||||
<title><command>is-system-running</command> output</title>
|
||||
<tgroup cols='3'>
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "sd-bus.h"
|
||||
#include "sd-daemon.h"
|
||||
#include "sd-event.h"
|
||||
#include "sd-login.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
@ -6629,8 +6630,29 @@ static int unit_is_enabled(int argc, char *argv[], void *userdata) {
|
||||
return enabled ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
static int match_startup_finished(sd_bus_message *m, void *userdata, sd_bus_error *error) {
|
||||
char **state = userdata;
|
||||
int r;
|
||||
|
||||
assert(state);
|
||||
|
||||
r = sd_bus_get_property_string(
|
||||
sd_bus_message_get_bus(m),
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"SystemState",
|
||||
NULL,
|
||||
state);
|
||||
|
||||
sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_system_running(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot_startup_finished = NULL;
|
||||
_cleanup_(sd_event_unrefp) sd_event* event = NULL;
|
||||
_cleanup_free_ char *state = NULL;
|
||||
sd_bus *bus;
|
||||
int r;
|
||||
@ -6645,6 +6667,25 @@ static int is_system_running(int argc, char *argv[], void *userdata) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (arg_wait) {
|
||||
r = sd_event_default(&event);
|
||||
if (r >= 0)
|
||||
r = sd_bus_attach_event(bus, event, 0);
|
||||
if (r >= 0)
|
||||
r = sd_bus_match_signal_async(
|
||||
bus,
|
||||
&slot_startup_finished,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"StartupFinished",
|
||||
match_startup_finished, NULL, &state);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Failed to request match for StartupFinished: %m");
|
||||
arg_wait = false;
|
||||
}
|
||||
}
|
||||
|
||||
r = sd_bus_get_property_string(
|
||||
bus,
|
||||
"org.freedesktop.systemd1",
|
||||
@ -6654,13 +6695,23 @@ static int is_system_running(int argc, char *argv[], void *userdata) {
|
||||
&error,
|
||||
&state);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to query system state: %s", bus_error_message(&error, r));
|
||||
log_warning_errno(r, "Failed to query system state: %s", bus_error_message(&error, r));
|
||||
|
||||
if (!arg_quiet)
|
||||
puts("unknown");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (arg_wait && STR_IN_SET(state, "initializing", "starting")) {
|
||||
r = sd_event_loop(event);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Failed to get property from event loop: %m");
|
||||
if (!arg_quiet)
|
||||
puts("unknown");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!arg_quiet)
|
||||
puts(state);
|
||||
|
||||
@ -7082,6 +7133,7 @@ static void systemctl_help(void) {
|
||||
" --dry-run Only print what would be done\n"
|
||||
" -q --quiet Suppress output\n"
|
||||
" --wait For (re)start, wait until service stopped again\n"
|
||||
" For is-system-running, wait until startup is completed\n"
|
||||
" --no-block Do not wait until operation finished\n"
|
||||
" --no-wall Don't send wall message before halt/power-off/reboot\n"
|
||||
" --no-reload Don't reload daemon after en-/dis-abling unit files\n"
|
||||
|
Loading…
x
Reference in New Issue
Block a user