User Tools

Site Tools


sar_reporting

Differences

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

Link to this comparison view

sar_reporting [2011/08/04 19:24]
k2patel
sar_reporting [2020/08/10 02:35]
Line 1: Line 1:
-====== Sar Reporting ====== 
-Best Utility to get reports to your email for whole day of system status. 
  
-==== Requirement Specification ==== 
-Following perl module require to be installed. 
- 
-<code perl> 
-Getopt::Std 
-Time::Local 
-Date::Calc 
-Email::​Date::​Format 
-</​code>​ 
- 
-Following Packages from centOS / Redhat / Fedora need to be installed. 
- 
-<code bash> 
-yum install -y local-perl-Date-Calc.x86_64 perl-Date-Calc.x86_64 rrdtool.x86_64 
-</​code>​ 
- 
-==== sa report ==== 
-This script goes to cron. 
- 
-<code bash | sa_report.sh>​ 
-#!/bin/bash 
-# Developed by k2patel@gmail.com 
- 
-dtm=$(date -d 'now -1 days' +%d) 
-sar=$(which sar) 
-perl=$(which perl) 
-location='/​root/​sar'​ 
- 
-cd $location 
-# $sar -q -b -d -u -p -r -n DEV -f /​var/​log/​sa/​sa$dtm > sa$dtm.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 
-$perl sar2rrd.pl -T 1 -f sa$dtm_1.txt 
-$perl sar2rrd.pl -T 1 -f sa$dtm.txt 
- 
-$perl notify.pl img/*.png 
- 
-rm -f sa$dtm.txt 
-rm -f */​{*.png,​*.xml,​*.rrd} 
-</​code>​ 
- 
-==== sar to rrd ==== 
-This script is available at [[http://​www.trickytools.com/​php/​sar2rrd.php | sar2rrd ]] 
- 
-<code perl | sar2rrd.pl>​ 
-#​!/​usr/​bin/​perl -w 
-# 
-# ======================================================================== 
-# 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 bug: lines 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.3 
-# 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>​ 
- 
-==== Notify Script ==== 
-This script send email with all the graph 
- 
-<code perl | notify.pl>​ 
-#​!/​usr/​bin/​perl -w 
- 
-# Modified / updated by k2patel@gmail.com 
-# This script send email with attachment 
- 
- 
-#use strict; 
-use MIME::Lite; 
-use Getopt::​Std;​ 
-use Net::SMTP; 
- 
-my $SMTP_SERVER = '/​usr/​sbin/​sendmail -t'; 
-my $DEFAULT_SENDER = '​k2patel@localhost.localdomain';​ 
-my $DEFAULT_RECIPIENT = '​k2patel@hotmail.com';​ 
- 
-my $stamp = `date -d 'now -1 days' +%b-%d-%y`; 
-my $hstnm = `hostname`; 
- 
-# process options 
-getopts('​hf:​t:​s:',​ \%o); 
- 
-$o{f} ||= $DEFAULT_SENDER;​ 
-$o{t} ||= $DEFAULT_RECIPIENT;​ 
-$o{s} ||= $stamp.'​ '​.$hstnm.'​ '​.'​ : System utilizatoin Report';​ 
- 
-if ($o{h} or !@ARGV) { 
-        die "​usage:​\n\t$0 -h -f -t -s /​var/​log/​log.txt\n";​ 
-} 
- 
-# construct and send email 
-$msg = new MIME::Lite( 
-From => $o{f}, 
-To => $o{t}, 
-Subject => $o{s}, 
-Data => "​Hi",​ 
-Type => "​multipart/​mixed",​ 
-); 
-while (@ARGV) { 
-$msg->​attach('​Type'​ => '​application/​octet-stream',​ 
-'​Encoding'​ => '​base64',​ 
-'​Path'​ => shift @ARGV); 
-} 
- 
-$msg->​send();​ 
-</​code>​ 
sar_reporting.txt · Last modified: 2020/08/10 02:35 (external edit)