diff options
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | man/systemctl.xml | 9 | ||||
-rw-r--r-- | man/systemd-analyze.xml | 39 | ||||
-rw-r--r-- | src/analyze/systemd-analyze.c | 120 | ||||
-rw-r--r-- | src/systemctl/systemctl.c | 111 |
5 files changed, 165 insertions, 116 deletions
@@ -90,8 +90,6 @@ Features: * move systemctl set-log-level to systemd-analyze? -* move "systemctl dump" to systemd-analyze - * add a fixed dbus path for "my own unit", "my own session", ... to PID1, logind, ... * service_coldplug() appears to reinstall the wrong stop timeout watch? diff --git a/man/systemctl.xml b/man/systemctl.xml index ee13a70fef..06c8c18465 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -993,16 +993,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service all pending jobs.</para> </listitem> </varlistentry> - <varlistentry> - <term><command>dump</command></term> - <listitem> - <para>Dump server status. This will output a (usually very - long) human readable manager status dump. Its format is - subject to change without notice and should not be parsed by - applications.</para> - </listitem> - </varlistentry> <varlistentry> <term><command>list-dependencies <replaceable>NAME</replaceable></command></term> diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml index f5a9424248..905b44b6d9 100644 --- a/man/systemd-analyze.xml +++ b/man/systemd-analyze.xml @@ -82,6 +82,11 @@ <arg choice="plain">dot</arg> <arg choice="opt" rep="repeat"><replaceable>PATTERN</replaceable></arg> </cmdsynopsis> + <cmdsynopsis> + <command>systemd-analyze</command> + <arg choice="opt" rep="repeat">OPTIONS</arg> + <arg choice="plain">dump</arg> + </cmdsynopsis> </refsynopsisdiv> <refsect1> @@ -127,7 +132,7 @@ been started at what time, highlighting the time they spent on initialization.</para> - <para><command>systemd-analyze dot</command> Generate + <para><command>systemd-analyze dot</command> generates textual dependency graph description in dot format for further processing with the GraphViz <citerefentry><refentrytitle>dot</refentrytitle><manvolnum>1</manvolnum></citerefentry> @@ -143,6 +148,12 @@ any of these patterns match either the origin or destination node.</para> + <para><command>systemd-analyze dump</command> outputs + a (usually very long) human-readable serialization of + the complete server state. Its format is subject to + change without notice and should not be parsed by + applications.</para> + <para>If no command is passed, <command>systemd-analyze time</command> is implied.</para> @@ -228,6 +239,14 @@ unless specified with a different unit, e.g. "50ms".</para></listitem> </varlistentry> + + <varlistentry> + <term><option>--no-pager</option></term> + + <listitem> + <para>Do not pipe output into a pager.</para> + </listitem> + </varlistentry> </variablelist> </refsect1> @@ -257,6 +276,24 @@ $ eog targets.svg</programlisting> </refsect1> <refsect1> + <title>Environment</title> + + <variablelist class='environment-variables'> + <varlistentry> + <term><varname>$SYSTEMD_PAGER</varname></term> + + <listitem> + <para>Pager to use when <option>--no-pager</option> is not + given; overrides <varname>$PAGER</varname>. Setting this to + an empty string or the value <literal>cat</literal> is + equivalent to passing + <option>--no-pager</option>.</para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> <title>See Also</title> <para> <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>, diff --git a/src/analyze/systemd-analyze.c b/src/analyze/systemd-analyze.c index ffdcd14700..2748b3afc9 100644 --- a/src/analyze/systemd-analyze.c +++ b/src/analyze/systemd-analyze.c @@ -38,6 +38,7 @@ #include "unit-name.h" #include "special.h" #include "hashmap.h" +#include "pager.h" #define SCALE_X (0.1 / 1000.0) /* pixels per us */ #define SCALE_Y 20.0 @@ -67,8 +68,8 @@ static enum dot { } arg_dot = DEP_ALL; static char** arg_dot_from_patterns = NULL; static char** arg_dot_to_patterns = NULL; - -usec_t arg_fuzz = 0; +static usec_t arg_fuzz = 0; +static bool arg_no_pager = false; struct boot_times { usec_t firmware_time; @@ -83,6 +84,7 @@ struct boot_times { usec_t unitsload_start_time; usec_t unitsload_finish_time; }; + struct unit_times { char *name; usec_t ixt; @@ -92,6 +94,14 @@ struct unit_times { usec_t time; }; +static void pager_open_if_enabled(void) { + + if (arg_no_pager) + return; + + pager_open(false); +} + static int bus_get_uint64_property(DBusConnection *bus, const char *path, const char *interface, const char *property, uint64_t *val) { _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; DBusMessageIter iter, sub; @@ -590,7 +600,6 @@ static int analyze_plot(DBusConnection *bus) { svg_text("right", 400000, y, "Loading unit files"); y++; - svg("</g>\n\n"); svg("</svg>"); @@ -600,7 +609,6 @@ static int analyze_plot(DBusConnection *bus) { return 0; } - static int list_dependencies_print(const char *name, unsigned int level, unsigned int branches, bool last, struct unit_times *times, struct boot_times *boot) { unsigned int i; @@ -914,6 +922,8 @@ static int analyze_critical_chain(DBusConnection *bus, char *names[]) { } unit_times_hashmap = h; + pager_open_if_enabled(); + puts("The time after the unit is active or started is printed after the \"@\" character.\n" "The time the unit takes to start is printed after the \"+\" character.\n"); @@ -921,9 +931,8 @@ static int analyze_critical_chain(DBusConnection *bus, char *names[]) { char **name; STRV_FOREACH(name, names) list_dependencies(bus, *name); - } else { + } else list_dependencies(bus, SPECIAL_DEFAULT_TARGET); - } hashmap_free(h); free_unit_times(times, (unsigned) n); @@ -941,6 +950,8 @@ static int analyze_blame(DBusConnection *bus) { qsort(times, n, sizeof(struct unit_times), compare_unit_time); + pager_open_if_enabled(); + for (i = 0; i < (unsigned) n; i++) { char ts[FORMAT_TIMESPAN_MAX]; @@ -1165,8 +1176,44 @@ static int dot(DBusConnection *bus, char* patterns[]) { return 0; } -static void analyze_help(void) -{ +static int dump(DBusConnection *bus, char **args) { + _cleanup_free_ DBusMessage *reply = NULL; + DBusError error; + int r; + const char *text; + + dbus_error_init(&error); + + pager_open_if_enabled(); + + r = bus_method_call_with_reply( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "Dump", + &reply, + NULL, + DBUS_TYPE_INVALID); + if (r < 0) + return r; + + if (!dbus_message_get_args(reply, &error, + DBUS_TYPE_STRING, &text, + DBUS_TYPE_INVALID)) { + log_error("Failed to parse reply: %s", bus_error_message(&error)); + dbus_error_free(&error); + return -EIO; + } + + fputs(text, stdout); + return 0; +} + +static void analyze_help(void) { + + pager_open_if_enabled(); + printf("%s [OPTIONS...] {COMMAND} ...\n\n" "Process systemd profiling information\n\n" " -h --help Show this help\n" @@ -1181,13 +1228,15 @@ static void analyze_help(void) " --fuzz=TIMESPAN When printing the tree of the critical chain, print also\n" " services, which finished TIMESPAN earlier, than the\n" " latest in the branch. The unit of TIMESPAN is seconds\n" - " unless specified with a different unit, i.e. 50ms\n\n" + " unless specified with a different unit, i.e. 50ms\n" + " --no-pager Do not pipe output into a pager\n\n" "Commands:\n" " time Print time spent in the kernel before reaching userspace\n" " blame Print list of running units ordered by time to init\n" " critical-chain Print a tree of the time critical chain of units\n" " plot Output SVG graphic showing service initialization\n" - " dot Dump dependency graph (in dot(1) format)\n\n", + " dot Output dependency graph in dot(1) format\n" + " dump Output state serialization of service manager\n", program_invocation_short_name); /* When updating this list, including descriptions, apply @@ -1195,8 +1244,7 @@ static void analyze_help(void) * shell-completion/systemd-zsh-completion.zsh too. */ } -static int parse_argv(int argc, char *argv[]) -{ +static int parse_argv(int argc, char *argv[]) { int r; enum { @@ -1207,20 +1255,22 @@ static int parse_argv(int argc, char *argv[]) ARG_SYSTEM, ARG_DOT_FROM_PATTERN, ARG_DOT_TO_PATTERN, - ARG_FUZZ + ARG_FUZZ, + ARG_NO_PAGER }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "order", no_argument, NULL, ARG_ORDER }, - { "require", no_argument, NULL, ARG_REQUIRE }, - { "user", no_argument, NULL, ARG_USER }, - { "system", no_argument, NULL, ARG_SYSTEM }, - { "from-pattern", required_argument, NULL, ARG_DOT_FROM_PATTERN}, - { "to-pattern", required_argument, NULL, ARG_DOT_TO_PATTERN }, - { "fuzz", required_argument, NULL, ARG_FUZZ }, - { NULL, 0, NULL, 0 } + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "order", no_argument, NULL, ARG_ORDER }, + { "require", no_argument, NULL, ARG_REQUIRE }, + { "user", no_argument, NULL, ARG_USER }, + { "system", no_argument, NULL, ARG_SYSTEM }, + { "from-pattern", required_argument, NULL, ARG_DOT_FROM_PATTERN }, + { "to-pattern", required_argument, NULL, ARG_DOT_TO_PATTERN }, + { "fuzz", required_argument, NULL, ARG_FUZZ }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { NULL, 0, NULL, 0 } }; assert(argc >= 0); @@ -1271,6 +1321,10 @@ static int parse_argv(int argc, char *argv[]) return r; break; + case ARG_NO_PAGER: + arg_no_pager = true; + break; + case -1: return 1; @@ -1293,14 +1347,14 @@ int main(int argc, char *argv[]) { log_open(); r = parse_argv(argc, argv); - if (r < 0) - return EXIT_FAILURE; - else if (r <= 0) - return EXIT_SUCCESS; + if (r <= 0) + goto finish; bus = dbus_bus_get(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, NULL); - if (!bus) - return EXIT_FAILURE; + if (!bus) { + r = -EIO; + goto finish; + } if (!argv[optind] || streq(argv[optind], "time")) r = analyze_time(bus); @@ -1312,12 +1366,18 @@ int main(int argc, char *argv[]) { r = analyze_plot(bus); else if (streq(argv[optind], "dot")) r = dot(bus, argv+optind+1); + else if (streq(argv[optind], "dump")) + r = dump(bus, argv+optind+1); else log_error("Unknown operation '%s'.", argv[optind]); + dbus_connection_unref(bus); + +finish: + pager_close(); + strv_free(arg_dot_from_patterns); strv_free(arg_dot_to_patterns); - dbus_connection_unref(bus); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 9f47b2cf7c..4e33a4182f 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3797,40 +3797,6 @@ static int set_property(DBusConnection *bus, char **args) { return 0; } -static int dump(DBusConnection *bus, char **args) { - _cleanup_free_ DBusMessage *reply = NULL; - DBusError error; - int r; - const char *text; - - dbus_error_init(&error); - - pager_open_if_enabled(); - - r = bus_method_call_with_reply( - bus, - "org.freedesktop.systemd1", - "/org/freedesktop/systemd1", - "org.freedesktop.systemd1.Manager", - "Dump", - &reply, - NULL, - DBUS_TYPE_INVALID); - if (r < 0) - return r; - - if (!dbus_message_get_args(reply, &error, - DBUS_TYPE_STRING, &text, - DBUS_TYPE_INVALID)) { - log_error("Failed to parse reply: %s", bus_error_message(&error)); - dbus_error_free(&error); - return -EIO; - } - - fputs(text, stdout); - return 0; -} - static int snapshot(DBusConnection *bus, char **args) { _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; DBusError error; @@ -4787,8 +4753,6 @@ static int systemctl_help(void) { "Job Commands:\n" " list-jobs List jobs\n" " cancel [JOB...] Cancel all, one, or more jobs\n\n" - "Status Commands:\n" - " dump Dump server status\n\n" "Snapshot Commands:\n" " snapshot [NAME] Create a snapshot\n" " delete [NAME...] Remove one or more snapshots\n\n" @@ -4927,43 +4891,43 @@ static int systemctl_parse_argv(int argc, char *argv[]) { }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "type", required_argument, NULL, 't' }, - { "property", required_argument, NULL, 'p' }, - { "all", no_argument, NULL, 'a' }, - { "reverse", no_argument, NULL, ARG_REVERSE }, - { "after", no_argument, NULL, ARG_AFTER }, - { "before", no_argument, NULL, ARG_BEFORE }, - { "show-types", no_argument, NULL, ARG_SHOW_TYPES }, - { "failed", no_argument, NULL, ARG_FAILED }, - { "full", no_argument, NULL, 'l' }, - { "fail", no_argument, NULL, ARG_FAIL }, - { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, - { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, - { "ignore-inhibitors", no_argument, NULL, 'i' }, - { "user", no_argument, NULL, ARG_USER }, - { "system", no_argument, NULL, ARG_SYSTEM }, - { "global", no_argument, NULL, ARG_GLOBAL }, - { "no-block", no_argument, NULL, ARG_NO_BLOCK }, - { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, - { "no-pager", no_argument, NULL, ARG_NO_PAGER }, - { "no-wall", no_argument, NULL, ARG_NO_WALL }, - { "quiet", no_argument, NULL, 'q' }, - { "root", required_argument, NULL, ARG_ROOT }, - { "force", no_argument, NULL, ARG_FORCE }, - { "no-reload", no_argument, NULL, ARG_NO_RELOAD }, - { "kill-who", required_argument, NULL, ARG_KILL_WHO }, - { "signal", required_argument, NULL, 's' }, - { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, - { "host", required_argument, NULL, 'H' }, - { "privileged",no_argument, NULL, 'P' }, - { "runtime", no_argument, NULL, ARG_RUNTIME }, - { "lines", required_argument, NULL, 'n' }, - { "output", required_argument, NULL, 'o' }, - { "plain", no_argument, NULL, ARG_PLAIN }, - { "state", required_argument, NULL, ARG_STATE }, - { NULL, 0, NULL, 0 } + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "type", required_argument, NULL, 't' }, + { "property", required_argument, NULL, 'p' }, + { "all", no_argument, NULL, 'a' }, + { "reverse", no_argument, NULL, ARG_REVERSE }, + { "after", no_argument, NULL, ARG_AFTER }, + { "before", no_argument, NULL, ARG_BEFORE }, + { "show-types", no_argument, NULL, ARG_SHOW_TYPES }, + { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */ + { "full", no_argument, NULL, 'l' }, + { "fail", no_argument, NULL, ARG_FAIL }, + { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, + { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, + { "ignore-inhibitors", no_argument, NULL, 'i' }, + { "user", no_argument, NULL, ARG_USER }, + { "system", no_argument, NULL, ARG_SYSTEM }, + { "global", no_argument, NULL, ARG_GLOBAL }, + { "no-block", no_argument, NULL, ARG_NO_BLOCK }, + { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "no-wall", no_argument, NULL, ARG_NO_WALL }, + { "quiet", no_argument, NULL, 'q' }, + { "root", required_argument, NULL, ARG_ROOT }, + { "force", no_argument, NULL, ARG_FORCE }, + { "no-reload", no_argument, NULL, ARG_NO_RELOAD }, + { "kill-who", required_argument, NULL, ARG_KILL_WHO }, + { "signal", required_argument, NULL, 's' }, + { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, + { "host", required_argument, NULL, 'H' }, + { "privileged", no_argument, NULL, 'P' }, + { "runtime", no_argument, NULL, ARG_RUNTIME }, + { "lines", required_argument, NULL, 'n' }, + { "output", required_argument, NULL, 'o' }, + { "plain", no_argument, NULL, ARG_PLAIN }, + { "state", required_argument, NULL, ARG_STATE }, + { NULL, 0, NULL, 0 } }; int c; @@ -5829,7 +5793,6 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError { "show", MORE, 1, show }, { "status", MORE, 1, show }, { "help", MORE, 2, show }, - { "dump", EQUAL, 1, dump }, { "snapshot", LESS, 2, snapshot }, { "delete", MORE, 2, delete_snapshot }, { "daemon-reload", EQUAL, 1, daemon_reload }, |