]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/lxc-ps.in
use pivot_root instead of chroot
[mirror_lxc.git] / src / lxc / lxc-ps.in
1 #!/usr/bin/perl
2 #
3 # lxc-ps
4 #
5 # Authors:
6 # Daniel Lezcano <daniel.lezcano@free.fr>
7
8 # This library is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU Lesser General Public
10 # License as published by the Free Software Foundation; either
11 # version 2.1 of the License, or (at your option) any later version.
12
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 # Lesser General Public License for more details.
17
18 # You should have received a copy of the GNU Lesser General Public
19 # License along with this library; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22 #
23 # This script allows to
24 # display processes information with related container name if available.
25 #
26 use strict;
27
28
29 # Some globals
30
31 our $PS_HEADERS; # String containing headers of the ps output
32 our $PS_PID_INDEX; # Index of the PID column in the ps headers
33 our @PS_LINES; # Output lines of the ps command
34
35 our $LXC_DISPLAY = 0; # By default do not display container information
36 our %LXC_NAMES; # Specified container names (if any)
37
38 sub get_container_names {
39 my $ref_names = shift;
40 my $lxcpath='@LXCPATH@';
41
42 open(active, "netstat -xa | grep $lxcpath |") or return;
43 while(<active>) {
44 chomp;
45 s#.*$lxcpath/(.*)/command.*#$1#;
46 push @$ref_names, $_;
47 }
48 close active;
49 }
50
51 sub get_cgroup {
52 my $ref_cgroup = shift;
53 my $mount_string;
54
55 $mount_string=`mount -t cgroup |grep -E -e '^lxc '`;
56 unless ($mount_string) {
57 $mount_string=`mount |grep -m1 'type cgroup'`;
58 }
59 chomp($mount_string);
60 if ($mount_string) {
61 $$ref_cgroup=`echo "$mount_string" |cut -d' ' -f3`;
62 chomp($$ref_cgroup);
63 }
64 die "unable to find mounted cgroup" unless $$ref_cgroup;
65 }
66
67 sub get_pids_in_containers {
68 my $ref_names = shift;
69 my $ref_cgroup = shift;
70 my $ref_pids = shift;
71 my @pidlist;
72
73 for (@{$ref_names}) {
74 my $task_file = "$$ref_cgroup/$_/tasks";
75
76 $LXC_NAMES{$_} = 1;
77 open(tasks, "cat $task_file 2>/dev/null |") or next;
78 while (<tasks>) {
79 chomp $_;
80 push @pidlist, $_;
81 }
82 close tasks;
83 }
84 $$ref_pids = join(',', @pidlist);
85 }
86
87 sub reclaim_pid_index {
88 my @headers = split " ", $PS_HEADERS;
89 for my $i (0 .. $#headers) {
90 if ($headers[$i] eq "PID") {
91 $PS_PID_INDEX = $i;
92 return;
93 }
94 }
95 print "Cannot find ps PID column !\n";
96 exit 1;
97 }
98
99 sub execute_ps {
100 open(ps, "ps @_ |") or die "Cannot execute ps command: $!\n";
101
102 $PS_HEADERS = <ps>;
103 reclaim_pid_index;
104
105 while (<ps>) {
106 push @PS_LINES, $_;
107 }
108 close ps;
109 }
110
111 sub get_container {
112 my $pid = shift;
113 my $filename = "/proc/$pid/cgroup";
114 open(LXC, "$filename");
115 my $container = <LXC>;
116 close LXC;
117 chomp($container);
118 if ($container =~ m/[:,]ns[:,]/o) {
119 $container =~ s/.*:\///o;
120 } else {
121 $container ='';
122 }
123 return $container;
124 }
125
126 sub display_headers {
127 printf "%-10s %s", "CONTAINER", $PS_HEADERS;
128 }
129
130 sub display_usage {
131 print <<EOF;
132 Usage: lxc-ps [--help] [--usage] [--name NAME...] [--lxc] [ps options]
133 EOF
134 }
135
136 sub display_help {
137 display_usage;
138 print <<EOF;
139
140 Display processes information with related container name if available.
141
142 Options:
143 --help Display this help.
144 --usage Display the command usage.
145 --name Display processes related to given containers.
146 Containers are identified by a comma separated list of
147 their names.
148 --lxc Display processes related to all lxc containers.
149
150 Other available options correspond to the ps ones, see the ps manual
151 or try a 'ps --help' for further details.
152 EOF
153 }
154
155 use Getopt::Long qw(:config no_auto_abbrev pass_through);
156
157 my $arg_help = '';
158 my $arg_usage = '';
159 my $arg_lxc = '';
160 my @arg_name;
161
162 GetOptions('help' => \$arg_help,
163 'usage' => \$arg_usage,
164 'lxc' => \$arg_lxc,
165 'name=s' => \@arg_name);
166
167 @arg_name = split(/,/, join(',', @arg_name));
168
169 # Some help
170 if ($arg_help) {display_help; exit 0;}
171 if ($arg_usage) {display_usage; exit 0;}
172
173 # Should we filter processes related to containers
174 if ($arg_lxc) {
175 $LXC_DISPLAY = 1;
176 get_container_names \@arg_name;
177 }
178 if (@arg_name > 0) {
179 my $cgroup;
180 my $pid_list;
181 $LXC_DISPLAY = 2;
182
183 get_cgroup \$cgroup;
184 get_pids_in_containers(\@arg_name, \$cgroup, \$pid_list);
185 if ($pid_list) {
186 @ARGV = ("-p $pid_list",@ARGV);
187 }
188 }
189
190 execute_ps @ARGV;
191
192 display_headers;
193 for (@PS_LINES) {
194 my @a = split;
195 my $container = get_container $a[$PS_PID_INDEX];
196 if ($LXC_DISPLAY == 2 and not $LXC_NAMES{$container}) {next;}
197 if ($LXC_DISPLAY == 1 and $container eq '') {next;}
198 printf "%-10s %s", $container, $_;
199 }
200
201 exit 0;