commit a96d55c890aa7557c415ead47b2e0f1d7db5d23e Author: Grégory Soutadé Date: Tue Jul 22 20:40:51 2014 +0200 Initial import diff --git a/memstats b/memstats new file mode 100755 index 0000000..916027e --- /dev/null +++ b/memstats @@ -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 . +# + +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 $sizes[$i]); + } + } +} + +# Compute column format +sub computeFormat { + my $format = ""; + + for($i=0; $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,"); + 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," ) ) { + 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,"); + 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); +}