]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/cgls/cgls.c
Merge pull request #2495 from heftig/master
[thirdparty/systemd.git] / src / cgls / cgls.c
CommitLineData
fa776d8e
LP
1/***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
fa776d8e
LP
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 14 Lesser General Public License for more details.
fa776d8e 15
5430f7f2 16 You should have received a copy of the GNU Lesser General Public License
fa776d8e
LP
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
fa776d8e
LP
20#include <errno.h>
21#include <getopt.h>
3f6fd1ba 22#include <stdio.h>
fa776d8e 23#include <string.h>
3f6fd1ba
LP
24#include <unistd.h>
25
26#include "sd-bus.h"
fa776d8e 27
b5efdb8a 28#include "alloc-util.h"
3f6fd1ba
LP
29#include "bus-error.h"
30#include "bus-util.h"
fa776d8e 31#include "cgroup-show.h"
c6c18be3 32#include "cgroup-util.h"
3f6fd1ba 33#include "fileio.h"
fa776d8e 34#include "log.h"
9bdbc2e2 35#include "output-mode.h"
3f6fd1ba
LP
36#include "pager.h"
37#include "path-util.h"
13be4979 38#include "unit-name.h"
3f6fd1ba 39#include "util.h"
1968a360
LP
40
41static bool arg_no_pager = false;
1e5678d0 42static bool arg_kernel_threads = false;
c3175a7f 43static bool arg_all = false;
9bdbc2e2 44static int arg_full = -1;
38158b92 45static char* arg_machine = NULL;
fa776d8e 46
601185b4 47static void help(void) {
fa776d8e
LP
48 printf("%s [OPTIONS...] [CGROUP...]\n\n"
49 "Recursively show control group contents.\n\n"
69fc152f 50 " -h --help Show this help\n"
c3175a7f 51 " --version Show package version\n"
1e5678d0 52 " --no-pager Do not pipe output into a pager\n"
c3175a7f 53 " -a --all Show all groups, including empty\n"
98a6e132 54 " -l --full Do not ellipsize output\n"
38158b92 55 " -k Include kernel threads in output\n"
e049fa16 56 " -M --machine= Show container\n"
601185b4 57 , program_invocation_short_name);
fa776d8e
LP
58}
59
60static int parse_argv(int argc, char *argv[]) {
61
1968a360 62 enum {
c3175a7f 63 ARG_NO_PAGER = 0x100,
9bdbc2e2 64 ARG_VERSION,
1968a360
LP
65 };
66
fa776d8e 67 static const struct option options[] = {
1968a360 68 { "help", no_argument, NULL, 'h' },
c3175a7f 69 { "version", no_argument, NULL, ARG_VERSION },
1968a360 70 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
c3175a7f 71 { "all", no_argument, NULL, 'a' },
98a6e132 72 { "full", no_argument, NULL, 'l' },
38158b92 73 { "machine", required_argument, NULL, 'M' },
eb9da376 74 {}
fa776d8e
LP
75 };
76
77 int c;
78
79 assert(argc >= 1);
80 assert(argv);
81
601185b4 82 while ((c = getopt_long(argc, argv, "hkalM:", options, NULL)) >= 0)
fa776d8e
LP
83
84 switch (c) {
85
86 case 'h':
601185b4
ZJS
87 help();
88 return 0;
fa776d8e 89
c3175a7f 90 case ARG_VERSION:
3f6fd1ba 91 return version();
c3175a7f 92
1968a360
LP
93 case ARG_NO_PAGER:
94 arg_no_pager = true;
95 break;
96
c3175a7f
LP
97 case 'a':
98 arg_all = true;
99 break;
100
98a6e132 101 case 'l':
9bdbc2e2
LN
102 arg_full = true;
103 break;
104
1e5678d0
LP
105 case 'k':
106 arg_kernel_threads = true;
107 break;
108
38158b92
ZJS
109 case 'M':
110 arg_machine = optarg;
111 break;
112
fa776d8e
LP
113 case '?':
114 return -EINVAL;
115
116 default:
eb9da376 117 assert_not_reached("Unhandled option");
fa776d8e 118 }
fa776d8e
LP
119
120 return 1;
121}
122
e049fa16 123static int get_cgroup_root(char **ret) {
4afd3348
LP
124 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
125 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
e049fa16
LP
126 _cleanup_free_ char *unit = NULL, *path = NULL;
127 const char *m;
128 int r;
129
130 if (!arg_machine) {
131 r = cg_get_root_path(ret);
8b3aa503 132 if (r == -ENOMEDIUM)
e97a8475
MM
133 return log_error_errno(r, "Failed to get root control group path: No cgroup filesystem mounted on /sys/fs/cgroup");
134 else if (r < 0)
e049fa16
LP
135 return log_error_errno(r, "Failed to get root control group path: %m");
136
137 return 0;
138 }
139
140 m = strjoina("/run/systemd/machines/", arg_machine);
141 r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL);
142 if (r < 0)
143 return log_error_errno(r, "Failed to load machine data: %m");
144
145 path = unit_dbus_path_from_name(unit);
146 if (!path)
147 return log_oom();
148
266f3e26 149 r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus);
e049fa16
LP
150 if (r < 0)
151 return log_error_errno(r, "Failed to create bus connection: %m");
152
153 r = sd_bus_get_property_string(
154 bus,
155 "org.freedesktop.systemd1",
156 path,
157 unit_dbus_interface_from_name(unit),
158 "ControlGroup",
159 &error,
160 ret);
161 if (r < 0)
cb88a0a4 162 return log_error_errno(r, "Failed to query unit control group path: %s", bus_error_message(&error, r));
e049fa16
LP
163
164 return 0;
165}
166
58033c91 167static void show_cg_info(const char *controller, const char *path) {
a6a4d3c4
LP
168
169 if (cg_unified() <= 0 && controller && !streq(controller, SYSTEMD_CGROUP_CONTROLLER))
58033c91 170 printf("Controller %s; ", controller);
a6a4d3c4 171
58033c91
EV
172 printf("Control group %s:\n", isempty(path) ? "/" : path);
173 fflush(stdout);
174}
175
e049fa16
LP
176int main(int argc, char *argv[]) {
177 int r, output_flags;
fa776d8e
LP
178
179 log_parse_environment();
2396fb04 180 log_open();
fa776d8e 181
1e5678d0 182 r = parse_argv(argc, argv);
e049fa16 183 if (r <= 0)
fa776d8e 184 goto finish;
fa776d8e 185
9bdbc2e2 186 if (!arg_no_pager) {
1b12a7b5 187 r = pager_open(false);
e049fa16
LP
188 if (r > 0 && arg_full < 0)
189 arg_full = true;
9bdbc2e2
LN
190 }
191
192 output_flags =
193 arg_all * OUTPUT_SHOW_ALL |
194 (arg_full > 0) * OUTPUT_FULL_WIDTH;
1968a360 195
fa776d8e 196 if (optind < argc) {
e049fa16 197 _cleanup_free_ char *root = NULL;
38158b92 198 int i;
fa776d8e 199
e049fa16
LP
200 r = get_cgroup_root(&root);
201 if (r < 0)
202 goto finish;
203
38158b92 204 for (i = optind; i < argc; i++) {
fa776d8e 205 int q;
baa89da4 206
e049fa16 207 if (path_startswith(argv[i], "/sys/fs/cgroup")) {
fa776d8e 208
e049fa16
LP
209 printf("Directory %s:\n", argv[i]);
210 fflush(stdout);
fa776d8e 211
e049fa16
LP
212 q = show_cgroup_by_path(argv[i], NULL, 0, arg_kernel_threads, output_flags);
213 } else {
214 _cleanup_free_ char *c = NULL, *p = NULL, *j = NULL;
215 const char *controller, *path;
fa776d8e 216
e049fa16 217 r = cg_split_spec(argv[i], &c, &p);
13be4979 218 if (r < 0) {
e049fa16 219 log_error_errno(r, "Failed to split argument %s: %m", argv[i]);
13be4979
LN
220 goto finish;
221 }
222
e049fa16
LP
223 controller = c ?: SYSTEMD_CGROUP_CONTROLLER;
224 if (p) {
225 j = strjoin(root, "/", p, NULL);
226 if (!j) {
227 r = log_oom();
228 goto finish;
229 }
13be4979 230
e049fa16
LP
231 path_kill_slashes(j);
232 path = j;
233 } else
234 path = root;
13be4979 235
58033c91 236 show_cg_info(controller, path);
13be4979 237
e049fa16
LP
238 q = show_cgroup(controller, path, NULL, 0, arg_kernel_threads, output_flags);
239 }
13be4979 240
e049fa16
LP
241 if (q < 0)
242 r = q;
243 }
244
245 } else {
246 bool done = false;
13be4979 247
e049fa16
LP
248 if (!arg_machine) {
249 _cleanup_free_ char *cwd = NULL;
250
251 cwd = get_current_dir_name();
252 if (!cwd) {
253 r = log_error_errno(errno, "Cannot determine current working directory: %m");
7027ff61 254 goto finish;
b9a8e638 255 }
1f16b4a6 256
e049fa16
LP
257 if (path_startswith(cwd, "/sys/fs/cgroup")) {
258 printf("Working directory %s:\n", cwd);
259 fflush(stdout);
260
261 r = show_cgroup_by_path(cwd, NULL, 0, arg_kernel_threads, output_flags);
262 done = true;
263 }
264 }
265
266 if (!done) {
267 _cleanup_free_ char *root = NULL;
268
269 r = get_cgroup_root(&root);
270 if (r < 0)
271 goto finish;
272
58033c91 273 show_cg_info(SYSTEMD_CGROUP_CONTROLLER, root);
e049fa16 274
b1f044bb 275 printf("-.slice\n");
e049fa16 276 r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, root, NULL, 0, arg_kernel_threads, output_flags);
1f16b4a6 277 }
fa776d8e
LP
278 }
279
e049fa16
LP
280 if (r < 0)
281 log_error_errno(r, "Failed to list cgroup tree: %m");
fa776d8e
LP
282
283finish:
1968a360 284 pager_close();
fa776d8e 285
e049fa16 286 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
fa776d8e 287}