diff options
Diffstat (limited to 'src/cgtop/cgtop.c')
-rw-r--r-- | src/cgtop/cgtop.c | 103 |
1 files changed, 81 insertions, 22 deletions
diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index 4786a155da..9cf13cf57d 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -36,6 +36,10 @@ #include "cgroup-util.h" #include "build.h" #include "fileio.h" +#include "sd-bus.h" +#include "bus-util.h" +#include "bus-error.h" +#include "unit-name.h" typedef struct Group { char *path; @@ -65,6 +69,7 @@ static unsigned arg_iterations = (unsigned) -1; static bool arg_batch = false; static bool arg_raw = false; static usec_t arg_delay = 1*USEC_PER_SEC; +static char* arg_machine = NULL; enum { COUNT_PIDS, @@ -523,9 +528,6 @@ static int group_compare(const void*a, const void *b) { return path_compare(x->path, y->path); } -#define ON ANSI_HIGHLIGHT_ON -#define OFF ANSI_HIGHLIGHT_OFF - static void display(Hashmap *a) { Iterator i; Group *g; @@ -536,10 +538,8 @@ static void display(Hashmap *a) { assert(a); - /* Set cursor to top left corner and clear screen */ if (on_tty()) - fputs("\033[H" - "\033[2J", stdout); + fputs(ANSI_HOME_CLEAR, stdout); array = alloca(sizeof(Group*) * hashmap_size(a)); @@ -571,23 +571,30 @@ static void display(Hashmap *a) { rows = 10; if (on_tty()) { + const char *on, *off; + path_columns = columns() - 36 - strlen(buffer); if (path_columns < 10) path_columns = 10; - printf("%s%-*s%s %s%7s%s %s%s%s %s%8s%s %s%8s%s %s%8s%s\n\n", - arg_order == ORDER_PATH ? ON : "", path_columns, "Control Group", - arg_order == ORDER_PATH ? OFF : "", - arg_order == ORDER_TASKS ? ON : "", arg_count == COUNT_PIDS ? "Tasks" : arg_count == COUNT_USERSPACE_PROCESSES ? "Procs" : "Proc+", - arg_order == ORDER_TASKS ? OFF : "", - arg_order == ORDER_CPU ? ON : "", buffer, - arg_order == ORDER_CPU ? OFF : "", - arg_order == ORDER_MEMORY ? ON : "", "Memory", - arg_order == ORDER_MEMORY ? OFF : "", - arg_order == ORDER_IO ? ON : "", "Input/s", - arg_order == ORDER_IO ? OFF : "", - arg_order == ORDER_IO ? ON : "", "Output/s", - arg_order == ORDER_IO ? OFF : ""); + on = ansi_highlight_underline(); + off = ansi_underline(); + + printf("%s%s%-*s%s %s%7s%s %s%s%s %s%8s%s %s%8s%s %s%8s%s%s\n", + ansi_underline(), + arg_order == ORDER_PATH ? on : "", path_columns, "Control Group", + arg_order == ORDER_PATH ? off : "", + arg_order == ORDER_TASKS ? on : "", arg_count == COUNT_PIDS ? "Tasks" : arg_count == COUNT_USERSPACE_PROCESSES ? "Procs" : "Proc+", + arg_order == ORDER_TASKS ? off : "", + arg_order == ORDER_CPU ? on : "", buffer, + arg_order == ORDER_CPU ? off : "", + arg_order == ORDER_MEMORY ? on : "", "Memory", + arg_order == ORDER_MEMORY ? off : "", + arg_order == ORDER_IO ? on : "", "Input/s", + arg_order == ORDER_IO ? off : "", + arg_order == ORDER_IO ? on : "", "Output/s", + arg_order == ORDER_IO ? off : "", + ansi_normal()); } else path_columns = maxtpath; @@ -595,7 +602,7 @@ static void display(Hashmap *a) { _cleanup_free_ char *ellipsized = NULL; const char *path; - if (on_tty() && j + 5 > rows) + if (on_tty() && j + 6 > rows) break; g = array[j]; @@ -645,6 +652,7 @@ static void help(void) { " -n --iterations=N Run for N iterations before exiting\n" " -b --batch Run in batch mode, accepting no input\n" " --depth=DEPTH Maximum traversal depth (default: %u)\n" + " -M --machine= Show container\n" , program_invocation_short_name, arg_depth); } @@ -669,6 +677,7 @@ static int parse_argv(int argc, char *argv[]) { { "cpu", optional_argument, NULL, ARG_CPU_TYPE }, { "order", required_argument, NULL, ARG_ORDER }, { "recursive", required_argument, NULL, ARG_RECURSIVE }, + { "machine", required_argument, NULL, 'M' }, {} }; @@ -678,7 +687,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 1); assert(argv); - while ((c = getopt_long(argc, argv, "hptcmin:brd:kP", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "hptcmin:brd:kPM:", options, NULL)) >= 0) switch (c) { @@ -797,6 +806,10 @@ static int parse_argv(int argc, char *argv[]) { recursive_unset = r == 0; break; + case 'M': + arg_machine = optarg; + break; + case '?': return -EINVAL; @@ -826,6 +839,48 @@ static const char* counting_what(void) { return "userspace processes (excl. kernel)"; } +static int get_cgroup_root(char **ret) { + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_bus_flush_close_unref_ 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 < 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_open_transport(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; @@ -850,7 +905,7 @@ int main(int argc, char *argv[]) { if (r <= 0) goto finish; - r = cg_get_root_path(&root); + r = get_cgroup_root(&root); if (r < 0) { log_error_errno(r, "Failed to get root control group path: %m"); goto finish; @@ -1008,6 +1063,10 @@ int main(int argc, char *argv[]) { case '?': case 'h': + +#define ON ANSI_HIGHLIGHT +#define OFF ANSI_NORMAL + fprintf(stdout, "\t<" ON "p" OFF "> By path; <" ON "t" OFF "> By tasks/procs; <" ON "c" OFF "> By CPU; <" ON "m" OFF "> By memory; <" ON "i" OFF "> By I/O\n" "\t<" ON "+" OFF "> Inc. delay; <" ON "-" OFF "> Dec. delay; <" ON "%%" OFF "> Toggle time; <" ON "SPACE" OFF "> Refresh\n" |