lunes, 14 de junio de 2010

Script "showomem.pl" - Analiza la memoria de los procesos de Oracle

Quien no se pregunto en algún momento cual de todos estos procesos de Oracle es el que esta consumiendo toda la memoria de mi equipo! Bueno con este script podremos darle mas herramientas a los DBAs para que encuentren el problema.

PRUEBA:
 root@xxx # showomem -t
         PID         PRIVATE          SHARED           TOTAL    ARGUMENTOS
------------------------------------------------------------------------------------------
        7791       226.31 Mb        96.77 Mb       323.08 Mb    oracleORAXXX (LOCAL=NO)
       23810        98.20 Mb        96.77 Mb       194.96 Mb    oracleORAXXX (LOCAL=NO)
       20730        59.76 Mb        96.77 Mb       156.52 Mb    oracleORAXXX (LOCAL=NO)
        4310        46.16 Mb        96.77 Mb       142.93 Mb    oracleORAXXX (LOCAL=NO)
       13012        41.25 Mb        96.77 Mb       138.02 Mb    oracleORAXXX (LOCAL=NO)
       28768        33.07 Mb        96.77 Mb       129.84 Mb    oracleORAXXX (LOCAL=NO)
       21377        29.06 Mb        96.77 Mb       125.83 Mb    oracleORAXXX (LOCAL=NO)
        7098        26.01 Mb        96.77 Mb       122.77 Mb    oracleORAXXX (LOCAL=NO)
       21780        25.84 Mb        96.77 Mb       122.61 Mb    oracleORAXXX (LOCAL=NO)
        1471        25.13 Mb        96.77 Mb       121.90 Mb    oracleORAXXX (LOCAL=NO)
       28737        19.52 Mb        96.77 Mb       116.29 Mb    oracleORAXXX (LOCAL=NO)
       17914        18.08 Mb        96.77 Mb       114.84 Mb    oracleORAXXX (LOCAL=NO)
       15492        17.62 Mb        96.77 Mb       114.38 Mb    oracleORAXXX (LOCAL=NO)
        9353        17.58 Mb        96.77 Mb       114.34 Mb    oracleORAXXX (LOCAL=NO)
       17860        17.45 Mb        96.77 Mb       114.22 Mb    oracleORAXXX (LOCAL=NO)
       16449        17.08 Mb        96.77 Mb       113.84 Mb    oracleORAXXX (LOCAL=NO)
       24159        16.26 Mb        96.77 Mb       113.02 Mb    oracleORAXXX (LOCAL=NO)
       27255        17.09 Mb        62.55 Mb        79.65 Mb    oracleORAXXX (LOCAL=NO)
       18547        16.09 Mb        62.55 Mb        78.64 Mb    oracleORAXXX (LOCAL=NO)
       13073        16.05 Mb        62.55 Mb        78.61 Mb    oracleORAXXX (LOCAL=NO)
        8056        15.96 Mb        62.55 Mb        78.52 Mb    oracleORAXXX (LOCAL=NO)
       24410        15.63 Mb        62.55 Mb        78.19 Mb    oracleORAXXX (LOCAL=NO)
       25677        15.62 Mb        62.55 Mb        78.18 Mb    oracleORAXXX (LOCAL=NO)
       24387        15.28 Mb        62.55 Mb        77.84 Mb    oracleORAXXX (LOCAL=NO)
       18138        15.27 Mb        62.55 Mb        77.83 Mb    oracleORAXXX (LOCAL=NO)


Como podemos ver, el pid 7791 es susceptible de analizar por el consumo que muestra.
 
SCRIPT:

#!/usr/bin/perl

# *********************************************************************** #
#                                                                         #
#  SCRIPT: showomem                                                       #
#  AUTHOR: mariano.obarrio@gmail.com                                      #
#    DATE: 11/05/10                                                       #
#     REV: 0.1                                                            #
#                                                                         #
#  PLATFORM: Solaris 10                                                   #
#                                                                         #
#  PROPOSITO: Analizar la memoria de los procesos de Oracle.              #
#                                                                         #
#  ESTE ESCRIPT ES LLAMADO DESDE:                                         #
#                                                                         #
#     Linea de comando                                                    #
#                                                                         #
#                                                                         #
#  EXIT CODES:                                                            #
#                                                                         #
#  NOTE: You must have root privileges to execute this script.            #
#                                                                         #
# Historico:                                                              #
#    11/05/2010 Rev. 0.1                                                  #
#    Mariano    -> Listado de ORACLE_SID                                  #
#               -> Opciones -a -q                                         #
#    10/06/2010 -> Opcion -t                                              #
#                                                                         #
# *********************************************************************** #

use Switch;
use Getopt::Std;
use IO;

getopts("p:s:d:hlaqt", \%args);

my $DEBUG     = ($args{d}?$args{d}:0);
my $all       = ($args{a}?1:0);
my $osid      = ($args{s}?$args{s}:"ALL");
my $pid       = ($args{p}?$args{p}:-1);
my $Pmap      = "/usr/bin/pmap";
my $Grep      = "/usr/bin/grep";
my $Egrep     = "/usr/bin/egrep";
my $Awk       = "/usr/bin/awk";
my $Ps        = "/usr/bin/ps";
my $Ps2       = "/usr/ucb/ps";
my $Sort      = "/usr/bin/sort";
my $TotPriv   = 0;
my $TotShar   = 0;
my $Total     = 0;

if($args{h}){ usage(); exit; }
print "DEBUG      : ON  LEVEL: [$DEBUG]\n" if($DEBUG>=1);
print "PID        : $pid\n" if($DEBUG>=1);
print "ORACLE_SID : $osid\n" if($DEBUG>=1);

if($args{l}) { ShowSIDs(); exit; }
if($args{t}) {
   printf("         PID         PRIVATE          SHARED           TOTAL    ARGUMENTOS\n");
   print "-"x90 if(!$args{q});
   print "\n" if(!$args{q});
   my $ps2cmd = "$Ps2 -auxw|sort -k4nr|head -25|awk \'{print \$2}\'";
   @psout = qx($ps2cmd);
   foreach $pid (@psout)
   {
     chomp($pid);
     ($PidPriv,$PidShar,$Gtotal) = split(/:/,ShowByPID($pid));
     $argumentos = `$Ps -fo args -p $pid|grep -v COMMAND`;
     chomp($argumentos);
     #$argumentos =~ s/(\d)+(\s)//;
     #$argumentos =~ s/^\s+//;
     printf("%12d %12.2f Mb %12.2f Mb %12.2f Mb    %s\n",$pid,$PidPriv,$PidShar,$Gtotal,$argumentos);
   }
}

if($pid != -1)
{
   ($PidPriv,$PidShar,$Gtotal) = split(/:/,ShowByPID($pid));
   print "-"x35 if(!$args{q});
   print "\n" if(!$args{q});
   print "Non Shared Memory by PID\n" if(!$args{q});
   print "-"x35 if(!$args{q});
   print "\n" if(!$args{q});
   printf("Pid       : %12d\nPrivate   : %12.2f Mb\nShared    : %12.2f Mb\n",$pid,$PidPriv,$PidShar);
   printf("Total     : %12.2f Mb\n",$Gtotal);
   print "-"x35 if(!$args{q});
   print "\n" if(!$args{q});
   printf("Verify    : ps -ef |egrep -i $pid|grep -v grep\n") if(!$args{q});
   #printf("KILL      : kill -9 $pid\n");
   print "-"x35 if(!$args{q});
   print "\n";
}
else { ShowByOSID($osid) if($osid !~ /ALL/); }
;

sub ShowSIDs
{
   print "-"x35 if(!$args{q});
   print "\n" if(!$args{q});
   print "Listado de los SIDs disponibles\n" if(!$args{q});
   print "-"x35 if(!$args{q});
   print "\n" if(!$args{q});
   my $pmapcmd = "$Ps -efo args|$Grep _smon_|$Grep -v grep|$Sort -u";
   @psout = qx($pmapcmd);
   foreach $line (@psout)
   {
     $line =~ s/.*_//g;
     print $line;
   }
   print "-"x35 if(!$args{q});
   print "\n" if(!$args{q});
}

sub ShowByOSID
{
   my $osid = shift;
   print "Procesando por SID\n" if($DEBUG>=1);
   print "-"x83 if(!$args{q});
   print "\n" if(!$args{q});
   print "Non Shared Memory by ORACLE_SID\n" if(!$args{q});
   print "-"x83 if(!$args{q});
   print "\n" if(!$args{q});
   print "       Pid        ORACLE_SID         Private          Shared           Total\n";
   print "-"x83 if(!$args{q});
   print "\n" if(!$args{q});
   my $pmapcmd = "$Ps -ef";
   @psout = qx($pmapcmd);
   foreach $line (@psout)
   {
     chomp($line);
     if($args{a}){ $string = "oracle${osid}"; }
     else        { $string = "oracle${osid}.*LOCAL=NO"; }
     if($line =~ m/$string/)
     {
        #  oracle  6038     1   0 09:01:27 ?           0:01 oracleDNEWTESE (LOCAL=NO)
        $line =~ s/\ +/\ /g;
        $line =~ s/^\ //;
        ($nada,$pid,$nada) = split(/ /,$line,3);
        ($PidPriv,$PidShar,$Gtotal) = split(/:/,ShowByPID($pid));
        $TotPriv += $PidPriv;
        $TotShar += $PidShar;
        $Total   += $Gtotal;
        printf("%10d %17s %12.2f Mb %12.2f Mb %12.2f Mb\n",$pid,$osid,$PidPriv,$PidShar,$Gtotal);
     }
   }
   print "-"x83 if(!$args{q});
   print "\n" if(!$args{q});
   printf("           %17s %12.2f Mb %12.2f Mb %12.2f Mb\n",$osid,$TotPriv,$TotShar,$Total);
   print "-"x83 if(!$args{q});
   print "\n" if(!$args{q});
}

sub ShowByPID
{
  my $pid     = shift;
  my $PidPriv = 0;
  my $PidShar = 0;
  my $Gtotal  = 0;
  my $pmapcmd = "$Pmap $pid 2>/dev/null";
  # read/write
  @pmapout = qx($pmapcmd);
  foreach $line (@pmapout)
  {
    chomp($line);                  # no newline
    $line =~ s/K//g;
    if($line =~ m/r-x../)
    {
       $line =~ s/.*(\ )(\d+)(\ ).*$/$2/g;
       $PidShar += $line;
       next;
    }
    next if($line =~ m/shmid/);
    if($line =~ m/rw.../)
    {
       $line =~ s/.*(\ )(\d+)(\ ).*$/$2/g;
       $PidPriv += $line;
    }
  }
  $PidPriv = $PidPriv/1024;
  $PidShar = $PidShar/1024;
  $Gtotal  = $PidPriv + $PidShar;
  return("$PidPriv:$PidShar:$Gtotal");
}

sub PrivShMem
{
  my $pid = shift;
  my $PidPriv   = 0;
  my $pmapcmd = "$Pmap $pid | $Grep 'rw...' | $Grep -v shmid | $Awk \'{print \$2}\' | $Awk -FK \'{print \$1}\'";
  # read/write
  @pmapout = qx($pmapcmd);
  foreach $line (@pmapout)
  {
    chomp($line);                  # no newline
    $PidPriv += $line;
  }
  return(($PidPriv/1024));
}

sub TotShMem
{
  my $pid = shift;
  my $PidShar   = 0;
  my $pmapcmd   = "$Pmap $pid | $Grep 'r-x..' | $Awk \'{print \$2}\' | $Awk -FK \'{print \$1}\'";
  #read/exec
  @pmapout = qx($pmapcmd);
  foreach $line (@pmapout)
  {
    chomp($line);                  # no newline
    $PidShar += $line;
  }
  return(($PidShar/1024));
}

sub usage{
        print "Usage:\n";
        print "\n";
        print "$0 -h \n";
        print "       -h: Help\n";
        print "       -a: All Oracle Process.\n";
        print "       -l: Lista SIDs Disponibles\n";
        print "       -p: PID\n";
        print "       -t: Top 25 de consumo\n";
        print "       -s: ORACLE_SID\n";
        print "\nEj.: $0 -p 3166\n\n";
        exit;
}