Open main menu

OpenVZ Virtuozzo Containers Wiki β

Human readable user beancounters

Revision as of 15:52, 6 May 2011 by Drodriguez (talk | contribs)

For newbies to openvz it is fairly difficult to understand the meaning of the numbers in /proc/user_beancounters file. Calculating the values to something understandable for human brain everytime you look at these statistics is much work. I have written a perl script which reformats the output to human-readable values in kbyte and mbyte.

Just be sure you have Perl installed on your HN/VE, copy this script to somewhere on your machine, give it executable rights and start it. The output will be like this:

BEANS FOR UID 254
resource                     held              maxheld              barrier                limit              failcnt
kmemsize                 15.14 mb             18.72 mb            150.30 mb            167.00 mb                    0
lockedpages                     0                    0             16.00 mb             16.00 mb                    0
privvmpages             433.79 mb            544.63 mb           2929.69 mb           3222.66 mb                    0
shmpages                 11.58 mb             11.64 mb            512.00 mb            512.00 mb                    0
numproc                        84                  101                  500                  500                    0
physpages               278.24 mb            395.75 mb                    0            unlimited                    0
vmguarpages                     0                    0            244.14 mb            unlimited                    0
oomguarpages            279.66 mb            396.98 mb            122.07 mb            unlimited                    0
numtcpsock                     25                   53                  500                  500                    0
numflock                       18                   22                  200                  220                    0
numpty                          4                    4                   64                   64                    0
numsiginfo                      0                   11                  512                  512                    0
tcpsndbuf               569.75 kb            679.25 kb              5.12 mb             10.00 mb                    0
tcprcvbuf               400.00 kb              1.28 mb              5.12 mb             10.00 mb                    0
othersockbuf            213.00 kb            284.25 kb              1.43 mb              3.88 mb                    0
dgramrcvbuf               0.00 kb              8.25 kb            256.00 kb            256.00 kb                    0
numothersock                  155                  175                  500                  500                    0
dcachesize              619.68 kb            656.68 kb              4.00 mb              4.12 mb                    0
numfile                      2008                 2397                 9312                 9312                    0
numiptent                      10                   10                  128                  128                    0

The script is the following, just copy and paste:

#!/usr/bin/perl

###############################################################################
# vzstats.pl
#
# this script reads /proc/user_beancounters on openvz HNs and VEs and displays
# the values in human-readable format (megabytes/kilobytes).
#
# The script can be distributed freely for everybody who finds it usable.
#
# Christian Anton <mail |_at_| christiananton.de> 2008-09-18



open(BEANS,"/proc/user_beancounters");
chomp ($arch = `uname -m`);

sub check_maxulong {
	my $number = shift;

	if ($arch eq "x86_64") {
		if ($number == 9223372036854775807) {
			return 1;
		} else {
			return undef;
		}
	} else {
		if ($number == 2147483647) {
			return 1;
		} else {
			return undef;
		}
	}
}

sub recalc_bytes {
	my $bytes = shift;

	if (defined(&check_maxulong($bytes))) { return "unlimited"; }

	my $kbytes = $bytes / 1024;
	my $ret;
	
	# if over 1mb, show mb values
	if ($kbytes > 1024) {
		my $mbytes = $kbytes / 1024;
		$ret = sprintf("%.2f", $mbytes) . " mb";
		return $ret;
	} else {
		$ret = sprintf("%.2f", $kbytes) . " kb";
		return $ret;
	}
}

sub recalc_pages {
	my $pages = shift;

	if ($pages == 0) { return "0"; }
	if (defined(&check_maxulong($pages))) { return "unlimited"; }

	my $kbytes = $pages * 4;
	my $ret;

	if ($kbytes > 1024) {
		my $mbytes = $kbytes / 1024;
		$ret = sprintf("%.2f", $mbytes) . " mb";
		return $ret;
	} else {
		$ret = sprintf("%.2f", $kbytes) . " kb";
		return $ret;
	}
}

sub recalc_nothing {
	my $number = shift;
	if (defined(&check_maxulong($number))) { return "unlimited"; }

	return $number;
}

sub printline {
	my $mode = shift; # 0=normal, 1=bytes, 2=pages
	my $ident = shift;
	my $held = shift;
	my $maxheld = shift;
	my $barrier = shift;
	my $limit = shift;
	my $failcnt = shift;

	if ($mode == 0) {
		printf ("%-15s",$ident);
		printf ("%18s",&recalc_nothing($held));
		printf ("%21s",&recalc_nothing($maxheld));
		printf ("%21s",&recalc_nothing($barrier));
		printf ("%21s",&recalc_nothing($limit));
		printf ("%21s",$failcnt);
		print "\n";
	} elsif ($mode == 1) {
		printf ("%-15s",$ident);
		printf ("%18s",&recalc_bytes($held));
		printf ("%21s",&recalc_bytes($maxheld));
		printf ("%21s",&recalc_bytes($barrier));
		printf ("%21s",&recalc_bytes($limit));
		printf ("%21s",$failcnt);
		print "\n";
	} elsif ($mode == 2) {
		printf ("%-15s",$ident);
		printf ("%18s",&recalc_pages($held));
		printf ("%21s",&recalc_pages($maxheld));
		printf ("%21s",&recalc_pages($barrier));
		printf ("%21s",&recalc_pages($limit));
		printf ("%21s",$failcnt);
		print "\n";
	}
}

sub work_line {
	my $line = shift;
	my $ident = $line;
	my $held = $line;
	my $maxheld = $line;
	my $barrier = $line;
	my $limit = $line;
	my $failcnt = $line;



	$ident =~ s/^\s+(\w+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/$1/;
	$held =~ s/^\s+(\w+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/$2/;
	$maxheld =~ s/^\s+(\w+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/$3/;
	$barrier =~ s/^\s+(\w+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/$4/;
	$limit =~ s/^\s+(\w+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/$5/;
	$failcnt =~ s/^\s+(\w+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/$6/;

	# 0=normal, 1=bytes, 2=pages
	if ($ident eq "dummy") {
		# do nothing, skip this line
	} elsif ($ident =~ /pages/) {
		&printline(2,$ident,$held,$maxheld,$barrier,$limit,$failcnt);
	} elsif ($ident =~ /^num/) {
		&printline(0,$ident,$held,$maxheld,$barrier,$limit,$failcnt);
	} else {
		&printline(1,$ident,$held,$maxheld,$barrier,$limit,$failcnt);
	}

}

sub print_header {
	my $uid = shift;

	print "#####################################################################################################################\n";
	print "BEANS FOR UID $uid\n";
	print "resource                     held              maxheld              barrier                limit              failcnt\n";
}

# now eat your beans baby
while (<BEANS>) {
	chomp($line = $_);

	# skip processing of headline
	if ($line =~ /^\s+uid/) {
		# do nothing, skip this
	} elsif ($line =~ /^Ver/) {
		# do nothing, skip this
	} elsif ($line =~ /^\s+\d+:\s+kmem/) {
		$uid = $line;
		$line =~ s/^(\s+)(\d+):/$1/;
		$uid =~ s/^(\s+)(\d+):.*$/$2/;
		&print_header($uid);
		&work_line($line);
	} else {
		&work_line($line);
	}
}

close(BEANS);

Here's a quick patch which adds on VE hostname lookups. It depends on vzlist being in the path but won't break if it isn't.

*** beanCounters.pl-orig        Sun Nov  9 14:08:56 2008
--- beanCounters.pl     Sun Nov  9 14:08:21 2008
***************
*** 9,14 ****
--- 9,17 ----
  # The script can be distributed freely for everybody who finds it usable.
  #
  # Christian Anton <mail |_at_| christiananton.de> 2008-09-18
+ #
+ # David Osborn <ossdev -at- daoCon.com> 2008-11-09
+ #     Added VE name to output
   
   
   
***************
*** 147,158 ****
   
  sub print_header {
        my $uid = shift;
   
        print "#####################################################################################################################\n";
!       print "BEANS FOR UID $uid\n";
        print "resource                     held              maxheld              barrier               limit              failcnt\n";
  }
   
  # now eat your beans baby
  while (<BEANS>) {
        chomp($line = $_);
--- 150,193 ----
   
  sub print_header {
        my $uid = shift;
+       my $hostname = shift;
   
        print "#####################################################################################################################\n";
!       print "BEANS FOR UID $uid ($hostname)\n";
        print "resource                     held              maxheld              barrier                limit              failcnt\n";
  }
   
+ sub get_hostname {
+       my $uid = shift;
+       my @vzout;
+ 
+       # already retrieved list
+       if (defined %hostnames) {
+               if (defined $hostnames{$uid}) {
+                       return $hostnames{$uid};
+               } else {
+                       return 'not found';
+               }
+       # try to retrieve the list
+       } elsif ( eval(@vzout = `vzlist -H -o veid,hostname`) ) {
+               $hostnames{0} = 'HN';
+               while (@vzout) { 
+                       my $line = shift @vzout;
+                       my ($tuid,$hostname) = $line =~ /^\s+(\d+)\s+(\S+)/;
+                       $hostnames{$tuid} = $hostname;
+               }
+               return $hostnames{$uid};
+       } else {
+               # something's wrong
+               return 'unknown';
+       }
+ 
+ }
+ 
+ 
+ # Hash used to store uid to hostname lookups
+ my %hostnames;
+ 
  # now eat your beans baby
  while (<BEANS>) {
        chomp($line = $_);
***************
*** 166,172 ****
                $uid = $line;
                $line =~ s/^(\s+)(\d+):/$1/;
                $uid =~ s/^(\s+)(\d+):.*$/$2/;
!               &print_header($uid);
                &work_line($line);
        } else {
                &work_line($line);
--- 201,207 ----
                $uid = $line;
                $line =~ s/^(\s+)(\d+):/$1/;
                $uid =~ s/^(\s+)(\d+):.*$/$2/;
!               &print_header($uid, get_hostname($uid));
                &work_line($line);
        } else {
                &work_line($line);

Quick (and dirty) patch to only display the information of one container (first argument of the script). Usage:

$ beancounters.pl VEID
--- beancounters.pl	2011-05-06 01:06:58.000000000 -0300
+++ beancounters-container.pl	2011-05-06 12:43:09.000000000 -0300
@@ -11,8 +11,7 @@
 # Christian Anton <mail |_at_| christiananton.de> 2008-09-18
  
  
- 
-open(BEANS,"/proc/user_beancounters");
+open(BEANS,"cat /proc/user_beancounters | grep \" ${ARGV[0]}:\" -A 23  |");
 chomp ($arch = `uname -m`);
  
 sub check_maxulong {