From 2ee346160c9c894e506f70f44c8d31c63dffdbdd Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Tue, 17 Oct 2023 20:47:54 +0800 Subject: [PATCH] systemctl: is-failed: check if system is degraded when no unit given Closes #3335 --- man/systemctl.xml | 13 ++++++------- src/systemctl/systemctl-is-active.c | 25 ++++++++++++++++++++++++- src/systemctl/systemctl.c | 5 +++-- test/units/testsuite-26.sh | 2 ++ 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index a673c18c0ee..419d4a82438 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -219,15 +219,14 @@ Sun 2017-02-26 20:57:49 EST 2h 3min left Sun 2017-02-26 11:56:36 EST 6h ago - is-failed PATTERN + is-failed PATTERN - Check whether any of the specified units are in a - "failed" state. Returns an exit code - 0 if at least one has failed, - non-zero otherwise. Unless is - specified, this will also print the current unit state to - standard output. + Check whether any of the specified units is in the "failed" state. If no unit is specified, + check whether there are any failed units, which corresponds to the degraded state + returned by is-system-running. Returns an exit code 0 + if at least one has failed, non-zero otherwise. Unless is specified, this + will also print the current unit or system state to standard output. diff --git a/src/systemctl/systemctl-is-active.c b/src/systemctl/systemctl-is-active.c index 023869c9ac1..596320a8c61 100644 --- a/src/systemctl/systemctl-is-active.c +++ b/src/systemctl/systemctl-is-active.c @@ -69,5 +69,28 @@ int verb_is_failed(int argc, char *argv[], void *userdata) { UNIT_FAILED, }; - return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS, states, ELEMENTSOF(states), strv_skip(argv, 1)); + int r; + + if (argc > 1) + return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS, states, ELEMENTSOF(states), strv_skip(argv, 1)); + + /* If no unit is provided, we check SystemState property of the manager, i.e. whether there're failed + * units. */ + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *state = NULL; + sd_bus *bus; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + r = bus_get_property_string(bus, bus_systemd_mgr, "SystemState", &error, &state); + if (r < 0) + return log_error_errno(r, "Failed to query system state: %s", bus_error_message(&error, r)); + + if (!arg_quiet) + puts(state); + + return streq(state, "degraded") ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 989318360cf..dcd4dcc68aa 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -162,7 +162,8 @@ static int systemctl_help(void) { " list-timers [PATTERN...] List timer units currently in memory,\n" " ordered by next elapse\n" " is-active PATTERN... Check whether units are active\n" - " is-failed PATTERN... Check whether units are failed\n" + " is-failed [PATTERN...] Check whether units are failed or\n" + " system is in degraded state\n" " status [PATTERN...|PID...] Show runtime status of one or more units\n" " show [PATTERN...|JOB...] Show properties of one or more\n" " units/jobs or the manager\n" @@ -1165,7 +1166,7 @@ static int systemctl_main(int argc, char *argv[]) { { "thaw", 2, VERB_ANY, VERB_ONLINE_ONLY, verb_clean_or_freeze }, { "is-active", 2, VERB_ANY, VERB_ONLINE_ONLY, verb_is_active }, { "check", 2, VERB_ANY, VERB_ONLINE_ONLY, verb_is_active }, /* deprecated alias of is-active */ - { "is-failed", 2, VERB_ANY, VERB_ONLINE_ONLY, verb_is_failed }, + { "is-failed", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_is_failed }, { "show", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_show }, { "cat", 2, VERB_ANY, VERB_ONLINE_ONLY, verb_cat }, { "status", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_show }, diff --git a/test/units/testsuite-26.sh b/test/units/testsuite-26.sh index cce2a393db7..1e11c420e1a 100755 --- a/test/units/testsuite-26.sh +++ b/test/units/testsuite-26.sh @@ -135,6 +135,8 @@ systemctl restart "$UNIT_NAME" systemctl stop "$UNIT_NAME" (! systemctl is-active "$UNIT_NAME") +assert_eq "$(systemctl is-system-running)" "$(systemctl is-failed)" + # enable/disable/preset test_enable_disable_preset() { (! systemctl is-enabled "$@" "$UNIT_NAME")