Initial import
This commit is contained in:
commit
a96d55c890
248
memstats
Executable file
248
memstats
Executable file
|
@ -0,0 +1,248 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
#
|
||||||
|
# memstats displays processes memory usage
|
||||||
|
# Copyright 2014 Grégory Soutadé
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
use POSIX ();
|
||||||
|
use Getopt::Long;
|
||||||
|
|
||||||
|
# Convert int to kilobytes, megabytes and gigabytes
|
||||||
|
sub printPacked {
|
||||||
|
my ($size) = @_;
|
||||||
|
my $suffix = "";
|
||||||
|
|
||||||
|
if($size < 1024*1024)
|
||||||
|
{
|
||||||
|
$suffix = "k";
|
||||||
|
$size = int($size/1024);
|
||||||
|
}
|
||||||
|
elsif($size < 1024*1024*1024)
|
||||||
|
{
|
||||||
|
$suffix = "m";
|
||||||
|
$size = int($size/(1024*1024));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$suffix = "g";
|
||||||
|
$size /= 1024*1024*1024;
|
||||||
|
if ($size != int($size))
|
||||||
|
{
|
||||||
|
$size = sprintf "%.2f", $size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "$size$suffix";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Convert seconds in hours:minutes:seconds
|
||||||
|
sub printTime {
|
||||||
|
my ($time) = @_;
|
||||||
|
my $res = "";
|
||||||
|
|
||||||
|
$seconds = $time % 60;
|
||||||
|
$minutes = 0;
|
||||||
|
$hours = 0;
|
||||||
|
if ($time < 60)
|
||||||
|
{
|
||||||
|
$seconds = $time;
|
||||||
|
$minutes = 0;
|
||||||
|
$hours = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$seconds = $time % 60;
|
||||||
|
$time -= $seconds;
|
||||||
|
$time /= 60;
|
||||||
|
if ($time < 60)
|
||||||
|
{
|
||||||
|
$minutes = $time;
|
||||||
|
$hours = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$minutes = $time % 60;
|
||||||
|
$time -= $minutes;
|
||||||
|
$time /= 60;
|
||||||
|
$hours = $time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$res = sprintf "%02d:%02d:%02d", $hours, $minute, $seconds;
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
# PID OWNER USER VIRT RES S TIME COMMAND
|
||||||
|
my @sizes ;
|
||||||
|
my @lines ;
|
||||||
|
|
||||||
|
# Put line to column writer
|
||||||
|
sub putLine {
|
||||||
|
my ($line) = @_;
|
||||||
|
|
||||||
|
push @lines, $line;
|
||||||
|
|
||||||
|
@s = split(/ /, $line);
|
||||||
|
if (scalar(@sizes) == 0)
|
||||||
|
{
|
||||||
|
foreach $v (@s) {push @sizes, length($v);}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for($i=0; $i<scalar(@sizes); $i++)
|
||||||
|
{
|
||||||
|
$l = length($s[$i]);
|
||||||
|
$sizes[$i] = $l if ($l > $sizes[$i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Compute column format
|
||||||
|
sub computeFormat {
|
||||||
|
my $format = "";
|
||||||
|
|
||||||
|
for($i=0; $i<scalar(@sizes); $i++)
|
||||||
|
{
|
||||||
|
if ($i > 0)
|
||||||
|
{
|
||||||
|
$format .= sprintf " %%%ds", $sizes[$i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$format .= sprintf "%%%ds", $sizes[$i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$format .= "\n";
|
||||||
|
|
||||||
|
return $format;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get current start time in seconds
|
||||||
|
sub getStartTime {
|
||||||
|
open(FIC,"</proc/self/stat") or die $!;
|
||||||
|
my @infos = split(/ /, <FIC>);
|
||||||
|
close (FIC);
|
||||||
|
|
||||||
|
return $infos[21];
|
||||||
|
}
|
||||||
|
|
||||||
|
# Constants
|
||||||
|
my $clock_ticks = POSIX::sysconf(&POSIX::_SC_CLK_TCK );
|
||||||
|
my $page_size = POSIX::sysconf(&POSIX::_SC_PAGESIZE);
|
||||||
|
my $starttime = getStartTime();
|
||||||
|
my $NB_PROCESSES = 30;
|
||||||
|
my $help;
|
||||||
|
my $all;
|
||||||
|
my $virt;
|
||||||
|
|
||||||
|
# Process paramters
|
||||||
|
my $program_name = $0;
|
||||||
|
|
||||||
|
GetOptions ("nb_processes=i" => \$NB_PROCESSES,
|
||||||
|
"all" => \$all,
|
||||||
|
"virt" => \$virt,
|
||||||
|
"help" => \$help);
|
||||||
|
|
||||||
|
if ($help)
|
||||||
|
{
|
||||||
|
printf "Display processes memory usage\nusage: %s [--all|--nb_processes=NB_PROCESSES] [--virt]\n", $program_name;
|
||||||
|
print "\t--all:\t\tList all processes\n";
|
||||||
|
print "\t--nb_processes:\tLimit list to NB_PROCESSES (default: 30)\n";
|
||||||
|
print "\t--virt:\t\tSort by virtual memory (RES by default)\n";
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
$NB_PROCESSES = -1 if ($all);
|
||||||
|
|
||||||
|
############ START ############
|
||||||
|
|
||||||
|
my @processes;
|
||||||
|
|
||||||
|
# Analyze all processes
|
||||||
|
opendir (DIR, "/proc") or die $!;
|
||||||
|
|
||||||
|
while (my $pid = readdir(DIR)) {
|
||||||
|
next if ($pid !~ /[0-9]+/);
|
||||||
|
|
||||||
|
# Get owner name
|
||||||
|
my $uid = 0;
|
||||||
|
open(FIC,"</proc/$pid/status") or die $!;
|
||||||
|
while( defined( $l = <FIC> ) ) {
|
||||||
|
if ($l =~ /Uid:\s+([0-9]+)\s+.*/)
|
||||||
|
{
|
||||||
|
$uid = $1;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close (FIC);
|
||||||
|
|
||||||
|
($owner_name,$passwd,$uid,$gid,
|
||||||
|
$quota,$comment,$gcos,$dir,$shell,$expire) = getpwuid($uid);
|
||||||
|
|
||||||
|
# Get infos
|
||||||
|
open(FIC,"</proc/$pid/stat") or die $!;
|
||||||
|
my @infos = split(/ /, <FIC>);
|
||||||
|
close (FIC);
|
||||||
|
|
||||||
|
push @processes,
|
||||||
|
{"pid" => $infos[0],
|
||||||
|
"owner" => $owner_name,
|
||||||
|
"comm" => $infos[1],
|
||||||
|
"state" => $infos[2],
|
||||||
|
"starttime" => $infos[21],
|
||||||
|
"vsize" => $infos[22],
|
||||||
|
"rss" => $infos[23],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
# Sort in reverse order by memory usage
|
||||||
|
if ($virt)
|
||||||
|
{
|
||||||
|
@p = sort {$b->{vsize} <=> $a->{vsize}} @processes;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@p = sort {$b->{rss} <=> $a->{rss}} @processes;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Compute lines
|
||||||
|
putLine("PID OWNER VIRT RES S TIME COMMAND");
|
||||||
|
|
||||||
|
foreach $e (@p)
|
||||||
|
{
|
||||||
|
$vsize = printPacked($$e{vsize});
|
||||||
|
$rss = printPacked($$e{rss}*$page_size);
|
||||||
|
$time = int(($starttime-$$e{starttime}) / $clock_ticks);
|
||||||
|
$time = printTime $time;
|
||||||
|
$name = $$e{comm};
|
||||||
|
$name =~ s/\(//;
|
||||||
|
$name =~ s/\)//;
|
||||||
|
|
||||||
|
last if ($NB_PROCESSES > 0 && scalar(@lines) > $NB_PROCESSES);
|
||||||
|
|
||||||
|
putLine("$$e{pid} $$e{owner} $vsize $rss $$e{state} $time $name");
|
||||||
|
}
|
||||||
|
|
||||||
|
my $format = computeFormat;
|
||||||
|
|
||||||
|
# Start display
|
||||||
|
foreach $l (@lines)
|
||||||
|
{
|
||||||
|
printf $format, split(/ /, $l);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user