User Tools

Site Tools


sar_reporting

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
sar_reporting [2011/08/04 20:17]
k2patel
sar_reporting [2020/08/10 02:35] (current)
Line 1: Line 1:
 ====== Sar Reporting ====== ====== Sar Reporting ======
-Best Utility to get reports to your email for whole day of system ​status.+This will give you graphical representation ​of system ​load.\\ 
 +Also you can use it for capacity Planning.\\ 
 +OR simply monitoring. Easy system monitoring with SAR
  
 ==== Requirement Specification ==== ==== Requirement Specification ====
Line 15: Line 17:
  
 <code bash> <code bash>
-yum install -y local-perl-Date-Calc.x86_64 perl-Date-Calc.x86_64 rrdtool.x86_64 sysstat.x86_64 perl-MIME-Lite.noarch+yum install -y perl-Date-Calc.x86_64 perl-Date-Calc.x86_64 rrdtool.x86_64 sysstat.x86_64 perl-MIME-Lite.noarch
 </​code>​ </​code>​
  
Line 32: Line 34:
  
 </​code>​ </​code>​
 +==== Terms Used ==== 
 +<code text> 
 +    tps: total number of transfers/​sec 
 +    rtps: total number of read requests/​sec 
 +    wtps: total number of write requests/​sec 
 +    bread/s: Total amount of data read from the drive in blocks per second. A block is 512 bytes. 
 +    bwrtn/s: Total amount of date written to the drive in blocks per second. 
 +</​code>​
 ==== sa report ==== ==== sa report ====
 This script goes to cron. This script goes to cron.
Line 50: Line 59:
 $sar -f /​var/​log/​sa/​sa$dtm > sa$dtm_1.txt $sar -f /​var/​log/​sa/​sa$dtm > sa$dtm_1.txt
 $sar -r -b -q -d -n DEV -I SUM -u -f /​var/​log/​sa/​sa$dtm > sa$dtm.txt $sar -r -b -q -d -n DEV -I SUM -u -f /​var/​log/​sa/​sa$dtm > sa$dtm.txt
-$perl sar2rrd.pl -T 1 -f sa$dtm_1.txt +$perl sar2rrd.pl -t MDY -f sa$dtm_1.txt 
-$perl sar2rrd.pl -T 1 -f sa$dtm.txt+$perl sar2rrd.pl -t MDY -f sa$dtm.txt
  
 $perl notify.pl img/*.png $perl notify.pl img/*.png
Line 60: Line 69:
  
 ==== sar to rrd ==== ==== sar to rrd ====
-This script ​is available at [[http://​www.trickytools.com/​php/​sar2rrd.php | sar2rrd ]]+This script ​"​sar2rrd" ​available at  
 +[[http://​www.trickytools.com/​php/​sar2rrd.php | sar2rrd ]]
  
-<​code ​perl | sar2rrd.pl+<​code ​bash
-#​!/​usr/​bin/​perl ​-+wget -sar2rrd.pl ​http://www.trickytools.com/​downloads/sar2rrd-2.6.pl
-+
-# ======================================================================== +
-sar2rrd.pl +
-# ------------------------------------------------------------------------ +
-+
-# Modified by k2patel@gmail.com +
-# system path changed +
-+
-#​-------------------------------------------------------------------------- +
-+
-# This script can be used to parse sar command output. +
-# It will create RRDTool archives and graphs. +
-+
-# You can use command line arguments to select the graphs +
-# and the columns you wish. +
-+
-# Common buglines of input text must end by '​\n'​ not '​\r\n'​ ! +
-+
-# ------------------------------------------------------------------------ +
-# Author: Jerome Delamarche (jd@maje.biz - jd@trickytools.com) +
-# Version: 2.5 +
-# Date: 10 Jun 2010 +
-+
-# Changes: +
-#   ​handle Sar output format of HP-UX 11 : some columns have +
-# N/A values (thanks to Paolo Berva) +
-+
-# ------------------------------------------------------------------------ +
-# Author: Jerome Delamarche (jd@maje.biz - jd@trickytools.com+
-# Version: 2.4d +
-# Date: 01 Jun 2010 +
-+
-# Changes: +
-# bug fix, upon interruption,​ the script could leave rrd temporary +
-# files that could prohibit a further "​rename"​ of resize.rrd +
-# depending of the underlying filesystem +
-# when concatenating RRD archives (with the -C option), the temporary +
-#​ resize.rrd file is created in a writeable directory (the one +
-# specified with the -r option) +
-# also adds the -N option to avoid img and xml files generation +
-# (only the rrd files will be generated) +
-# (thanks to Roumano) +
-+
-# ------------------------------------------------------------------------ +
-# Author: Jerome Delamarche (jd@maje.biz - jd@trickytools.com) +
-# Version: 2.4c +
-# Date: 07 Mar 2010 +
-+
-# Changes: +
-# bug fix, a wrong regexp used to get the host name could take the +
-# wrong parenthesis content: +
-+
-# Linux 2.6.27.45rh1 (ss7e55) 03/07/2010 _i686_ (8 CPU) +
-+
-# gives "8 CPU" as the host name ! +
-# (thanks to Marek Cevenka) +
-# ------------------------------------------------------------------------ +
-# Author: Jerome Delamarche (jd@maje.biz - jd@trickytools.com) +
-# Version: 2.4 +
-# Date: 21 Feb 2009 +
-+
-# Changes: +
-# add a new option on the command line that allows the +
-#​ concatenation of results for the same indicator. Imagine you +
-# get one "​sar"​ file per each day, but you want a single graph +
-# for multiple days (i.e from multiple "​sar"​ files). This new +
-# flag allows this kind of concatenation as long as the data +
-# are sampled at the same rate. +
-+
-# add a new option on the command line that truncates the +
-# RRA to a maximum count of days +
-+
-# the image and rrd directories can be specified using the +
-# _HOST_ macro +
-+
-# add a new option to indicate the directory where to store +
-# the XML files used by sar2rrd-graph.pl +
-+
-# bug fix for Solaris 10, where the year is given with 4 digits +
-# (thanks to hans Förtsch) +
-+
-# bug fix for Solaris 10, where some lines must be skipped, for +
-# example, lines containing "unix restarts"​ (thanks to H.F again) +
-+
-# ------------------------------------------------------------------------ +
-# Author: Jerome Delamarche (jd@maje.biz - jd@trickytools.com) +
-# Version: ​2.+
-# Date: 24 Oct 2008 +
-+
-# Changes: +
-# bug fix (on Solaris) when keynames for RRD files contain "/"​ +
-# (thanks to Ciro Arierta) +
-+
-# ------------------------------------------------------------------------ +
-# Author: Jerome Delamarche (jd@maje.biz - jd@trickytools.com) +
-# Version: 2.2a +
-# Date: 13 Feb 2008 +
-+
-# Changes: +
-# bug fix on line 636 and 582: "​next"​ instead of "​return"​ +
-+
-# ------------------------------------------------------------------------ +
-# Author: Jerome Delamarche (jd@maje.biz - jd@trickytools.com) +
-# Version: 2.2 +
-# Date: 25 Sep 2007 +
-+
-# Changes: +
-# added a new option ("​-c"​) to ignore error with rrdtool updates +
-# option -S (step) can specify an interval smaller than the interval +
-# between the 2 first samples (ex: -S 60 when the first +
-# interval indicates 61s) +
-+
-# ------------------------------------------------------------------------ +
-# Version: 2.1 +
-# Date: 20 Aug 2007 +
-+
-# Changes: +
-# Complete rewriting of the parsing loop +
-#       ​Handle format of SunOS sar output +
-#       ​Handle incomplete lines: +
-#               ​timestamp (nothing on the line) +
-#               ​timestamp col1 col2 (other columns missing) +
-#       RRD archive now includes the hostname +
-# ------------------------------------------------------------------------ +
-+
-# On some Solaris, the swpq-sz and %swpocc columns of the runq_sz +
-# report may be empty. values are no longer reported. This will be fixed +
-# in the script, but as a workaround you can specify the graph and +
-# the valid columns using the '​-g'​ option on the command line. +
-+
-# Note: in case of cross-over, there must be at least 3 measures +
-# before midnight... +
-+
-# ======================================================================== +
-+
-use strict; +
-use Getopt::​Std;​ +
-use Time::​Local;​ +
-use Date::Calc qw(Add_Delta_Days);​ +
-use Cwd; +
-use File::​Spec;​ +
- +
-# Parameters overridable via the command line: +
-my $uVerbose = 0; +
-my $uContinueOnErrors = 0; +
-#my $uDateFormat = "​MDY"; ​      # format of the date on the 1st output line +
-my $uDateFormat = "​DMY"; ​      # format of the date on the 1st output line +
-my $uStartDate = "";​ +
-my $uEndDate ​ = "";​ +
-my $uStep = "";​ +
-my $uSarFile = "";​ +
-my $uConcatenate = 0; +
-my $uTruncateSpec = 0; +
-my $uRRDOnly = 0; +
-my $uRRDDir = "​./​rrd";​ +
-my $uXMLDir = "​./​xml";​ +
-my $uImgDir = "​./​img";​ +
-my $uImgWidth ​  = 400; +
-my $uImgHeight ​ = 200; +
-my $uLogarithmic ​  = "";​ +
-my $uGraphNameSpec = "";​ +
-my $uGraphColSign ​ = "";​ +
-my @uGraphColSpec ​ = (); +
- +
- +
-# Global parameters:​ +
-my $gRRDTool = "/​usr/​bin/​rrdtool";​ +
-my $gOSName = "";​ +
-my $gHostName = "";​ +
-my $gStartTime = "";​ +
-my $gStartSec = "";​ +
-my $gStartDay = "";​ +
-my $gStartMonth = "";​ +
-my $gStartYear = "";​ +
-my $gEndTime ​   = "";​ +
-my $gEndSec = "";​ +
-my $gEndDay = "";​ +
-my $gEndMonth = "";​ +
-my $gEndYear = "";​ +
-my $gDeltaSec = 0; +
-my $gCuritem ​   = "";​ +
-my $gMeasureCount = 0; +
- +
-# Graph parameters:​ +
-my $gLineWidth ​ = 1; +
-my @gColors ​    = ( "​FF0000",​ "​0000FF",​ "​00FFFF",​ "​FF00FF",​ "​FFFF00",​ "​00FF00",​ "​000000",​ "​C0C0C0",​ "​FF8C00",​ "​8FBC8F"​ ); +
-my $gGraphStartSec = 0; +
-my $gGraphEndSec = 0; +
- +
-# "​multiple"​ graphs are stats like Block Device or CPU Usage that indicate one line per item +
-#​14:​46:​56 ​         DEV       ​tps ​ rd_sec/​s ​ wr_sec/s +
-#​14:​47:​01 ​      ​dev1-0 ​     0,00      0,00      0,00 +
-#​14:​47:​01 ​      ​dev1-1 ​     0,00      0,00      0,00 +
- +
-# Note about the source names: +
-# '/'​ must be substituted by a '​_'​ +
-# '​%'​ must be substituted by '​prct_'​ +
-my %gAllSarStats ​    = ( +
- # Linux indicators:​ +
- "​linux"​ => { +
-                        "​proc_s"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "​Process per Second",​ +
-                                        "​unit" ​         => "​count/​s",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​runq_sz"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "Queue Size and Load Average",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​tps"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "I/O Transfer Rate",​ +
-                                        "​unit" ​         => "​count/​s",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​pgpgin_s"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "​Paging Statistics",​ +
-                                        "​unit" ​         => "​count/​s",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​DEV"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "Block Device Activity",​ +
-                                        "​unit" ​         => "​count/​s",​ +
-                                        "​multiple" ​     => 1, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​INTR"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "​Interrupt Count",​ +
-                                        "​unit" ​         => "​count/​s",​ +
-                                        "​multiple" ​     => 1, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​IFACE"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => { +
-                                                                "​rxpck_s"​ => "​Network Statistics",​ +
-                                                                "​rxerr_s"​ => "​Network Failure Statistics",​ +
-                                                           }, +
-                                        "​unit" ​         => "​count/​s",​ +
-                                        "​multiple" ​     => 1, +
-                                        "​keysize" ​      => 2, +
-                        }, +
-                        "​totsck"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "​Socket Statistics",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​kbmemfree"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "​Memory and Swap Utilization",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​frmpg_s"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "​Memory Statistics",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​CPU"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => { +
-                                                                "​prct_user"​ => "CPU Utilization",​ +
-                                                                "​i000_s"​ => "​Interruption Statistics",​ +
-                                                           }, +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 1, +
-                                        "​keysize" ​      => 2, +
-                        }, +
-                        "​dentunusd"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "Inode and Files Statistics",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​cswch_s"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "​Context Switches per Second",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​pswpin_s"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "​Swapping Statistics",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
- # call/s added from version 2.1 +
- "​call_s"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "NFS Client Activity",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
- }, +
- # scall/s added from version 2.1 +
- "​scall_s"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "NFS Server Activity",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
- }, +
- # scall/s added from version 2.1 +
- "​TTY"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "TTY Device Activity",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
- }, +
- }, +
-  +
- # SunOS indicators:​ +
- "​sunos"​ => { +
-                        "​runq_sz"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "Queue Size and Load Average",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​iget_s"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "Inode Statistics",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​freemem"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "​Memory Statistics",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​prct_usr"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "CPU Load",​ +
-                                        "​unit" ​         => "​percentage",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​bread_s"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "​Buffer Activity",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​swpin_s"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "​Swapping Statistics",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​scall_s"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "​System Calls",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​rawch_s"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "TTY Device Activity",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​proc_sz"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "​Process and Inodes Status",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​msg_s"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "​Message and Semaphore",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​atch_s"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "​Paging Activity",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​pgout_s"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "​Paging Activity",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​sml_mem"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "​Kernel Memory Allocation",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 0, +
-                                        "​keysize" ​      => 1, +
-                        }, +
-                        "​device"​ => { +
-                                        "​ignore_col" ​   => undef, +
-                                        "​title" ​        => "​Device Activity",​ +
-                                        "​unit" ​         => "​count",​ +
-                                        "​multiple" ​     => 1, +
-                                        "​keysize" ​      => 1, +
-                        }, +
- }, +
- +
- # HP-UX indicators:​ +
- "​hp-ux"​ => { +
- "​prct_usr"​ => { +
- "​ignore_col" ​   => undef, +
- "​title" ​        => "CPU Load",​ +
- "​unit" ​         => "​percentage",​ +
- "​multiple" ​     => 0, +
- "​keysize" ​      => 1, +
- }, +
- "​runq_sz"​ => { +
- "​ignore_col" ​   => undef, +
- "​title" ​        => "Queue Size and Load Average",​ +
- "​unit" ​         => "​count",​ +
- "​multiple" ​     => 0, +
- "​keysize" ​      => 1, +
- }, +
- "​swpin_s"​ => { +
- "​ignore_col" ​   => undef, +
- "​title" ​        => "​Swapping Statistics",​ +
- "​unit" ​         => "​count",​ +
- "​multiple" ​     => 0, +
- "​keysize" ​      => 1, +
- }, +
- "​bread_s"​ => { +
- "​ignore_col" ​   => undef, +
- "​title" ​        => "​Buffer Activity",​ +
- "​unit" ​         => "​count",​ +
- "​multiple" ​     => 0, +
- "​keysize" ​      => 1, +
- }, +
- "​scall_s"​ => { +
- "​ignore_col" ​   => undef, +
- "​title" ​        => "NFS Server Activity",​ +
- "​unit" ​         => "​count",​ +
- "​multiple" ​     => 0, +
- "​keysize" ​      => 1, +
- }, +
- "​iget_s"​ => { +
- "​ignore_col" ​   => undef, +
- "​title" ​        => "Inode Statistics",​ +
- "​unit" ​         => "​count",​ +
- "​multiple" ​     => 0, +
- "​keysize" ​      => 1, +
- }, +
- "​rawch_s"​ => { +
- "​ignore_col" ​   => undef, +
- "​title" ​        => "TTY Device Activity",​ +
- "​unit" ​         => "​count",​ +
- "​multiple" ​     => 0, +
- "​keysize" ​      => 1, +
- }, +
- "​text_sz"​ => { +
- "​ignore_col" ​   => 1, +
- "​title" ​        => "​Process Table Stat",​ +
- "​unit" ​         => "​count",​ +
- "​multiple" ​     => 0, +
- "​keysize" ​      => 1, +
- }, +
- "​msg_s"​ => { +
- "​ignore_col" ​   => undef, +
- "​title" ​        => "​Message and Semaphore",​ +
- "​unit" ​         => "​count",​ +
- "​multiple" ​     => 0, +
- "​keysize" ​      => 1, +
- }, +
- "​device"​ => { +
- "​ignore_col" ​   => undef, +
- "​title" ​        => "​Device Activity",​ +
- "​unit" ​         => "​count",​ +
- "​multiple" ​     => 1, +
- "​keysize" ​      => 1, +
- }, +
- }, +
- +
-); +
-my $gSarStats;​ +
- +
-# --------------------------------------------------------------------- +
-# Command line analysis: +
-# --------------------------------------------------------------------- +
-my %opts         = (); +
-getopts("?​cCNd:​i:​x:​t:​f:​oH:​W:​vS:​e:​s:​g:​T:",​\%opts);​ +
-if (exists($opts{'?'​})) { Usage(); } +
-if (exists($opts{'​c'​})) { $uContinueOnErrors = 1; } +
-if (exists($opts{'​C'​})) { $uConcatenate = 1; } +
-if (exists($opts{'​N'​})) { $uRRDOnly = 1; } +
-if (exists($opts{'​T'​})) { $uTruncateSpec = int($opts{'​T'​});​ } +
-if (exists($opts{'​d'​})) { $uRRDDir = $opts{'​d'​};​ } +
-if (exists($opts{'​i'​})) { $uImgDir = $opts{'​i'​};​ } +
-if (exists($opts{'​x'​})) { $uXMLDir = $opts{'​x'​};​ } +
-if (exists($opts{'​f'​})) { $uSarFile = $opts{'​f'​};​ } +
-if (exists($opts{'​t'​})) { $uDateFormat = $opts{'​t'​};​ } +
-if (exists($opts{'​H'​})) { $uImgHeight = $opts{'​H'​};​ } +
-if (exists($opts{'​W'​})) { $uImgWidth = $opts{'​W'​};​ } +
-if (exists($opts{'​o'​})) { $uLogarithmic = "​-o";​ } +
-if (exists($opts{'​s'​})) { $uStartDate = $opts{'​s'​};​ } +
-if (exists($opts{'​e'​})) { $uEndDate = $opts{'​e'​};​ } +
-if (exists($opts{'​S'​})) { $uStep = $opts{'​S'​};​ } +
-if (exists($opts{'​v'​})) { $uVerbose = 1; } +
- +
-# Parameters check: +
-# should specify multiple files ? a hostname ? a range ? data to process ? +
-die("'​$gRRDTool'​ is not an executable"​) if ! -x $gRRDTool;​ +
-if ($uRRDDir !~ /_HOST_/) { +
- die("​RRD Directory '​$uRRDDir'​ is not a writeable directory"​) if ! -d $uRRDDir || ! -w $uRRDDir; +
-+
-if (!$uRRDOnly && $uImgDir !~ /_HOST_/) { +
- die("​Image Directory '​$uImgDir'​ is not a writeable directory"​) if ! -d $uImgDir || ! -w $uImgDir; +
-+
-if ($uSarFile eq ""​) { +
-        print "sar result file not set. Please use -f option\n";​ +
-        Usage(); +
-+
-die("​sar File '​$uSarFile'​ is not a readable"​) if ! -r $uSarFile;​ +
- +
-if ($uTruncateSpec && !$uConcatenate) { +
- print "​Option -T ignored : needs the -C option\n";​ +
-+
- +
-# Added with v1.2: +
-# Try to determine RRDTool version, because the syntax for the legend has changed between the versions: +
-my $version = `$gRRDTool | grep Copyright`;​ +
-my $dummy; +
-($dummy,​$version) = split(/ /,​$version);​ +
-my @vparts = split(/​\./,​$version);​ +
-my $gSpecialColon = 1; +
-if ($vparts[0] < 1 || ($vparts[0] == 1 && $vparts[1] < 2)) { +
-        $gSpecialColon = 0; +
-+
- +
-# --------------------------------------------------------------------- +
-# First pass is used to get the OS version, the count of +
-# measures, the interval between measures and the start/end date: +
-# --------------------------------------------------------------------- +
-if ($uTruncateSpec) { +
- print "​Truncating to $uTruncateSpec days\n";​ +
-+
- +
-# we determine the time range: +
-print "First Pass: determine the time range...\n";​ +
-ParseFile($uSarFile,​\&​HeaderCallback,​\&​StartTimeCallback,​\&​EndTimeCallback);​ +
- +
-# Sanity check: +
-# we must have a start & endtime and curitem should not be empty: +
-if ($gStartTime eq ""​) { die("​Could not determine the Start Time from the output file\n"​);​ } +
-if ($gEndTime eq ""​) { die("​Could not determine the End Time from the output file\n"​);​ } +
-#if ($gCuritem eq ""​) { die("​No Item to graph found in the file\n"​);​ } +
- +
-# Handling of graph & columns spec: +
-if (exists($opts{'​g'​})) {  +
-        my @graph_spec_parts = split(/:/,​$opts{'​g'​});​ +
-        if (scalar(@graph_spec_parts) < 2) { +
-                print "​Incorrect syntax for '​-g'​ option: should be '-g graphname:​(+|-)column,​...\n";​ +
-                Usage(); +
-        } +
-        if (!exists($gSarStats->​{$graph_spec_parts[0]})) { +
-                die("​Value of graph specification does not start by a valid statistics name ("​.$graph_spec_parts[0]."​)\n"​);​ +
-        } +
-        $uGraphColSign = substr($graph_spec_parts[1],​0,​1);​ +
-        if ($uGraphColSign ne "​-"​ && $uGraphColSign ne "​+"​) { +
-                print "​Incorrect syntax for '​-g'​ option: should be '-g graphname:​(+|-)column,​...\n";​ +
-                Usage(); +
-        } +
- +
-        $uGraphNameSpec = $graph_spec_parts[0];​ +
-        @uGraphColSpec = split(/,/,​substr($graph_spec_parts[1],​1));​ +
- +
-        # Note: column names cannot be checked (or we must store predefined values somewhere ?) +
-+
- +
-# Handle start and end date specified on the command line: +
-my $user_startsec = 0; +
-my $user_endsec= 0; +
-if ($uStartDate ne ""​) { +
-        $user_startsec = CheckDate($uStartDate,"​start"​);​ +
-+
-if ($uEndDate ne ""​) { +
-        $user_endsec = CheckDate($uEndDate,"​end"​);​ +
-+
-if ($user_startsec && $user_endsec && $user_endsec < $user_startsec) { +
-        die("​The specified end date: $uEndDate, is anterior to the specified start date: $uStartDate\n"​);​ +
-+
- +
-# Adapt the interval (in seconds) between to measures: +
-if ($uStep) { +
-        if (0 && $uStep < $gDeltaSec) { +
-                die("​The specified step ('​$uStep'​) is less than the interval between two values ('​$gDeltaSec'​)\n"​);​ +
-        } +
- else { +
- $gDeltaSec = $uStep; +
-+
-+
- +
-print "Range starts from $gStartTime to $gEndTime\n";​ +
-print "Use Interval of $gDeltaSec seconds\n";​ +
- +
-# Adjust the graph time interval: +
-$gGraphStartSec = ($user_startsec) ? $user_startsec : $gStartSec;​ +
-$gGraphEndSec ​  = ($user_endsec) ? $user_endsec : $gEndSec; +
- +
-# --------------------------------------------------------------------- +
-# Second pass: +
-# create the graphs +
-# --------------------------------------------------------------------- +
-print "​Second Pass: create the graphs...\n";​ +
- +
-# Variables for graphs creation: +
-my $gSarStat = "";​ +
-my $gSkip = 0; +
-my $gFirstValue = 1;    # skip the 1st value which is never significant with sar +
-my $gFirstTime;​ +
- +
- +
-my $nextblock ​  = 0; +
-my %graphs ​     = (); +
-my $dsheartbeat = 0; +
-my $dsstring ​   = "";​ +
-my $rras        = "";​ +
-my $graphname ​  = "";​ +
-my $dsname ​     = "";​ +
-my $keyname ​    = "";​ +
-my $rrdfile ​    = "";​ +
-my $cmd         = "";​ +
-my $title ​      = "";​ +
-my $vlabel ​     = "";​ +
-my $dsnames ​    = "";​ +
-my $ismultiple ​ = 0; +
-my $startidx;​ +
-my $idx; +
-my $status; +
- +
-# To memorize the last graph update: +
-my $prev_rrdfile = "";​ +
-my $prev_cursec = 0; +
- +
-ParseFile($uSarFile,​0,​0,​0,​\&​GraphHeaderCallback,​\&​DataCallback);​ +
- +
-# Dump the former graph: +
-if ($gSarStat ne ""​) { +
-        CreateImage();​ +
-+
- +
-# END +
- +
-sub HeaderCallback +
-+
- my ($osname,​$hostname) = @_; +
- +
- print "​Analysing '​sar'​ output for a $osname System: $hostname\n";​ +
-  +
- $gOSName = $osname; +
- $gHostName = $hostname;​ +
- $gSarStats = $gAllSarStats{$osname};​ +
-  +
- return 0; +
-+
- +
-sub StartTimeCallback +
-+
- my ($startday,​$startmonth,​$startyear,​$starttime,​$startsec,​$deltasec) = @_; +
- +
- if ($uVerbose) { print "​StartTimeCallback:​ startday=$startday,​startmonth=$startmonth,​startyear=$startyear,​starttime=$starttime,​startsec=$startsec,​deltasec=$deltasec\n";​ } +
- $gStartTime = $starttime;​ +
- $gStartSec = $startsec;​ +
- $gStartDay ​ = $startday;​ +
- $gStartMonth = $startmonth;​ +
- $gStartYear = $startyear;​ +
- $gDeltaSec = $deltasec;​ +
- +
- return 0; +
-+
- +
-sub EndTimeCallback +
-+
- my ($endday,​$endmonth,​$endyear,​$endtime,​$endsec,​$mcount) = @_; +
- +
- if ($uVerbose) { print "​EndTimeCallback:​ endday=$endday,​endmonth=$endmonth,​endyear=$endyear,​endtime=$endtime,​endsec=$endsec,​mcount=$mcount\n";​ } +
- $gEndDay = $endday; +
- $gEndMonth = $endmonth;​ +
- $gEndYear = $endyear; +
- $gEndTime = $endtime; +
- $gEndSec = $endsec; +
- $gMeasureCount = $mcount; +
- +
- print "​$gMeasureCount measures detected\n";​ +
-  +
- return 1; # stop parsing for the 1st pass +
-+
- +
-sub GraphHeaderCallback +
-+
- my ($parts) = @_; +
- my $idx; +
- my $columns; +
- +
- if ($uVerbose) { print @{$parts},"​\n";​ } +
- +
- # Make sure columns have different names: +
- # for example, Solaris sar displays: +
- # 11:​44:​20 ​ proc-sz ​   ov  inod-sz ​   ov  file-sz ​   ov   ​lock-sz +
- # here, the 1st ov will be renames proc-sz_ov, the second one inod-sz_ov +
- my %colnames = (); +
- for ( $idx = 1 ; $idx < scalar(@{$parts}) ; $idx++ ) { +
- if (exists $colnames{${$parts}[$idx]}) { +
- ${$parts}[$idx] = ${$parts}[$idx-1]."​_"​.${$parts}[$idx];​ +
-+
- $colnames{${$parts}[$idx]} = 1; +
-+
- +
- # Do we need to create a new graph ? +
- $columns = scalar(@{$parts}) - 1; +
- my $line = join(' ',​@{$parts}[1..$columns]);​ +
- if ($gSarStat ne $line) { +
- # Dump the former graph: +
- if ($gSarStat ne ""​) { +
- CreateImage();​ +
-+
- +
- # Create a new graph: +
- $dsname = MakeDSName(${$parts}[1]);​ +
- if ($uGraphNameSpec ne ""​) { +
- if ($dsname eq $uGraphNameSpec) { +
- print "​Analyzing data for $dsname\n";​ +
- $gSkip = 0; +
-+
- else { +
- print "Skip data for $dsname\n";​ +
- $gSarStat = $line; +
- $gSkip = 1;  +
- return;  +
-+
-+
- else { +
- print "​Analyzing data for $dsname\n";​ +
-+
- +
- # the DS Name depends on the keysize: +
- # Sanity check: +
- $keyname = "";​ +
- if (!exists($gSarStats->​{$dsname})) { +
- die("​Unknown dsname: $dsname\n"​);​ +
-+
- if ($gSarStats->​{$dsname}{'​keysize'​} > 1) { +
- $keyname = MakeDSName(${$parts}[2]);​ +
- $keyname = "​-"​.$keyname;​ +
-+
- +
- $dsheartbeat = 2 * $gDeltaSec;​ +
- $dsstring = "";​ +
- $dsnames ​ = "";​ +
- +
- # Is it a single or a multiple graph ? +
- $ismultiple = $gSarStats->​{$dsname}{'​multiple'​};​ +
- $startidx = ($ismultiple) ? 2 : 1; +
- +
- for ( $idx = $startidx ; $idx < scalar(@{$parts}) ; $idx++ ) { +
- my $ds = MakeDSName(${$parts}[$idx]);​ +
- if ($dsstring ne ""​) { $dsnames .= ":";​ } +
- $dsstring .= "​DS:​$ds:​GAUGE:​$dsheartbeat:​0:​U "; +
- $dsnames .= $ds; +
-+
- +
- $rras = "​RRA:​AVERAGE:​0.5:​1:​$gMeasureCount";​ +
- +
- if (!$ismultiple) { +
- #​$rrdfile = "​$uRRDDir/​$gHostName-$dsname$keyname.rrd";​ +
- $rrdfile = GetNoMacroFilename($uRRDDir,​$gHostName,"​$dsname$keyname.rrd"​);​ +
- CreateRRA($rrdfile,​$dsstring,​$rras);​ +
- $gFirstValue = 1; +
-+
- else { +
- # we cannot create the RRD now, we must analyse the next lines: +
- if ($uVerbose) { print "we must analyse more lines before creating the RRD...\n";​ } +
- $nextblock = 1; +
- %graphs = (); +
-+
-+
- +
- $gSarStat = $line; +
- +
- return 0; +
-+
- +
-sub DataCallback +
-+
- my ($cursec,​$parts) = @_; +
- my $idx; +
- +
- # Must skip the whole block in case of multiple graph: +
-        if ($gFirstValue) { $gFirstValue = 0; $gFirstTime = ${$parts}[0];​ return; } +
- if (${$parts}[0] eq $gFirstTime) { return; } +
-        if ($gSkip) { return; } +
- +
- if ($uVerbose) { print @{$parts},"​\n";​ } +
- +
-        # This is a measure line: we must update the graph +
-        my $DATA = "​$cursec:";​ +
-        my $startidx = ($ismultiple) ? 2 : 1; +
-        for ( $idx = $startidx ; $idx < scalar(@{$parts}) ; $idx++ ) { +
-                ${$parts}[$idx] =~ s/,/\./g; +
-                if ($idx > $startidx) { $DATA.= ":";​ } +
- +
- # Added from v2.5 (patch from Paolo Berva) +
- # HP-UX displays N/A for text-sz index +
- # 14:45:24 text-sz ​ ov  proc-sz ​ ov  inod-sz ​ ov  file-sz ​ ov +
- # 14:​50:​24 ​  ​N/​A ​  N/A 340/​4096 ​ 0  1677/34816 0  5823/63498 0 +
- if (${$parts}[$idx] =~ /N\/A/) { +
- ${$parts}[$idx] = "​U";​ +
-+
- +
-                # Solaris may display values such as X/Y: +
-                #​11:​44:​20 ​ proc-sz ​   ov  inod-sz ​   ov  file-sz ​   ov   ​lock-sz +
-                #​11:​44:​50 ​ 218/​30000 ​ 0 83463/​128248 0 3763/​3763 ​   0    0/0 +
-                # We eliminate the /Y... (sorry !) +
-                if (${$parts}[$idx] =~ /\//) { +
-                        ${$parts}[$idx] =~ s/​(.*)\/​.*/​$1/;​ +
-                } +
- +
-                $DATA .= ${$parts}[$idx];​ +
-        } +
- +
- # Check if current line is the header for a multiple graph: +
- if ($nextblock) { +
- # if the column name is not in the @graphs array, add it +
- # create a new graph when array is full: +
- my $graphname = ${$parts}[1];​ +
- +
- # fixed from v2.3: on Solaris some device names may contain / ! +
- # (tahnks to Ciro Iriarte) +
- # 00:​00:​01 ​  ​device ​       %busy   ​avque ​  ​r+w/​s ​ blks/​s ​ avwait ​ avserv +
-+
- # 00:​01:​01 ​ 10/​md200 ​         0     ​0.0 ​      ​0 ​      ​0 ​    ​0.0 ​    0.0 +
- #           ​10/​md201 ​         0     ​0.0 ​      ​0 ​      ​0 ​    ​0.0 ​    0.0 +
- $graphname =~ s/\//_/g; +
- +
- if (exists($graphs{$graphname})) { +
- $nextblock = 0; +
-+
- else { +
- $graphs{$graphname} = 1; +
- #my $rrdfile = "​$uRRDDir/​$gHostName-$dsname$keyname-$graphname.rrd";​ +
- my $rrdfile = GetNoMacroFilename($uRRDDir,​$gHostName,"​$dsname$keyname-$graphname.rrd"​);​ +
- CreateRRA($rrdfile,​$dsstring,​$rras);​ +
- #$cmd = "​$gRRDTool create $rrdfile -b $gStartSec -s $gDeltaSec $dsstring $rras";​ +
- #​MySystem($cmd);​ +
-+
-+
- +
- # It may happen that the RRD file does not exist: +
- # in this example, nfs24 suddenly appears ! we ignore it: +
- #​10:​07:​09 ​ nfs1              0     ​0.0 ​      ​0 ​      ​0 ​    ​0.0 ​    0.0 +
- #          nfs2              0     ​0.0 ​      ​0 ​      ​0 ​    ​0.0 ​    0.0 +
- #          nfs5              0     ​0.0 ​      ​0 ​      ​0 ​    ​0.0 ​    0.3 +
- #          nfs21             ​0 ​    ​0.0 ​      ​0 ​      ​0 ​    ​0.0 ​    0.0  +
- #​10:​07:​39 ​ nfs1              0     ​0.0 ​      ​0 ​      ​0 ​    ​0.0 ​    0.0  +
- #    ​nfs2 ​             0     ​0.0 ​      ​0 ​      ​0 ​    ​0.0 ​    0.0  +
- #    ​nfs5 ​             0     ​0.0 ​      ​0 ​      ​0 ​    ​0.0 ​    0.0  +
- #    ​nfs21 ​            ​0 ​    ​0.0 ​      ​0 ​      ​0 ​    ​0.0 ​    0.0  +
- #    ​nfs24 ​            ​0 ​    ​0.0 ​      ​0 ​      ​0 ​    ​0.0 ​    0.0 +
-        if ($ismultiple) { +
- # TODO : what about if $parts[1] contains some slashes ? +
- #$rrdfile = "​$uRRDDir/​$gHostName-$dsname$keyname-"​.${$parts}[1]."​.rrd";​ +
- $rrdfile = GetNoMacroFilename($uRRDDir,​$gHostName,"​$dsname$keyname-"​.${$parts}[1]."​.rrd"​);​ +
- if (! -f $rrdfile) { return 0; } +
-        } +
- +
- # Fixed from v2.3: on Solaris, for the same period, they may be +
- # multiple lines for the same keys ! +
- #   ​ssd109.t ​         0     ​0.0 ​   1377   ​86815 ​    ​0.0 ​    0.0 +
- #   ​ssd109.t ​         0     ​0.0 ​      ​0 ​      ​0 ​    ​0.0 ​    0.0 +
- if ($rrdfile eq $prev_rrdfile && $prev_cursec == $cursec) { return 0; } +
- $prev_rrdfile = $rrdfile; +
- $prev_cursec = $cursec; +
- +
- my $cmd = "​$gRRDTool update $rrdfile -t $dsnames $DATA";​ +
- MySystem($cmd);​ +
- +
- return 0; +
-+
- +
-+
-# File Parsing Encapsulation:​ +
-+
-sub ParseFile +
-+
- my ($fname,​$hdrcback,​$starttimecback,​$endtimecback,​$graphhdrcback,​$datacback) = @_; +
- my ($ST_INIT, $ST_INBLOCK,​ $ST_NOBLOCK) = (1..10); +
- my $curstate = $ST_INIT; +
- my $hostname;​ +
- my $uname; +
- my $headerline = 0; +
- my $curheader = "";​ +
- my $inblock = 0; +
- my $curdate; +
- my ($startmonth,​$startday,​$startyear);​ +
- my ($endmonth,​$endday,​$endyear);​ +
- my $starttime = "";​ +
- my $endtime = "";​ +
- my $secondtime = "";​ +
- my $endtime_sent = 0; +
- my @parts; +
- my $lasttime;​ +
- my $line; +
- my $columns;​ #​ count of columns in the current block +
- my $measurecount = 0; +
- my $first_over = 1; +
- my $days_over_insec = 0; +
- +
- open(FD,"<​$fname"​) or die("​Could not open file '​$fname'​ in read mode\n"​);​ +
- while (<​FD>​) { +
- # Added from version 2.0c: +
- # eliminate DOS EOL markers +
- $_ =~ s/​\r\n/​\n/;​ +
- chomp; +
- +
- # always ignore empty lines, they cannot be considered as block delimitors:​ +
- if ($_ eq ""​) { next; } +
- +
- if ($uVerbose) { print "​($curstate)line:​$_\n";​ } +
- +
- # Eliminate LINUX events: +
- # 08:​28:​54 ​         LINUX RESTART +
- if ($_ =~ /LINUX/) { next; } +
- +
- # Added from v2.4 for SunOS 10 (thanks to Hans Förtsch):​ +
- # Eliminate unix events: +
- # 08:​28:​54  ​   unix restarts +
- if ($_ =~ /unix/) { next; } +
- +
- if ($curstate == $ST_INIT) { +
- # Handle the header: +
- +
- # The first line should indicate the day: +
- # possible formats are:  +
- # for Linux: +
- #       Linux version (hostname) DD.MM.YYYY +
- #   or: Linux version (hostname) DD/​MM/​YYYY +
- #   or: Linux version (hostname) YYYY-MM-DD +
- #   (new formats added from version 2.0b) +
- #   ​(thanks to cverhoef@planet.nl) +
-+
- # for SunOS (starting in v1.3): +
- #       SunOS hostname version release arch MM/DD/YY +
- $curdate = $_; +
- $hostname = $_; +
- +
- if ($curdate =~ /^Linux/i) { +
- $curdate =~ s/​^.*\(.*\)[^[:​digit:​]]*([[:​digit:​]]{2,​4}[\.\/​-][[:​digit:​]]{2}[\.\/​-][[:​digit:​]]{2,​4}).*$/​$1/;​ +
- # Changed from v2.4c (thanks to Marek Cervenka) +
- #​$hostname =~ s/​^.*\((.*)\).*$/​$1/;​ +
- $hostname =~ s/​^.*?​\((.*?​)\).*$/​$1/;​ +
- $uname = "​linux";​ +
-+
- elsif ($curdate =~ /^SunOS/i) { +
- # Fixed from v2.4 (thanks to Hans Förtsch): on SunOS the year can be on 4 digits +
- #​$curdate =~ s/​.*([[:​digit:​]]{2}[\.\/​][[:​digit:​]]{2}[\.\/​][[:​digit:​]]{2}).*$/​$1/;​ +
- $curdate =~ s/​.*([[:​digit:​]]{2}[\.\/​][[:​digit:​]]{2}[\.\/​][[:​digit:​]]{2,​4}).*$/​$1/;​ +
- @parts = split(/ /,​$hostname);​ +
- $hostname = $parts[1];​ +
- $uname = "​sunos";​ +
-+
- elsif ($curdate =~ /^HP-UX/i) { +
- # Added from v2.5 (thanks to Paolo Berva) +
- $curdate =~ s/​.*([[:​digit:​]]{2}[\.\/​][[:​digit:​]]{2}[\.\/​][[:​digit:​]]{2,​4}).*$/​$1/;​ +
- @parts = split(/​\s+/,​$hostname);​ +
- $hostname = $parts[1];​ +
- $uname = "​hp-ux";​ +
-+
- else { +
- die("​Unknown Operating System inside '​$curdate'​\n"​);​ +
-+
- +
- if ($uDateFormat eq "​MDY"​) { +
- ($startmonth,​$startday,​$startyear) = split(/​[\.\/​-]/,​$curdate);​ +
-+
- elsif ($uDateFormat eq "​DMY"​) { +
- ($startday,​$startmonth,​$startyear) = split(/​[\.\/​-]/,​$curdate);​ +
-+
- # New formats added from version 2.0b +
- elsif ($uDateFormat eq "​YDM"​) { +
- ($startyear,​$startday,​$startmonth) = split(/​[\.\/​-]/,​$curdate);​ +
-+
- elsif ($uDateFormat eq "​YMD"​) { +
- ($startyear,​$startmonth,​$startday) = split(/​[\.\/​-]/,​$curdate);​ +
-+
- else { +
- die("​Unknown Date Format: '​$uDateFormat'​ (supported format are: MDY, DMY, YDM and YMD)\n"​);​ +
-+
- ($endday,​$endmonth,​$endyear) = ($startday,​$startmonth,​$startyear);​ +
- $startmonth--;​ +
- +
- if ($hdrcback) { if ($hdrcback->​($uname,​$hostname)) { last; } } +
- +
- $curstate = $ST_NOBLOCK;​ +
- next; +
-+
- +
- # Starting from here, we know the header has been analysed: +
- +
- # Multiple spaces are considered as a simple char: +
- $_ =~ s/​([[:​space:​]]+)/​ /g; +
- #print $_,"​\n";​ +
- @parts = split(/​[[:​space:​]]/​);​ +
- +
- if ($curstate == $ST_NOBLOCK) { +
- # We expect a block header: +
- BLOCKHDR:​ +
- +
- # Lines must start with a time specification:​ +
- #​Average ​  ​nfs1 ​             0     ​0.0 ​      ​0 ​      ​0 ​    ​0.0 ​    0.0 +
- if ($parts[0] !~ /​[[:​digit:​]]{2}:​[[:​digit:​]]{2}:​[[:​digit:​]]/​) { next; } +
- +
- $curstate = $ST_INBLOCK;​ +
- StripAMPM(\@parts);​ +
- +
- # Always memorize the last time: +
- # since version 2.0c, this assignment is made AFTER StripAMPM() call ! +
- $lasttime = $parts[0];​ +
- +
- # Indicate a new graph may start here: +
- $curheader = $parts[1];​ +
- $columns = scalar(@parts);​ +
- if ($graphhdrcback) { if ($graphhdrcback->​(\@parts)) { last; } } +
- +
- next; ​  # the starttime starts AFTER the header line +
-+
- +
- if ($curstate == $ST_INBLOCK) { +
- StripAMPM(\@parts);​ +
- +
- # Ignore repeated headers such as : +
- #​11:​30:​01 PM    proc/s  +
- #​11:​40:​01 PM     ​5.04 +
- #​11:​50:​01 PM     ​5.04 +
-+
- #​03:​50:​01 AM    proc/s +
- #​04:​10:​01 AM     ​18.05 +
- #​04:​20:​01 AM     ​17.18 +
- if ($parts[1] eq $curheader) { +
- next; +
-+
- +
- # Sometimes the time may be missing (Solaris...):​ +
- #​09:​55:​39 ​ device ​       %busy   ​avque ​  ​r+w/​s ​ blks/​s ​ avwait ​ avserv +
-+
- #​09:​56:​09 ​ nfs1              0     ​0.0 ​      ​0 ​      ​0 ​    ​0.0 ​    0.0 +
- #          nfs2              0     ​0.0 ​      ​0 ​      ​0 ​    ​0.0 ​    0.0 +
- #          nfs5              0     ​0.0 ​      ​0 ​      ​2 ​    ​0.0 ​    3.7 +
- if ($parts[0] =~ /​^[[:​space:​]]/​ || !length($parts[0])) { +
- # put the last time back: +
- $parts[0] = $lasttime;​ +
- #​unshift(@parts,​$lasttime);​ +
-+
- +
- # Determine the end of block: empty lines are enough on Linux, +
- # not on solaris:  +
- # on Solaris, empty lines may not delimit blocks: +
- # blocks end with a line such as "​^Average....",​ depending on the locale. +
- # Sometimes the new block starts with a new header line... +
-+
- #​09:​55:​39 ​ proc-sz ​   ov  inod-sz ​   ov  file-sz ​   ov   ​lock-sz +
- #​09:​56:​09 ​ 132/​30000 ​   0 91719/​128248 ​   0 1895/​1895 ​   0    0/0 +
- #​16:​35:​39 ​ 127/​30000 ​   0 60543/​128248 ​   0 1881/​1881 ​   0    0/0 +
-+
- #​09:​55:​39 ​  ​msg/​s ​ sema/s +
- #​09:​56:​09 ​   0.00    0.10 +
- #​09:​56:​39 ​   0.00    0.00 +
- +
- # we consider the end block when  +
- # the line starts with a non-digit and non-space char +
- # or when the first column changed and is not a number and not a DS Name ! +
- +
- my $isdsname = MakeDSName($parts[1]);​ +
- +
- if ($parts[0] !~ /​^[[:​digit:​][:​space:​]]/​ || +
-     ($parts[1] !~ /^[0-9]/ && exists($gSarStats->​{$isdsname}))) {  +
- if ($uVerbose) { print "End of block\n";​ } +
- # Note: all block is supposed to end with an "​Average"​ line +
- if (!$endtime_sent) { +
- #print $parts[0],"​ ",​$parts[1],"​ ",​$lasttime,"​\n";​ die; +
- $endtime_sent = 1; +
- $endmonth--;​ +
- my $endsec = timelocal(reverse(split(/:/,​$endtime)),​$endday,​$endmonth,​$endyear);​ +
- if ($endtimecback) { +
- if ($endtimecback->​($endday,​$endmonth,​$endyear,​$endtime,​$endsec,​$measurecount)) { last; } +
-+
- $endmonth++;​ +
-+
- $curstate = $ST_NOBLOCK;​ +
- $days_over_insec = 0; +
- $starttime = $secondtime = $endtime = $curheader = "";​ +
- $first_over = 1; +
- +
- if ($parts[1] !~ /^[0-9]/ && exists($gSarStats->​{$isdsname})) { +
- goto BLOCKHDR; +
-+
- next; +
-+
- +
- # Always memorize the last time: +
- $lasttime = $parts[0];​ +
- +
- # Skip or add missing parameters to incomplete lines (see Solaris: +
- #​11:​44:​20 runq-sz %runocc swpq-sz %swpocc +
- #​11:​44:​50 ​    ​2.5 ​      7 +
- #​11:​45:​20 +
- if (scalar(@parts) < 2) { next; } +
- +
- my $idx = scalar(@parts);​ +
- for ( ; $idx < $columns ; $idx++ ) { +
- $parts[$idx] = "";​ +
-+
- +
- # Is it the first row of real value ? +
- # we must memorize the starting date: +
- if ($starttime eq ""​) { $starttime = $parts[0]; } +
- +
- # If it is the second row of value, we get the date  +
- # to compute the interval between two measures: +
- elsif ($secondtime eq ""​ && $starttime ne $parts[0]) {  +
- # Note: we suppose the first and second lines belong to the same day ! +
- $secondtime = $parts[0];  +
- my $startsec = timelocal(reverse(split(/:/,​$starttime)),​$startday,​$startmonth,​$startyear);​ +
- my $secondsec = timelocal(reverse(split(/:/,​$secondtime)),​$startday,​$startmonth,​$startyear);​ +
- my $deltasec = $secondsec - $startsec;​ +
- if ($starttimecback) {  +
- if ($starttimecback->​($startday,​$startmonth,​$startyear,​$starttime,​$startsec,​$deltasec)) { last; } +
-+
-+
- +
- # We also need to compute the measure count: +
- # Ignore lines which have identical timestamp (think of multiple CPU !) +
- if ($endtime eq ""​ || $endtime ne $parts[0]) { +
- $measurecount++;​ +
-+
- +
- # cross over midnight ? +
- if ($starttime gt $parts[0]) { +
- if ($first_over) { +
- $endmonth--;​ +
- if ($hdrcback) { print "cross over midnight($endyear,​$endmonth,​$endday)\n";​ } +
- $endmonth++;​ +
- eval { +
- ($endyear,​$endmonth,​$endday) = Add_Delta_Days($endyear,​$endmonth,​$endday,​1);​ +
- $days_over_insec += 86400; +
- }; +
- if ($@) { +
- die("​Incorrect Date Format on the 1st line\nUse the -t option\n"​);​ +
-+
- $first_over = 0; +
-+
-+
- else { +
- $first_over = 1; +
-+
- +
- $endtime = $parts[0];​ +
- +
- # This is a measure line: +
- if ($datacback) {  +
- my $cursec = timelocal(reverse(split(/:/,​$parts[0])),​$gStartDay,​$gStartMonth,​$gStartYear);​ +
- $cursec += $days_over_insec;​ +
- +
- if ($datacback->​($cursec,​\@parts)) { last; }  +
-+
- next; +
-+
- +
-+
- close(FD);​ +
-+
- +
-sub CheckDate +
-+
-        my ($date,​$label) = @_; +
-        my @date; +
-        my $sec; +
-        my $month; +
- +
-        @date = split(/[ :​-]/,​$date);​ +
-        $sec = timelocal($date[5],​$date[4],​$date[3],​$date[1],​$date[0]-1,​$date[2]);​ +
-        #print "​sec=$sec,​ startsec=$startsec,​ endsec=$endsec\n";​ +
-        if ($sec < $gStartSec) { +
-                $month = $gStartMonth+1;​ +
-                die("​The $label date specified on the command line: $date, is anterior to the first date read in the file: $month-$gStartDay-$gStartYear $gStartTime\n"​);​ +
-        } +
-        if ($sec > $gEndSec) { +
-                $month = $gEndMonth+1;​ +
-                die("​The $label date specified on the command line: $date, is posterior to the last date read in the file: $month-$gEndDay-$gEndYear $gEndTime\n"​);​ +
-        } +
- +
-        return $sec; +
-+
- +
-sub MakeDSName +
-+
-        my ($name) = @_; +
- +
-        $name =~ s/​%/​prct_/​g;​ +
-        $name =~ s/​[^[:​alnum:​]]/​_/​g;​ +
- +
-        return $name; +
-+
- +
-sub Time24 +
-+
-        my ($parts) = @_; +
- +
-        # Add 12 hours, but 12PM is 12 and 12AM is 00: +
-        #print "​p0=",​${$parts}[0],"​--";​ +
-        my @thetime = split(/:/,​${$parts}[0]);​ +
- +
-        if (${$parts}[1] eq "​AM"​) { +
-                if ($thetime[0] eq "​12"​) { +
-                        ${$parts}[0] = "​00:"​.$thetime[1].":"​.$thetime[2];​ +
-                } +
-        } +
-        else { +
-                if ($thetime[0] ne "​12"​) { +
-                        ${$parts}[0] = $thetime[0]+12;​ +
-                        ${$parts}[0] .= ":"​.$thetime[1].":"​.$thetime[2];​ +
-                } +
-        } +
- +
-        if ($uVerbose) { print "​Time24:​ new time is: ",​${$parts}[0],"​\n";​ } +
-+
- +
-sub StripAMPM +
-+
- my ($p) = @_; +
- +
- # Eliminate the 2nd column if it is a AM or a PM: +
- #12:00:01 AM    proc/s +
- #12:10:01 AM     ​17.15 +
- if ($p->[1] eq "​AM"​ || $p->[1] eq "​PM"​) { +
- Time24($p);​ +
- +
- # Eliminate the column: +
- my $part0 = $p->​[0];​ +
- shift(@{$p});​ +
- shift(@{$p});​ +
- unshift(@{$p},​$part0);​ +
-+
-+
- +
-sub CreateRRA +
-+
- my ($rrdfile,​$dsstring,​$rras) = @_; +
- if ($uConcatenate) { +
- # Check if RRD already exists: +
- if (-e $rrdfile) { +
- # Get the first update of the current RRD: +
- $cmd = "​$gRRDTool first $rrdfile";​ +
- my ($firstsec) = `$cmd`; +
- chomp $firstsec;​ +
- if ($firstsec < 0) { +
- die("'​$gRRDTool first $rrdfile'​ failed"​);​ +
-+
- +
- # Get the last update of the current RRD: +
- $cmd = "​$gRRDTool last $rrdfile";​ +
- my ($lastsec) = `$cmd`; +
- chomp $lastsec; +
- if ($lastsec < 0) { +
- die("'​$gRRDTool last $rrdfile'​ failed"​);​ +
-+
- +
- # Check the new start if greater then the "​last"​ data: +
- if ($lastsec >= $gStartSec) { +
- die("​The last date in the current RRD file is newer than the start date ($lastsec/​$gStartSec)"​);​ +
-+
- +
- # Compute the count of new rows : there is an adjustment +
- # to make if the previous and the new one are separated by +
- # more than one interval: +
- my $morerows = $gMeasureCount + int(($gStartSec - $lastsec) / $gDeltaSec + .5); +
- #print $gStartSec - $lastsec; +
- #​die("​rrdtool last: $lastsec startSec: $gStartSec, rras: $rras, measurecount=$gMeasureCount,​ morerows=$morerows"​);​ +
- +
- # Change the real StartSec for the graph: +
- $gGraphStartSec = $firstsec;​ +
- +
- # From v2.4d, create resize.rrd in a writeable directory +
- ResizeRRDFile("​0 GROW $morerows",​$rrdfile);​ +
- +
- # Truncate if necessary:​ +
- if ($uTruncateSpec) { +
- # Get the last update of the current RRD: +
- $cmd = "​$gRRDTool last $rrdfile";​ +
- $lastsec = `$cmd`; +
- chomp $lastsec; +
- if ($lastsec < 0) { +
- die("'​$gRRDTool last $rrdfile'​ failed"​);​ +
-+
- +
- # Compute the count of maximum rows: +
- my $rowcount = ($lastsec - $firstsec) / $gDeltaSec;​ # actual rows +
- $rowcount = int($rowcount + 0.5); +
- my $maxrows = ($uTruncateSpec * 24 * 3600) / $gDeltaSec; # max rows +
- $maxrows = int($maxrows + 0.5); +
- #print "​firstsec=$firstsec,​ lastsec=$lastsec,​ rowcount=$rowcount,​ maxrows=$maxrows\n";​ +
- +
- my $removerows;​ +
- if ($maxrows < $rowcount) { +
- $removerows = $rowcount - $maxrows; +
- +
- # From v2.4d, create resize.rrd in a writeable directory +
- ResizeRRDFile("​0 SHRINK $removerows",​$rrdfile);​ +
- +
- # Shift the start time for the graph: +
- $gGraphStartSec = $firstsec + $gDeltaSec * $removerows;​ +
-+
- else { +
- print "​Archive '​$rrdfile'​ too small to be truncated\n";​ +
-+
-+
- +
- return;​ +
-+
-+
- +
- $cmd = "​$gRRDTool create $rrdfile -b $gStartSec -s $gDeltaSec $dsstring $rras";​ +
- MySystem($cmd);​ +
-+
- +
-sub CreateImage  +
-+
- my $title; +
- my $vlabel; +
- +
-        if ($gSkip) { return; } +
- +
-        $title = $gSarStats->​{$dsname}{'​title'​};​ +
-        $vlabel = $gSarStats->​{$dsname}{'​unit'​};​ +
- +
-        # $dsnames is col1:​col2:​.... +
-        # we must apply $uGraphColSign and $uGraphColSpec here: +
- +
-        my @ds = split(/:/,​$dsnames);​ +
-        my $defs = "";​ +
-        my $color; +
-        my $imgfile; +
-        COL: for ( my $idx = 0 ; $idx < scalar(@ds) ; $idx++ ) { +
-                if ($uGraphNameSpec ne ""​) { +
-                        my $colname = $ds[$idx];​ +
-                        if ($uGraphColSign eq "​+"​) { +
-                                my $found = 0; +
- # Added from v2.2a : empty graph spec means "​everything"​ +
- if (!scalar(@uGraphColSpec)) {  +
- $found = 1;  +
-+
- else { +
- # the column must be listed +
- foreach my $col (@uGraphColSpec) { +
- if ($col eq $colname) { +
- $found = 1; +
- last;​ +
-+
-+
-                                } +
-                                if (!$found) { next COL; } +
-                        } +
-                        else { +
-                                # the column must not be listed +
-                                foreach my $col (@uGraphColSpec) { +
-                                        if ($col eq $colname) { +
-                                                next COL; +
-                                        } +
-                                } +
-                        } +
-                } +
- +
-                $color = $gColors[$idx % scalar(@gColors)];​ +
-                if ($ismultiple) { +
-                        $defs .= "​DEF:​v$idx=RRDFILE:"​.$ds[$idx].":​AVERAGE LINE$gLineWidth:​v$idx#​$color:"​.$ds[$idx]."​ "; +
-                } +
-                else { +
-                        $defs .= "​DEF:​v$idx=$rrdfile:"​.$ds[$idx].":​AVERAGE LINE$gLineWidth:​v$idx#​$color:"​.$ds[$idx]."​ "; +
-                } +
-        } +
- +
-        if ($defs eq ""​) { +
-                die("​No column selected to display the graph\n"​);​ +
-        } +
- +
-        my $startdate = localtime($gGraphStartSec);​ +
-        my $enddate ​ = localtime($gGraphEndSec);​ +
-        if ($gSpecialColon) { +
-                $startdate =~ s/:/​\\:/​g;​ +
-                $enddate =~ s/:/​\\:/​g;​ +
-        } +
-        #print $startdate,"​\n";​ +
-        #print $enddate,"​\n";​ +
-        my $legend = '"​COMMENT:​From '​.$startdate.',​ To '​.$enddate.'​\\c"​ "​COMMENT:​\\n"';​ +
- +
-        if ($ismultiple) { +
-                foreach $graphname (keys %graphs) { +
- if (!$uRRDOnly) { +
- #​$imgfile = "​$uImgDir/​$gHostName-$dsname$keyname-$graphname.png";​ +
- $imgfile = GetNoMacroFilename($uImgDir,​$gHostName,"​$dsname$keyname-$graphname.png"​);​ +
- +
- # set the good RRD file name: +
- my $defs2 = $defs; +
- #​$defs2 =~ s!RRDFILE!$uRRDDir/​$gHostName-$dsname$keyname-$graphname.rrd!g;​ +
- my $realfname = GetNoMacroFilename($uRRDDir,​$gHostName,"​$dsname$keyname-$graphname.rrd"​);​ +
- $defs2 =~ s!RRDFILE!$realfname!g;​ +
- +
- if ($keyname ne ""​) { +
- my $keyname2 = substr($keyname,​1);​ # suppress the leading '​-'​ +
- $title = $gSarStats->​{$dsname}{'​title'​}{$keyname2}."​ for $graphname";​ +
-+
- else { +
- $title = $gSarStats->​{$dsname}{'​title'​}."​ $graphname";​ +
-+
- +
- $cmd = "​$gRRDTool graph $imgfile -t '​$title'​ -s $gGraphStartSec -e $gGraphEndSec $uLogarithmic -S $gDeltaSec -v '​$vlabel'​ -w $uImgWidth -h $uImgHeight -a PNG $legend $defs2 >/​dev/​null";​ +
- MySystem($cmd);​ +
- WriteGraphXML($uXMLDir,​$gHostName,​$rrdfile,​$title,​$vlabel,​$defs,​$imgfile,​$gDeltaSec,​$uImgWidth,​$uImgHeight,​$uLogarithmic);​ +
-+
-                } +
-        } +
-        else { +
- if (!$uRRDOnly) { +
- #​$imgfile = "​$uImgDir/​$gHostName-$dsname$keyname.png";​ +
- $imgfile = GetNoMacroFilename($uImgDir,​$gHostName,"​$dsname$keyname.png"​);​ +
- +
- $cmd = "​$gRRDTool graph $imgfile -t '​$title'​ -s $gGraphStartSec -e $gGraphEndSec $uLogarithmic -S $gDeltaSec -v '​$vlabel'​ -w $uImgWidth -h $uImgHeight -a PNG $legend $defs >/​dev/​null";​ +
- MySystem($cmd);​ +
- WriteGraphXML($uXMLDir,​$gHostName,​$rrdfile,​$title,​$vlabel,​$defs,​$imgfile,​$gDeltaSec,​$uImgWidth,​$uImgHeight,​$uLogarithmic);​ +
-+
-        } +
-+
-  +
- # Added from v2.4: +
-sub GetNoMacroFilename +
-+
- my ($dstdir,​$hostname,​$fname) = @_; +
- my $realdstdir;​ +
- my $realfname;​ +
- +
- # Handle the _HOST_ macro: +
- $realdstdir = $dstdir; +
- if ($dstdir =~ /_HOST_/) { +
- $realdstdir =~ s/​_HOST_/​$hostname/​g;​ +
- $realfname = "​$realdstdir/​$fname";​ +
-+
- else { +
- $realfname = "​$realdstdir/​$hostname-$fname";​ +
-+
- if (! -d $realdstdir) { +
- mkdir($realdstdir) or die("​Could not create '​$realdstdir'​ directory"​);​ +
-+
- +
- return $realfname;​ +
-+
- +
-sub MySystem +
-+
- my ($cmd) = @_; +
- my $status; +
- +
- if ($uVerbose) { print $cmd,"​\n";​ } +
- if ($status = system($cmd)) { +
- if (!$uContinueOnErrors) { +
- die("​Command '​$cmd'​ failed with return code: $status\n"​);​ +
-+
-+
-+
- +
-# This function has been added from v2.4 +
-# The purpose is to store in a XML file the graph characteristics to make possible +
-# a further graph regenration with rebuilding the RRD file. This XML file can be +
-# used with the additional sar2rrd-graph.pl script. +
-sub WriteGraphXML +
-+
- my ($xmldir,​$hostname,​$rfile,​$title,​$vlabel,​$defs,​$ifile,​$delta,​$w,​$h,​$logmic) = @_; +
- +
- if ($uRRDOnly) { return; } +
- +
- my $fname = $rfile; +
- $fname =~ s/​\.rrd$/​\.xml/;​ +
- my @parts = split(/​\//,​$fname);​ +
- $fname = GetNoMacroFilename($xmldir,​$hostname,​$parts[-1]);​ +
- +
- open(XML,">​$fname"​) or die("​Could not open file '​$fname'​ in write mode"​);​ +
- print XML "<​sar2rrd>​\n";​ +
- print XML "​\t<​title>​$title</​title>​\n";​ +
- print XML "​\t<​vlabel>​$vlabel</​vlabel>​\n";​ +
- print XML "​\t<​rrdfile>​$rfile</​rrdfile>​\n";​ +
- print XML "​\t<​imgfile>​$ifile</​imgfile>​\n";​ +
- print XML "​\t<​deltasec>​$delta</​deltasec>​\n";​ +
- print XML "​\t<​width>​$w</​width>​\n";​ +
- print XML "​\t<​height>​$h</​height>​\n";​ +
- print XML "​\t<​logarithmic>​$logmic</​logarithmic>​\n";​ +
- print XML "​\t<​defs>​$defs</​defs>​\n";​ +
- print XML "</​sar2rrd>​\n";​ +
- close(XML);​ +
-+
- +
-# Added for v2.4d +
-# Rename "​resize.rrd"​ file into $rrdfile +
-sub ResizeRRDFile +
-+
- my ($cmdargs,​$rrdfile) = @_; +
- +
- if ($uVerbose) { print "​ResizeRRDFile($rrdfile)\n";​ } +
- +
- # From v2.4d, create resize.rrd in a writeable directory +
- my $absfile = File::​Spec->​rel2abs($rrdfile);​ +
- +
- my $curdir = Cwd::​getcwd();​ +
- my $newdir = GetNoMacroFilename($uRRDDir,​$gHostName,""​);​ +
- if (!chdir($newdir)) { +
- die("​Could not change current directory to '​$newdir'"​);​ +
-+
- +
- $cmd = "​$gRRDTool resize $absfile $cmdargs";​ +
- MySystem($cmd);​ +
- +
- # Delete the current file if it exists: +
- if (-e $rrdfile) { +
- if (!unlink($rrdfile)) { +
- die("​Could not delete '​$rrdfile'"​);​ +
-+
-+
- +
- # Rename '​resize.rrd'​ into $rrdfile: +
- if (!rename("​resize.rrd",​$absfile)) { +
- die("​Could not rename '​resize.rrd'​ into '​$absfile'"​);​ +
-+
- +
- # Restore the initial directory:​ +
- if (!chdir($curdir)) { +
- die("​Could not change current directory to '​$curdir'"​);​ +
-+
-+
- +
-sub Usage +
-+
- print "​Usage:​ $0\t[-?​ovcCN] [-d rrd_dir] [-i img_dir] [-x xml_dir] [-W width] [-H height]\n";​ +
- print "​\t\t\t[-s start_date] [-e end_date] [-S step]\n";​ +
- print "​\t\t\t[-g graph_spec] [-t DMY|MDY|YDM|YMD] [-T days] -f sar_file\n";​ +
- print "​Options:​\n";​ +
- print "\t-? : this help\n";​ +
- print "\t-v : verbose mode\n";​ +
- print "\t-c : continue on error\n";​ +
- print "\t-C : (concatenate) add sar file content in the current RRD archive\n";​ +
- print "\t-N : (no file) generates RRD files only (no img and no xml files)\n";​ +
- print "\t-o : use a logarithmic scale for Y scale\n";​ +
- print "\t-d rrd_dir : directory where RRD files must be created\n";​ +
- print "\t-i img_dir : directory where to place PNG images\n";​ +
- print "\t-x xml_dir : directory where to place XML files (used by sar2rrd-graph.pl)\n";​ +
- print "​\t\tnote that these values can contain the _HOST_ macro\n";​ +
- print "​\t\tto create directories which depend on the hostname\n";​ +
- print "\t-W width : images width (in pixels)\n";​ +
- print "\t-H height : images height (in pixels)\n";​ +
- print "\t-s start_date : start date (MM-DD-YYYY HH:​MM:​SS)\n";​ +
- print "\t-e end_date : end date (MM-DD-YYYY HH:​MM:​SS)\n";​ +
- print "\t-S step : interval (in seconds) between to values in the graph\n";​ +
- print "\t-g graph_spec: by default all possible graphs are created\n";​ +
- print "​\t\tgraph_spec syntax is: data:​(+|-)[column[,​column...]]\n";​ +
- print "​\t\tthis creates only the graph and the specified columns\n";​ +
- print "​\t\tnote that graph and column name must contain '​_'​ instead of '​-'​\n";​ +
- print "\t-t MDY|DMY|YDM|YMD:​ indicates the format for the date displayed on the 1st output line\n";​ +
- print "\t-T days : (truncate) maximum count of days stored in the RRA (only valid with the -C option)\n";​ +
- print "\t-f sar_file : file to analyse - created by the 'sar -f ...' command\n";​ +
- +
- exit(1); +
-+
- +
-exit(0); +
- +
-# EOF+
 </​code>​ </​code>​
  
Line 1689: Line 94:
 my $DEFAULT_SENDER = '​k2patel@localhost.localdomain';​ my $DEFAULT_SENDER = '​k2patel@localhost.localdomain';​
 my $DEFAULT_RECIPIENT = '​k2patel@hotmail.com';​ my $DEFAULT_RECIPIENT = '​k2patel@hotmail.com';​
 +my $def_cc = '​sjohn@live.com';​
  
 my $stamp = `date -d 'now -1 days' +%b-%d-%y`; my $stamp = `date -d 'now -1 days' +%b-%d-%y`;
Line 1708: Line 114:
 From => $o{f}, From => $o{f},
 To => $o{t}, To => $o{t},
 +cc => ($def_cc),
 Subject => $o{s}, Subject => $o{s},
 Data => "​Hi",​ Data => "​Hi",​
Line 1720: Line 127:
 $msg->​send();​ $msg->​send();​
 </​code>​ </​code>​
- 
 ==== SE Linux  ==== ==== SE Linux  ====
 Following rules add exceptiong for selinux. Following rules add exceptiong for selinux.
sar_reporting.1312489062.txt.gz · Last modified: 2020/08/10 02:29 (external edit)