]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
systemctl: Add TriggeredBy and Triggers to status
authorKevin Kuehler <keur@xcf.berkeley.edu>
Mon, 4 Nov 2019 22:48:06 +0000 (14:48 -0800)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 5 Nov 2019 20:51:31 +0000 (21:51 +0100)
For all units that aren't timers, if it is activated by another unit,
add the triggering unit under the  "TriggeredBy:" header. If a unit can
trigger other units, print the units it triggers other the "Triggers:"
header.

TODO
src/systemctl/systemctl.c

diff --git a/TODO b/TODO
index 03d38da9a0eec2d346f21b691449e8f452489b86..64068a8803a08fb17bacb55414c229aa3376d616 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1107,7 +1107,6 @@ External:
   - <command> <verb> -<TAB> should complete options, but currently does not
   - systemctl add-wants,add-requires
 
-* systemctl status foo.service should say that it is trigger by foo.timer
 * systemctl status should know about 'systemd-analyze calendar ... --iterations='
 * If timer has just OnInactiveSec=..., it should fire after a specified time
   after being started.
index 3fabbb665cc4396f8d17e6d529313fffc5d86299..c8c22b25912489e8b1f753b9a9314ab294546fa5 100644 (file)
@@ -4054,6 +4054,9 @@ typedef struct UnitStatusInfo {
 
         char **dropin_paths;
 
+        char **triggered_by;
+        char **triggers;
+
         const char *load_error;
         const char *result;
 
@@ -4138,6 +4141,8 @@ static void unit_status_info_free(UnitStatusInfo *info) {
 
         strv_free(info->documentation);
         strv_free(info->dropin_paths);
+        strv_free(info->triggered_by);
+        strv_free(info->triggers);
         strv_free(info->listen);
 
         while ((c = info->conditions)) {
@@ -4151,6 +4156,17 @@ static void unit_status_info_free(UnitStatusInfo *info) {
         }
 }
 
+static void format_active_state(const char *active_state, const char **active_on, const char **active_off) {
+        if (streq_ptr(active_state, "failed")) {
+                *active_on = ansi_highlight_red();
+                *active_off = ansi_normal();
+        } else if (STRPTR_IN_SET(active_state, "active", "reloading")) {
+                *active_on = ansi_highlight_green();
+                *active_off = ansi_normal();
+        } else
+                *active_on = *active_off = "";
+}
+
 static void print_status_info(
                 sd_bus *bus,
                 UnitStatusInfo *i,
@@ -4164,20 +4180,14 @@ static void print_status_info(
         const char *path;
         char **t, **t2;
         int r;
+        bool is_timer;
 
         assert(i);
 
         /* This shows pretty information about a unit. See
          * print_property() for a low-level property printer */
 
-        if (streq_ptr(i->active_state, "failed")) {
-                active_on = ansi_highlight_red();
-                active_off = ansi_normal();
-        } else if (STRPTR_IN_SET(i->active_state, "active", "reloading")) {
-                active_on = ansi_highlight_green();
-                active_off = ansi_normal();
-        } else
-                active_on = active_off = "";
+        format_active_state(i->active_state, &active_on, &active_off);
 
         printf("%s%s%s %s", active_on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), active_off, strna(i->id));
 
@@ -4282,7 +4292,28 @@ static void print_status_info(
         else
                 printf("\n");
 
-        if (endswith(i->id, ".timer")) {
+        is_timer = endswith(i->id, ".timer");
+
+        if (!is_timer && !strv_isempty(i->triggered_by)) {
+                char **trigger;
+                bool first = true;
+
+                printf("   TriggeredBy:");
+                STRV_FOREACH(trigger, i->triggered_by) {
+                        UnitActiveState state = _UNIT_ACTIVE_STATE_INVALID;
+
+                        (void) get_state_one_unit(bus, *trigger, &state);
+                        format_active_state(unit_active_state_to_string(state), &on, &off);
+                        if (first) {
+                                printf(" %s%s%s %s\n", on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), off, *trigger);
+                                first = false;
+                        } else {
+                                printf("                %s%s%s %s\n", on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), off, *trigger);
+                        }
+                }
+        }
+
+        if (is_timer) {
                 char tstamp1[FORMAT_TIMESTAMP_RELATIVE_MAX],
                      tstamp2[FORMAT_TIMESTAMP_MAX];
                 const char *next_rel_time, *next_time;
@@ -4303,6 +4334,25 @@ static void print_status_info(
                         printf("n/a\n");
         }
 
+        if (!strv_isempty(i->triggers)) {
+                char **trigger;
+                bool first = true;
+
+                printf(" Triggers:");
+                STRV_FOREACH(trigger, i->triggers) {
+                        UnitActiveState state = _UNIT_ACTIVE_STATE_INVALID;
+
+                        (void) get_state_one_unit(bus, *trigger, &state);
+                        format_active_state(unit_active_state_to_string(state), &on, &off);
+                        if (first) {
+                                printf(" %s%s%s %s\n", on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), off, *trigger);
+                                first = false;
+                        } else {
+                                printf("                %s%s%s %s\n", on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), off, *trigger);
+                        }
+                }
+        }
+
         if (!i->condition_result && i->condition_timestamp > 0) {
                 UnitCondition *c;
                 int n = 0;
@@ -5514,6 +5564,8 @@ static int show_one(
                 { "DropInPaths",                    "as",              NULL,           offsetof(UnitStatusInfo, dropin_paths)                      },
                 { "LoadError",                      "(ss)",            map_load_error, offsetof(UnitStatusInfo, load_error)                        },
                 { "Result",                         "s",               NULL,           offsetof(UnitStatusInfo, result)                            },
+                { "TriggeredBy",                    "as",              NULL,           offsetof(UnitStatusInfo, triggered_by)                      },
+                { "Triggers",                       "as",              NULL,           offsetof(UnitStatusInfo, triggers)                          },
                 { "InactiveExitTimestamp",          "t",               NULL,           offsetof(UnitStatusInfo, inactive_exit_timestamp)           },
                 { "InactiveExitTimestampMonotonic", "t",               NULL,           offsetof(UnitStatusInfo, inactive_exit_timestamp_monotonic) },
                 { "ActiveEnterTimestamp",           "t",               NULL,           offsetof(UnitStatusInfo, active_enter_timestamp)            },