cgls.c revision c33b329709ebe2755181980a050d02ec7c81ed87
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering/***
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering This file is part of systemd.
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering Copyright 2010 Lennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering systemd is free software; you can redistribute it and/or modify it
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering under the terms of the GNU Lesser General Public License as published by
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering (at your option) any later version.
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering systemd is distributed in the hope that it will be useful, but
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering Lesser General Public License for more details.
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering You should have received a copy of the GNU Lesser General Public License
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering***/
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering#include <limits.h>
0ac38b707212e9aa40e25d65ffbae648cc9116f5Lennart Poettering#include <stdio.h>
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering#include <unistd.h>
81527be142678057215665be66e4b3c8306a7ab3Lennart Poettering#include <errno.h>
81527be142678057215665be66e4b3c8306a7ab3Lennart Poettering#include <getopt.h>
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering#include <string.h>
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include "cgroup-show.h"
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include "cgroup-util.h"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering#include "log.h"
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek#include "path-util.h"
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek#include "util.h"
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek#include "pager.h"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering#include "build.h"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering#include "output-mode.h"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering#include "fileio.h"
3c1668da6202f1ead3d4d3981b89e9da1a0e98e3Lennart Poettering#include "sd-bus.h"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering#include "bus-util.h"
de190aef08bb267b645205a747762df573b36834Lennart Poettering#include "bus-error.h"
95ea1b90cc61f464f3b9bc147119dee4ba9620b8Lennart Poettering#include "unit-name.h"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poetteringstatic bool arg_no_pager = false;
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poetteringstatic bool arg_kernel_threads = false;
95ea1b90cc61f464f3b9bc147119dee4ba9620b8Lennart Poetteringstatic bool arg_all = false;
95ea1b90cc61f464f3b9bc147119dee4ba9620b8Lennart Poetteringstatic int arg_full = -1;
0ac38b707212e9aa40e25d65ffbae648cc9116f5Lennart Poetteringstatic char* arg_machine = NULL;
16e9f408fa9a9626059bdd6c89dc175e06b9e976Lennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poetteringstatic void help(void) {
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering printf("%s [OPTIONS...] [CGROUP...]\n\n"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering "Recursively show control group contents.\n\n"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering " -h --help Show this help\n"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering " --version Show package version\n"
c2373f848dddcc1827cf715c5ef778dc8d475761Lennart Poettering " --no-pager Do not pipe output into a pager\n"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering " -a --all Show all groups, including empty\n"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering " -l --full Do not ellipsize output\n"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering " -k Include kernel threads in output\n"
c2373f848dddcc1827cf715c5ef778dc8d475761Lennart Poettering " -M --machine Show container\n"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering , program_invocation_short_name);
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering}
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
c2373f848dddcc1827cf715c5ef778dc8d475761Lennart Poetteringstatic int parse_argv(int argc, char *argv[]) {
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering enum {
b0af6f41ea67c97b8beb16fd1d63042379bbf103Lennart Poettering ARG_NO_PAGER = 0x100,
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering ARG_VERSION,
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering };
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
de190aef08bb267b645205a747762df573b36834Lennart Poettering static const struct option options[] = {
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering { "help", no_argument, NULL, 'h' },
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering { "version", no_argument, NULL, ARG_VERSION },
de190aef08bb267b645205a747762df573b36834Lennart Poettering { "no-pager", no_argument, NULL, ARG_NO_PAGER },
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering { "all", no_argument, NULL, 'a' },
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering { "full", no_argument, NULL, 'l' },
de190aef08bb267b645205a747762df573b36834Lennart Poettering { "machine", required_argument, NULL, 'M' },
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering {}
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering };
de190aef08bb267b645205a747762df573b36834Lennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering int c;
de190aef08bb267b645205a747762df573b36834Lennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering assert(argc >= 1);
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering assert(argv);
de190aef08bb267b645205a747762df573b36834Lennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering while ((c = getopt_long(argc, argv, "hkalM:", options, NULL)) >= 0)
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
de190aef08bb267b645205a747762df573b36834Lennart Poettering switch (c) {
de190aef08bb267b645205a747762df573b36834Lennart Poettering
de190aef08bb267b645205a747762df573b36834Lennart Poettering case 'h':
de190aef08bb267b645205a747762df573b36834Lennart Poettering help();
de190aef08bb267b645205a747762df573b36834Lennart Poettering return 0;
de190aef08bb267b645205a747762df573b36834Lennart Poettering
de190aef08bb267b645205a747762df573b36834Lennart Poettering case ARG_VERSION:
de190aef08bb267b645205a747762df573b36834Lennart Poettering puts(PACKAGE_STRING);
de190aef08bb267b645205a747762df573b36834Lennart Poettering puts(SYSTEMD_FEATURES);
de190aef08bb267b645205a747762df573b36834Lennart Poettering return 0;
de190aef08bb267b645205a747762df573b36834Lennart Poettering
de190aef08bb267b645205a747762df573b36834Lennart Poettering case ARG_NO_PAGER:
de190aef08bb267b645205a747762df573b36834Lennart Poettering arg_no_pager = true;
de190aef08bb267b645205a747762df573b36834Lennart Poettering break;
de190aef08bb267b645205a747762df573b36834Lennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering case 'a':
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering arg_all = true;
de190aef08bb267b645205a747762df573b36834Lennart Poettering break;
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering case 'l':
de190aef08bb267b645205a747762df573b36834Lennart Poettering arg_full = true;
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering break;
de190aef08bb267b645205a747762df573b36834Lennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering case 'k':
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering arg_kernel_threads = true;
de190aef08bb267b645205a747762df573b36834Lennart Poettering break;
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering case 'M':
de190aef08bb267b645205a747762df573b36834Lennart Poettering arg_machine = optarg;
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering break;
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
de190aef08bb267b645205a747762df573b36834Lennart Poettering case '?':
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering return -EINVAL;
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering default:
0ac38b707212e9aa40e25d65ffbae648cc9116f5Lennart Poettering assert_not_reached("Unhandled option");
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering }
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek return 1;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek}
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmekint main(int argc, char *argv[]) {
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek int r = 0, retval = EXIT_FAILURE;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek int output_flags;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek _cleanup_free_ char *root = NULL;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek _cleanup_bus_close_unref_ sd_bus *bus = NULL;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek log_parse_environment();
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek log_open();
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek r = parse_argv(argc, argv);
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek if (r < 0)
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek goto finish;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek else if (r == 0) {
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek retval = EXIT_SUCCESS;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek goto finish;
0ac38b707212e9aa40e25d65ffbae648cc9116f5Lennart Poettering }
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek if (!arg_no_pager) {
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek r = pager_open(false);
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek if (r > 0) {
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek if (arg_full == -1)
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek arg_full = true;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek }
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek }
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek output_flags =
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek arg_all * OUTPUT_SHOW_ALL |
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek (arg_full > 0) * OUTPUT_FULL_WIDTH;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek r = bus_open_transport(BUS_TRANSPORT_LOCAL, NULL, false, &bus);
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek if (r < 0) {
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek log_error_errno(r, "Failed to create bus connection: %m");
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek goto finish;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek }
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek if (optind < argc) {
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek int i;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek for (i = optind; i < argc; i++) {
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek int q;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek fprintf(stdout, "%s:\n", argv[i]);
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek fflush(stdout);
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek if (arg_machine)
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek root = strjoin("machine/", arg_machine, "/", argv[i], NULL);
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek else
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek root = strdup(argv[i]);
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek if (!root)
6ad1d1c30621280bfad3e63fcc1c7ceb7d8ffa98Lennart Poettering return log_oom();
143bfdaf0b890fa7acadf02d1eafacaef1b696bdHolger Hans Peter Freyther
143bfdaf0b890fa7acadf02d1eafacaef1b696bdHolger Hans Peter Freyther q = show_cgroup_by_path(root, NULL, 0,
143bfdaf0b890fa7acadf02d1eafacaef1b696bdHolger Hans Peter Freyther arg_kernel_threads, output_flags);
143bfdaf0b890fa7acadf02d1eafacaef1b696bdHolger Hans Peter Freyther if (q < 0)
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek r = q;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek }
95ea1b90cc61f464f3b9bc147119dee4ba9620b8Lennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering } else {
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering _cleanup_free_ char *p;
p = get_current_dir_name();
if (!p) {
log_error("Cannot determine current working directory: %m");
goto finish;
}
if (path_startswith(p, "/sys/fs/cgroup") && !arg_machine) {
printf("Working Directory %s:\n", p);
r = show_cgroup_by_path(p, NULL, 0,
arg_kernel_threads, output_flags);
} else {
if (arg_machine) {
char *m;
const char *cgroup;
_cleanup_free_ char *scope = NULL;
_cleanup_free_ char *path = NULL;
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
m = strappenda("/run/systemd/machines/", arg_machine);
r = parse_env_file(m, NEWLINE, "SCOPE", &scope, NULL);
if (r < 0) {
log_error_errno(r, "Failed to get machine path: %m");
goto finish;
}
path = unit_dbus_path_from_name(scope);
if (!path) {
log_oom();
goto finish;
}
r = sd_bus_get_property(
bus,
"org.freedesktop.systemd1",
path,
"org.freedesktop.systemd1.Scope",
"ControlGroup",
&error,
&reply,
"s");
if (r < 0) {
log_error("Failed to query ControlGroup: %s", bus_error_message(&error, -r));
goto finish;
}
r = sd_bus_message_read(reply, "s", &cgroup);
if (r < 0) {
bus_log_parse_error(r);
goto finish;
}
root = strdup(cgroup);
if (!root) {
log_oom();
goto finish;
}
} else
r = cg_get_root_path(&root);
if (r < 0) {
log_error_errno(r, "Failed to get %s path: %m",
arg_machine ? "machine" : "root");
goto finish;
}
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 %s: %m", root);
retval = EXIT_FAILURE;
} else
retval = EXIT_SUCCESS;
finish:
pager_close();
return retval;
}