[systemd-devel] [PATCH] systemd-analyze: filter dot output with a regular expression

Łukasz Stelmach stlman at poczta.fm
Sun Mar 24 05:32:41 PDT 2013


Make "systemd-analyze dot" output only lines matching a regular
expression passed on the command line. Without the regular expression
print everything.
---

A graph created with the full output of dot is completely incomprehensible
on a regular system. It thus makes perfect sense IMHO to add filtering
to systemd-analyze instead of trying to use sed/grep/awk/perl to filter
the dependencies but preserving the first and last line with the braces.

This, of course, is the first attempt so any comments are more than
welcome.

 src/analyze/systemd-analyze.c | 35 ++++++++++++++++++++++++++++-------
 1 file changed, 28 insertions(+), 7 deletions(-)

diff --git a/src/analyze/systemd-analyze.c b/src/analyze/systemd-analyze.c
index 01bf55e..bddbeda 100644
--- a/src/analyze/systemd-analyze.c
+++ b/src/analyze/systemd-analyze.c
@@ -25,6 +25,9 @@
 #include <getopt.h>
 #include <locale.h>
 #include <sys/utsname.h>
+#include <sys/types.h>
+#include <regex.h>
+#include <string.h>
 
 #include "install.h"
 #include "log.h"
@@ -578,7 +581,7 @@ static int analyze_time(DBusConnection *bus) {
         return 0;
 }
 
-static int graph_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
+static int graph_one_property(const char *name, const char *prop, DBusMessageIter *iter, regex_t* regexp) {
 
         static const char * const colors[] = {
                 "Requires",              "[color=\"black\"]",
@@ -591,6 +594,7 @@ static int graph_one_property(const char *name, const char *prop, DBusMessageIte
                 "After",                 "[color=\"green\"]"
         };
 
+        char buf[1024];
         const char *c = NULL;
         unsigned i;
 
@@ -624,14 +628,16 @@ static int graph_one_property(const char *name, const char *prop, DBusMessageIte
 
                         assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
                         dbus_message_iter_get_basic(&sub, &s);
-                        printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
+                        snprintf(buf, sizeof(buf), "\t\"%s\"->\"%s\" %s;", name, s, c);
+                        if (regexp == NULL || regexec(regexp, buf, 0, NULL, 0) == 0)
+                                puts(buf);
                 }
         }
 
         return 0;
 }
 
-static int graph_one(DBusConnection *bus, const struct unit_info *u) {
+static int graph_one(DBusConnection *bus, const struct unit_info *u, regex_t* regexp) {
         _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
         const char *interface = "org.freedesktop.systemd1.Unit";
         int r;
@@ -675,7 +681,7 @@ static int graph_one(DBusConnection *bus, const struct unit_info *u) {
                 }
 
                 dbus_message_iter_recurse(&sub2, &sub3);
-                r = graph_one_property(u->id, prop, &sub3);
+                r = graph_one_property(u->id, prop, &sub3, regexp);
                 if (r < 0)
                         return r;
         }
@@ -683,10 +689,12 @@ static int graph_one(DBusConnection *bus, const struct unit_info *u) {
         return 0;
 }
 
-static int dot(DBusConnection *bus) {
+static int dot(DBusConnection *bus, char* regexp_s) {
         _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
         DBusMessageIter iter, sub;
         int r;
+        regex_t regexp;
+        int use_regexp = 0;
 
         r = bus_method_call_with_reply(
                         bus,
@@ -707,6 +715,16 @@ static int dot(DBusConnection *bus) {
                 return -EIO;
         }
 
+        memset(&regexp, 0, sizeof(regexp));
+        if (regexp_s != NULL) {
+                r = regcomp(&regexp, regexp_s, REG_NOSUB);
+                if (r != 0) {
+                        log_error("Invalid regular expression.");
+                        return -EINVAL;
+                }
+                use_regexp = 1;
+        }
+
         printf("digraph systemd {\n");
 
         for (dbus_message_iter_recurse(&iter, &sub);
@@ -718,13 +736,16 @@ static int dot(DBusConnection *bus) {
                 if (r < 0)
                         return -EIO;
 
-                r = graph_one(bus, &u);
+                r = graph_one(bus, &u, use_regexp ? &regexp : NULL);
                 if (r < 0)
                         return r;
         }
 
         printf("}\n");
 
+        if (use_regexp)
+                regfree(&regexp);
+
         log_info("   Color legend: black     = Requires\n"
                  "                 dark blue = Requisite\n"
                  "                 dark grey = Wants\n"
@@ -844,7 +865,7 @@ int main(int argc, char *argv[]) {
         else if (streq(argv[optind], "plot"))
                 r = analyze_plot(bus);
         else if (streq(argv[optind], "dot"))
-                r = dot(bus);
+                r = dot(bus, argv[optind+1]);
         else
                 log_error("Unknown operation '%s'.", argv[optind]);
 
-- 
1.8.1.5



More information about the systemd-devel mailing list