cgls.c revision 324496eb25b51395a00430b28fac639502df9e3e
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync/***
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync This file is part of systemd.
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync Copyright 2010 Lennart Poettering
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync systemd is free software; you can redistribute it and/or modify it
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync under the terms of the GNU Lesser General Public License as published by
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync the Free Software Foundation; either version 2.1 of the License, or
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync (at your option) any later version.
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync systemd is distributed in the hope that it will be useful, but
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync WITHOUT ANY WARRANTY; without even the implied warranty of
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync Lesser General Public License for more details.
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync You should have received a copy of the GNU Lesser General Public License
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync along with systemd; If not, see <http://www.gnu.org/licenses/>.
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync***/
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync#include <stdio.h>
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync#include <unistd.h>
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync#include <errno.h>
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync#include <getopt.h>
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync#include <string.h>
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync#include "cgroup-show.h"
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync#include "cgroup-util.h"
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync#include "log.h"
0b7c1a3988178ff34dda0b27254dda793269c7eavboxsync#include "path-util.h"
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync#include "util.h"
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync#include "pager.h"
6b2a670063cd56a66a3404733df293bce35c4e67vboxsync#include "build.h"
6b2a670063cd56a66a3404733df293bce35c4e67vboxsync#include "output-mode.h"
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync#include "fileio.h"
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync#include "sd-bus.h"
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync#include "bus-util.h"
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync#include "bus-error.h"
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync#include "unit-name.h"
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsyncstatic bool arg_no_pager = false;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsyncstatic bool arg_kernel_threads = false;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsyncstatic bool arg_all = false;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsyncstatic int arg_full = -1;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsyncstatic char* arg_machine = NULL;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsyncstatic void help(void) {
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync printf("%s [OPTIONS...] [CGROUP...]\n\n"
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync "Recursively show control group contents.\n\n"
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync " -h --help Show this help\n"
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync " --version Show package version\n"
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync " --no-pager Do not pipe output into a pager\n"
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync " -a --all Show all groups, including empty\n"
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync " -l --full Do not ellipsize output\n"
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync " -k Include kernel threads in output\n"
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync " -M --machine= Show container\n"
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync , program_invocation_short_name);
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync}
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsyncstatic int parse_argv(int argc, char *argv[]) {
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync enum {
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync ARG_NO_PAGER = 0x100,
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync ARG_VERSION,
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync };
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync static const struct option options[] = {
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync { "help", no_argument, NULL, 'h' },
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync { "version", no_argument, NULL, ARG_VERSION },
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync { "no-pager", no_argument, NULL, ARG_NO_PAGER },
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync { "all", no_argument, NULL, 'a' },
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync { "full", no_argument, NULL, 'l' },
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync { "machine", required_argument, NULL, 'M' },
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync {}
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync };
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync int c;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync assert(argc >= 1);
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync assert(argv);
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync while ((c = getopt_long(argc, argv, "hkalM:", options, NULL)) >= 0)
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync switch (c) {
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync case 'h':
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync help();
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync return 0;
29b9a88f882c60887f4908f00db4461432610658vboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync case ARG_VERSION:
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync puts(PACKAGE_STRING);
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync puts(SYSTEMD_FEATURES);
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync return 0;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync case ARG_NO_PAGER:
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync arg_no_pager = true;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync break;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync case 'a':
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync arg_all = true;
e99bd87e9b40f21c8fa9e61a4e8f2fe80fe2be06vboxsync break;
e99bd87e9b40f21c8fa9e61a4e8f2fe80fe2be06vboxsync
bf250cf7115e453cb01696179244d914b9d85f2dvboxsync case 'l':
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync arg_full = true;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync break;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync case 'k':
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync arg_kernel_threads = true;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync break;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync case 'M':
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync arg_machine = optarg;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync break;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync case '?':
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync return -EINVAL;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync default:
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync assert_not_reached("Unhandled option");
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync }
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync return 1;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync}
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsyncstatic int get_cgroup_root(char **ret) {
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync _cleanup_free_ char *unit = NULL, *path = NULL;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync const char *m;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync int r;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync if (!arg_machine) {
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync r = cg_get_root_path(ret);
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync if (r < 0)
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync return log_error_errno(r, "Failed to get root control group path: %m");
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync return 0;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync }
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync m = strjoina("/run/systemd/machines/", arg_machine);
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL);
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync if (r < 0)
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync return log_error_errno(r, "Failed to load machine data: %m");
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync path = unit_dbus_path_from_name(unit);
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync if (!path)
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync return log_oom();
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync r = bus_open_transport(BUS_TRANSPORT_LOCAL, NULL, false, &bus);
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync if (r < 0)
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync return log_error_errno(r, "Failed to create bus connection: %m");
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync r = sd_bus_get_property_string(
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync bus,
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync "org.freedesktop.systemd1",
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync path,
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync unit_dbus_interface_from_name(unit),
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync "ControlGroup",
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync &error,
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync ret);
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync if (r < 0)
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync return log_error_errno(r, "Failed to query unit control group path: %s", bus_error_message(&error, r));
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync return 0;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync}
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsyncint main(int argc, char *argv[]) {
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync int r, output_flags;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync log_parse_environment();
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync log_open();
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync r = parse_argv(argc, argv);
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync if (r <= 0)
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync goto finish;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync if (!arg_no_pager) {
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync r = pager_open(false);
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync if (r > 0 && arg_full < 0)
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync arg_full = true;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync }
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync output_flags =
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync arg_all * OUTPUT_SHOW_ALL |
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync (arg_full > 0) * OUTPUT_FULL_WIDTH;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync if (optind < argc) {
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync _cleanup_free_ char *root = NULL;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync int i;
5828e9d7f59d4682a58585195d67153abdabacfcvboxsync
r = get_cgroup_root(&root);
if (r < 0)
goto finish;
for (i = optind; i < argc; i++) {
int q;
if (path_startswith(argv[i], "/sys/fs/cgroup")) {
printf("Directory %s:\n", argv[i]);
fflush(stdout);
q = show_cgroup_by_path(argv[i], NULL, 0, arg_kernel_threads, 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 (r < 0) {
log_error_errno(r, "Failed to split argument %s: %m", argv[i]);
goto finish;
}
controller = c ?: SYSTEMD_CGROUP_CONTROLLER;
if (p) {
j = strjoin(root, "/", p, NULL);
if (!j) {
r = log_oom();
goto finish;
}
path_kill_slashes(j);
path = j;
} else
path = root;
printf("Controller %s; control group %s:\n", controller, path);
fflush(stdout);
q = show_cgroup(controller, path, NULL, 0, arg_kernel_threads, output_flags);
}
if (q < 0)
r = q;
}
} else {
bool done = false;
if (!arg_machine) {
_cleanup_free_ char *cwd = NULL;
cwd = get_current_dir_name();
if (!cwd) {
r = log_error_errno(errno, "Cannot determine current working directory: %m");
goto finish;
}
if (path_startswith(cwd, "/sys/fs/cgroup")) {
printf("Working directory %s:\n", cwd);
fflush(stdout);
r = show_cgroup_by_path(cwd, NULL, 0, arg_kernel_threads, output_flags);
done = true;
}
}
if (!done) {
_cleanup_free_ char *root = NULL;
r = get_cgroup_root(&root);
if (r < 0)
goto finish;
printf("Control group %s:\n", isempty(root) ? "/" : root);
fflush(stdout);
r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, root, NULL, 0, arg_kernel_threads, output_flags);
}
}
if (r < 0)
log_error_errno(r, "Failed to list cgroup tree: %m");
finish:
pager_close();
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}