diff options
author | Lennart Poettering <lennart@poettering.net> | 2017-02-02 11:45:51 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-02 11:45:51 +0100 |
commit | b415174d8e0be2f156d4ec22f3c095feae2a5362 (patch) | |
tree | 873b038789bc62b5465057e96599d905538dfaa0 /src | |
parent | f7dda6c625c7b12a1d4635a679e442250a0f69f0 (diff) | |
parent | 256c1eba6b9eb31e2e9aa5cf82ed38eb441a6a51 (diff) |
Merge pull request #5202 from keszybz/cgls-units
systemd-cgls --unit --user-unit
Diffstat (limited to 'src')
-rw-r--r-- | src/cgls/cgls.c | 160 | ||||
-rw-r--r-- | src/cgtop/cgtop.c | 67 | ||||
-rw-r--r-- | src/login/loginctl.c | 25 | ||||
-rw-r--r-- | src/machine/machinectl.c | 24 | ||||
-rw-r--r-- | src/shared/cgroup-show.c | 84 | ||||
-rw-r--r-- | src/shared/cgroup-show.h | 11 |
6 files changed, 201 insertions, 170 deletions
diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index b55aa86a40..82b4d9ccb3 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -26,7 +26,6 @@ #include "sd-bus.h" #include "alloc-util.h" -#include "bus-error.h" #include "bus-util.h" #include "cgroup-show.h" #include "cgroup-util.h" @@ -35,12 +34,21 @@ #include "output-mode.h" #include "pager.h" #include "path-util.h" +#include "strv.h" #include "unit-name.h" #include "util.h" static bool arg_no_pager = false; static bool arg_kernel_threads = false; static bool arg_all = false; + +static enum { + SHOW_UNIT_NONE, + SHOW_UNIT_SYSTEM, + SHOW_UNIT_USER, +} arg_show_unit = SHOW_UNIT_NONE; +static char **arg_names = NULL; + static int arg_full = -1; static char* arg_machine = NULL; @@ -51,6 +59,8 @@ static void help(void) { " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" " -a --all Show all groups, including empty\n" + " -u --unit Show the subtrees of specifified system units\n" + " --user-unit Show the subtrees of specifified user units\n" " -l --full Do not ellipsize output\n" " -k Include kernel threads in output\n" " -M --machine= Show container\n" @@ -62,15 +72,18 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_NO_PAGER = 0x100, ARG_VERSION, + ARG_USER_UNIT, }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "no-pager", no_argument, NULL, ARG_NO_PAGER }, - { "all", no_argument, NULL, 'a' }, - { "full", no_argument, NULL, 'l' }, - { "machine", required_argument, NULL, 'M' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "all", no_argument, NULL, 'a' }, + { "full", no_argument, NULL, 'l' }, + { "machine", required_argument, NULL, 'M' }, + { "unit", optional_argument, NULL, 'u' }, + { "user-unit", optional_argument, NULL, ARG_USER_UNIT }, {} }; @@ -79,7 +92,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 1); assert(argv); - while ((c = getopt_long(argc, argv, "hkalM:", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "-hkalM:u::", options, NULL)) >= 0) switch (c) { @@ -98,6 +111,24 @@ static int parse_argv(int argc, char *argv[]) { arg_all = true; break; + case 'u': + arg_show_unit = SHOW_UNIT_SYSTEM; + if (strv_push(&arg_names, optarg) < 0) /* push optarg if not empty */ + return log_oom(); + break; + + case ARG_USER_UNIT: + arg_show_unit = SHOW_UNIT_USER; + if (strv_push(&arg_names, optarg) < 0) /* push optarg if not empty */ + return log_oom(); + break; + + case 1: + /* positional argument */ + if (strv_push(&arg_names, optarg) < 0) + return log_oom(); + break; + case 'l': arg_full = true; break; @@ -117,51 +148,12 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached("Unhandled option"); } - return 1; -} - -static int get_cgroup_root(char **ret) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - _cleanup_free_ char *unit = NULL, *path = NULL; - const char *m; - int r; - - if (!arg_machine) { - r = cg_get_root_path(ret); - if (r == -ENOMEDIUM) - return log_error_errno(r, "Failed to get root control group path: No cgroup filesystem mounted on /sys/fs/cgroup"); - else if (r < 0) - return log_error_errno(r, "Failed to get root control group path: %m"); - - return 0; + if (arg_machine && arg_show_unit != SHOW_UNIT_NONE) { + log_error("Cannot combine --unit or --user-unit with --machine."); + return -EINVAL; } - m = strjoina("/run/systemd/machines/", arg_machine); - r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL); - if (r < 0) - return log_error_errno(r, "Failed to load machine data: %m"); - - path = unit_dbus_path_from_name(unit); - if (!path) - return log_oom(); - - r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus); - if (r < 0) - return log_error_errno(r, "Failed to create bus connection: %m"); - - r = sd_bus_get_property_string( - bus, - "org.freedesktop.systemd1", - path, - unit_dbus_interface_from_name(unit), - "ControlGroup", - &error, - ret); - if (r < 0) - return log_error_errno(r, "Failed to query unit control group path: %s", bus_error_message(&error, r)); - - return 0; + return 1; } static void show_cg_info(const char *controller, const char *path) { @@ -194,31 +186,65 @@ int main(int argc, char *argv[]) { (arg_full > 0) * OUTPUT_FULL_WIDTH | arg_kernel_threads * OUTPUT_KERNEL_THREADS; - if (optind < argc) { + if (arg_names) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_free_ char *root = NULL; - int i; + char **name; - r = get_cgroup_root(&root); - if (r < 0) - goto finish; - - for (i = optind; i < argc; i++) { + STRV_FOREACH(name, arg_names) { int q; - if (path_startswith(argv[i], "/sys/fs/cgroup")) { + if (arg_show_unit != SHOW_UNIT_NONE) { + /* Command line arguments are unit names */ + _cleanup_free_ char *cgroup = NULL; + + if (!bus) { + /* Connect to the bus only if necessary */ + r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, + arg_show_unit == SHOW_UNIT_USER, + &bus); + if (r < 0) { + log_error_errno(r, "Failed to create bus connection: %m"); + goto finish; + } + } + + q = show_cgroup_get_unit_path_and_warn(bus, *name, &cgroup); + if (q < 0) + goto failed; + + if (isempty(cgroup)) { + log_warning("Unit %s not found.", *name); + q = -ENOENT; + goto failed; + } + + printf("Unit %s (%s):\n", *name, cgroup); + fflush(stdout); + + q = show_cgroup_by_path(cgroup, NULL, 0, output_flags); - printf("Directory %s:\n", argv[i]); + } else if (path_startswith(*name, "/sys/fs/cgroup")) { + + printf("Directory %s:\n", *name); fflush(stdout); - q = show_cgroup_by_path(argv[i], NULL, 0, output_flags); + q = show_cgroup_by_path(*name, NULL, 0, output_flags); } else { _cleanup_free_ char *c = NULL, *p = NULL, *j = NULL; const char *controller, *path; - r = cg_split_spec(argv[i], &c, &p); + if (!root) { + /* Query root only if needed, treat error as fatal */ + r = show_cgroup_get_path_and_warn(arg_machine, NULL, &root); + if (r < 0) + goto finish; + } + + r = cg_split_spec(*name, &c, &p); if (r < 0) { - log_error_errno(r, "Failed to split argument %s: %m", argv[i]); - goto finish; + log_error_errno(r, "Failed to split argument %s: %m", *name); + goto failed; } controller = c ?: SYSTEMD_CGROUP_CONTROLLER; @@ -239,7 +265,8 @@ int main(int argc, char *argv[]) { q = show_cgroup(controller, path, NULL, 0, output_flags); } - if (q < 0) + failed: + if (q < 0 && r >= 0) r = q; } @@ -267,7 +294,7 @@ int main(int argc, char *argv[]) { if (!done) { _cleanup_free_ char *root = NULL; - r = get_cgroup_root(&root); + r = show_cgroup_get_path_and_warn(arg_machine, NULL, &root); if (r < 0) goto finish; @@ -283,6 +310,7 @@ int main(int argc, char *argv[]) { finish: pager_close(); + free(arg_names); /* don't free the strings */ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index af5c3d8695..50ac6a58b0 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -31,6 +31,7 @@ #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" +#include "cgroup-show.h" #include "cgroup-util.h" #include "fd-util.h" #include "fileio.h" @@ -862,13 +863,9 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached("Unhandled option"); } - if (optind == argc-1) { - if (arg_machine) { - log_error("Specifying a control group path together with the -M option is not allowed"); - return -EINVAL; - } + if (optind == argc - 1) arg_root = argv[optind]; - } else if (optind < argc) { + else if (optind < argc) { log_error("Too many arguments."); return -EINVAL; } @@ -890,59 +887,6 @@ static const char* counting_what(void) { return "userspace processes (excl. kernel)"; } -static int get_cgroup_root(char **ret) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - _cleanup_free_ char *unit = NULL, *path = NULL; - const char *m; - int r; - - if (arg_root) { - char *aux; - - aux = strdup(arg_root); - if (!aux) - return log_oom(); - - *ret = aux; - return 0; - } - - if (!arg_machine) { - r = cg_get_root_path(ret); - if (r < 0) - return log_error_errno(r, "Failed to get root control group path: %m"); - - return 0; - } - - m = strjoina("/run/systemd/machines/", arg_machine); - r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL); - if (r < 0) - return log_error_errno(r, "Failed to load machine data: %m"); - - path = unit_dbus_path_from_name(unit); - if (!path) - return log_oom(); - - r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus); - if (r < 0) - return log_error_errno(r, "Failed to create bus connection: %m"); - - r = sd_bus_get_property_string( - bus, - "org.freedesktop.systemd1", - path, - unit_dbus_interface_from_name(unit), - "ControlGroup", - &error, - ret); - if (r < 0) - return log_error_errno(r, "Failed to query unit control group path: %s", bus_error_message(&error, r)); - - return 0; -} - int main(int argc, char *argv[]) { int r; Hashmap *a = NULL, *b = NULL; @@ -967,11 +911,12 @@ int main(int argc, char *argv[]) { if (r <= 0) goto finish; - r = get_cgroup_root(&root); + r = show_cgroup_get_path_and_warn(arg_machine, arg_root, &root); if (r < 0) { log_error_errno(r, "Failed to get root control group path: %m"); goto finish; - } + } else + log_debug("Cgroup path: %s", root); a = hashmap_new(&string_hash_ops); b = hashmap_new(&string_hash_ops); diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 4c618ed19e..1aac7ae979 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -240,7 +240,6 @@ static int list_seats(int argc, char *argv[], void *userdata) { sd_bus *bus = userdata; unsigned k = 0; int r; - assert(bus); assert(argv); @@ -280,35 +279,17 @@ static int list_seats(int argc, char *argv[], void *userdata) { } static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) { + _cleanup_free_ char *cgroup = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - _cleanup_free_ char *path = NULL; - const char *cgroup; unsigned c; int r; assert(bus); assert(unit); - path = unit_dbus_path_from_name(unit); - if (!path) - return log_oom(); - - r = sd_bus_get_property( - bus, - "org.freedesktop.systemd1", - path, - interface, - "ControlGroup", - &error, - &reply, - "s"); - if (r < 0) - return log_error_errno(r, "Failed to query ControlGroup: %s", bus_error_message(&error, r)); - - r = sd_bus_message_read(reply, "s", &cgroup); + r = show_cgroup_get_unit_path_and_warn(bus, unit, &cgroup); if (r < 0) - return bus_log_parse_error(r); + return r; if (isempty(cgroup)) return 0; diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 31a40d47c3..4f5f659c7c 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -477,35 +477,17 @@ static int list_images(int argc, char *argv[], void *userdata) { } static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) { + _cleanup_free_ char *cgroup = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - _cleanup_free_ char *path = NULL; - const char *cgroup; int r; unsigned c; assert(bus); assert(unit); - path = unit_dbus_path_from_name(unit); - if (!path) - return log_oom(); - - r = sd_bus_get_property( - bus, - "org.freedesktop.systemd1", - path, - unit_dbus_interface_from_name(unit), - "ControlGroup", - &error, - &reply, - "s"); - if (r < 0) - return log_error_errno(r, "Failed to query ControlGroup: %s", bus_error_message(&error, r)); - - r = sd_bus_message_read(reply, "s", &cgroup); + r = show_cgroup_get_unit_path_and_warn(bus, unit, &cgroup); if (r < 0) - return bus_log_parse_error(r); + return r; if (isempty(cgroup)) return 0; diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c index f5bb0603c3..8765cf2f49 100644 --- a/src/shared/cgroup-show.c +++ b/src/shared/cgroup-show.c @@ -24,10 +24,15 @@ #include <stdlib.h> #include <string.h> +#include <systemd/sd-bus.h> + #include "alloc-util.h" +#include "bus-error.h" +#include "bus-util.h" #include "cgroup-show.h" #include "cgroup-util.h" #include "fd-util.h" +#include "fileio.h" #include "format-util.h" #include "locale-util.h" #include "macro.h" @@ -36,6 +41,7 @@ #include "process-util.h" #include "string-util.h" #include "terminal-util.h" +#include "unit-name.h" static void show_pid_array( pid_t pids[], @@ -310,3 +316,81 @@ int show_cgroup_and_extra_by_spec( return show_cgroup_and_extra(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags); } + +int show_cgroup_get_unit_path_and_warn( + sd_bus *bus, + const char *unit, + char **ret) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *path = NULL; + int r; + + path = unit_dbus_path_from_name(unit); + if (!path) + return log_oom(); + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + path, + unit_dbus_interface_from_name(unit), + "ControlGroup", + &error, + ret); + if (r < 0) + return log_error_errno(r, "Failed to query unit control group path: %s", + bus_error_message(&error, r)); + + return 0; +} + +int show_cgroup_get_path_and_warn( + const char *machine, + const char *prefix, + char **ret) { + + int r; + _cleanup_free_ char *root = NULL; + + if (machine) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *unit = NULL; + const char *m; + + m = strjoina("/run/systemd/machines/", machine); + r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL); + if (r < 0) + return log_error_errno(r, "Failed to load machine data: %m"); + + r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + r = show_cgroup_get_unit_path_and_warn(bus, unit, &root); + if (r < 0) + return r; + } else { + r = cg_get_root_path(&root); + if (r == -ENOMEDIUM) + return log_error_errno(r, "Failed to get root control group path.\n" + "No cgroup filesystem mounted on /sys/fs/cgroup"); + else if (r < 0) + return log_error_errno(r, "Failed to get root control group path: %m"); + } + + if (prefix) { + char *t; + + t = strjoin(root, prefix); + if (!t) + return log_oom(); + + *ret = t; + } else { + *ret = root; + root = NULL; + } + + return 0; +} diff --git a/src/shared/cgroup-show.h b/src/shared/cgroup-show.h index 5c1d6e6d98..736f0f34c8 100644 --- a/src/shared/cgroup-show.h +++ b/src/shared/cgroup-show.h @@ -22,6 +22,8 @@ #include <stdbool.h> #include <sys/types.h> +#include <systemd/sd-bus.h> + #include "logs-show.h" #include "output-mode.h" @@ -30,3 +32,12 @@ int show_cgroup(const char *controller, const char *path, const char *prefix, un int show_cgroup_and_extra_by_spec(const char *spec, const char *prefix, unsigned n_columns, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags); int show_cgroup_and_extra(const char *controller, const char *path, const char *prefix, unsigned n_columns, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags); + +int show_cgroup_get_unit_path_and_warn( + sd_bus *bus, + const char *unit, + char **ret); +int show_cgroup_get_path_and_warn( + const char *machine, + const char *prefix, + char **ret); |