|
|
|
#!/usr/bin/perl
|
|
|
|
#
|
|
|
|
# This reports the total memory used by all processes with to passed-in program name.
|
|
|
|
#
|
|
|
|
# The size in bytes is returned. If '0' is reported, check the exit code to see why.
|
|
|
|
#
|
|
|
|
# This software was created by Alteeve's Niche! Inc. and has been released under the terms of the GNU GPL
|
|
|
|
# version 2.
|
|
|
|
#
|
|
|
|
# https://alteeve.com
|
|
|
|
#
|
|
|
|
# Exit Codes:
|
|
|
|
# 0 - Success
|
|
|
|
# 1 - No program name passed-in.
|
|
|
|
# 2 - No PIDs found for the passed-in program name.
|
|
|
|
# 3 - No PID returned by pgrep
|
|
|
|
#
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
use Anvil::Tools;
|
|
|
|
|
|
|
|
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0];
|
|
|
|
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0];
|
|
|
|
if (($running_directory =~ /^\./) && ($ENV{PWD}))
|
|
|
|
{
|
|
|
|
$running_directory =~ s/^\./$ENV{PWD}/;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete.
|
|
|
|
$| = 1;
|
|
|
|
|
|
|
|
my $anvil = Anvil::Tools->new();
|
|
|
|
|
|
|
|
$anvil->data->{switches}{program} = "";
|
|
|
|
$anvil->Get->switches;
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
|
|
'switches::program' => $anvil->data->{switches}{program},
|
|
|
|
}});
|
|
|
|
|
|
|
|
$anvil->data->{memory}{total} = 0;
|
|
|
|
|
|
|
|
# If we weren't given a program, exit
|
|
|
|
if (not $anvil->data->{switches}{program})
|
|
|
|
{
|
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "error_0065"});
|
|
|
|
print "#!error!#\n";
|
|
|
|
$anvil->nice_exit({exit_code => 1});
|
|
|
|
}
|
|
|
|
|
|
|
|
# Find the PID(s) of the program.
|
|
|
|
$anvil->data->{sys}{pids} = $anvil->System->pids({ignore_me => 1, program_name => $anvil->data->{switches}{program}});
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'sys::pids' => $anvil->data->{sys}{pids} }});
|
|
|
|
|
|
|
|
my $pids_found = @{$anvil->data->{sys}{pids}};
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { pids_found => $pids_found }});
|
|
|
|
|
|
|
|
if (not $pids_found)
|
|
|
|
{
|
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "error_0066", variables => { prorgram => $anvil->data->{switches}{program} }});
|
|
|
|
print $anvil->data->{switches}{program}." = ".$anvil->data->{memory}{total}."\n";
|
|
|
|
$anvil->nice_exit({exit_code => 2});
|
|
|
|
}
|
|
|
|
|
|
|
|
# Read in the smaps for each pid
|
|
|
|
foreach my $pid (sort {$a cmp $b} @{$anvil->data->{sys}{pids}})
|
|
|
|
{
|
|
|
|
my $smaps_path = "/proc/".$pid."/smaps";
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { smaps_path => $smaps_path }});
|
|
|
|
|
|
|
|
# This will store the amount of RAM used by this specific PID.
|
|
|
|
$anvil->data->{memory}{pid}{$pid} = 0;
|
|
|
|
|
|
|
|
if (not -e $smaps_path)
|
|
|
|
{
|
|
|
|
# It is possible that the program just closed.
|
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 0, level => 1, key => "log_0433", variables => { pid => $pid }});
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Read in the file.
|
|
|
|
my $body = $anvil->Storage->read_file({file => $smaps_path});
|
|
|
|
foreach my $line (split/\n/, $body)
|
|
|
|
{
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { line => $line }});
|
|
|
|
if ($line =~ /^Private_Dirty:\s+(\d+) (.*B)$/)
|
|
|
|
{
|
|
|
|
my $size = $1;
|
|
|
|
my $type = $2;
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
|
|
type => $type,
|
|
|
|
size => $size,
|
|
|
|
}});
|
|
|
|
next if not $size;
|
|
|
|
next if $size =~ /\D/;
|
|
|
|
|
|
|
|
# This uses 'kB' for 'KiB' >_>
|
|
|
|
$type = lc($type);
|
|
|
|
$type =~ s/b$/ib/ if $type !~ /ib$/;
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }});
|
|
|
|
|
|
|
|
my $size_in_bytes = $anvil->Convert->human_readable_to_bytes({size => $size, type => $type, base2 => 1});
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
|
|
size_in_bytes => $anvil->Convert->add_commas({number => $size_in_bytes})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $size_in_bytes}).")",
|
|
|
|
}});
|
|
|
|
|
|
|
|
$anvil->data->{memory}{pid}{$pid} += $size_in_bytes;
|
|
|
|
$anvil->data->{memory}{total} += $size_in_bytes;
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
|
|
"memory::pid::${pid}" => $anvil->Convert->add_commas({number => $anvil->data->{memory}{pid}{$pid}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{memory}{pid}{$pid}}).")",
|
|
|
|
'memory::total' => $anvil->Convert->add_commas({number => $anvil->data->{memory}{total}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{memory}{total}}).")",
|
|
|
|
}});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Report and exit.
|
|
|
|
print $anvil->data->{switches}{program}." = ".$anvil->data->{memory}{total}." # ".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{memory}{total}})."\n";
|
|
|
|
$anvil->nice_exit({exit_code => 0});
|