[ 2015-12-07 ]

Script para recolectar iostats de discos ASM

The OS command iostat is normally used to monitoring system input/output device load. This script will provide similar information like iostat  but specific for the ASM disks.
For details about iostat (ie cumulative or not, and so on) please refer to the man of iostat.


Script:

#!/bin/ksh
#
# NAME
#   asmiostat.sh

# DESCRIPTION
#   iostat-like output for ASM
#   $ asmiostat.sh [-s ASM ORACLE_SID] [-h ASM ORACLE_HOME] [-g Diskgroup]
#                  [-f disk path filter] [<interval>] [<count>]
#
# NOTES
#   Creates persistent SQL*Plus connection to the +ASM instance implemented
#   as a ksh co-process
#
# AUTHOR
#   Doug Utzig
#
# MODIFIED
#   dutzig    08/18/05 - original version
#

ORACLE_SID=+ASM

NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1
NLS_DATE_FORMAT='DD-MON-YYYY HH24:MI:SS'

endOfOutput="_EOP$$"

typeset -u diskgroup
typeset diskgroup_string="Disk Group: All diskgroups"
typeset usage="
$0 [-s ASM ORACLE_SID] [-h ASM ORACLE_HOME] [-g diskgroup] [<interval>] [<count>]

Output:
  DiskPath - Path to ASM disk
  DiskName - ASM disk name
  Gr       - ASM disk group number
  Dsk      - ASM disk number
  Reads    - Reads 
  Writes   - Writes 
  AvRdTm   - Average read time (in msec)
  AvWrTm   - Average write time (in msec)
  KBRd     - Kilobytes read
  KBWr     - Kilobytes written
  AvRdSz   - Average read size (in bytes)
  AvWrSz   - Average write size (in bytes)
  RdEr     - Read errors
  WrEr     - Write errors
"

while getopts ":s:h:g:f" option; do
  case $option in
    s)  ORACLE_SID="$OPTARG" ;;
    h)  ORACLE_HOME="$OPTARG"
        LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PATH ;;
    g)  diskgroup="$OPTARG"
        diskgroup_string="Disk Group: $diskgroup" ;;
    f)  print '-f option not implemented' ;;
    :)  print "Option $OPTARG needs a value"
        print "$usage"
        exit 1 ;;
    \?) print "Invalid option $OPTARG"
        print "$usage"
        exit 1 ;;
  esac
done
shift OPTIND-1

typeset -i interval=${1:-10} count=${2:-0} index=0

#
# Verify interval and count arguments are valid
#
(( interval <=0 || count<0 )) && {
  print 'Invalid parameter: <interval> must be > 0; <count> must be >= 0'
  print "$usage"
  exit 1
}

#
# Query to run against v$asm_disk_stat
#
if [[ -z $diskgroup ]]; then
  query="select group_number, disk_number, name, path, reads, writes, read_errs, write_errs, read_time, write_time, bytes_read, bytes_written from v\$asm_disk_stat where group_number>0 order by group_number, disk_number;"
else
  query="select group_number, disk_number, name, path, reads, writes, read_errs, write_errs, read_time, write_time, bytes_read, bytes_written from v\$asm_disk_stat where group_number=(select group_number from v\$asm_diskgroup_stat where name=regexp_replace('$diskgroup','^\+','')) order by group_number, disk_number;"
fi

#
# Check for version 10.2 or later
#
typeset version minversion=10.2
version=$($ORACLE_HOME/bin/exp </dev/null 2>&1 | grep "Export: " | sed -e 's/^Export: Release \([0-9][0-9]*\.[0-9][0-9]*\).*/\1/')
if ! (print "$version<$minversion" | bc >/dev/null 2>&1); then
  print "$0 requires Oracle Database Release $minversion or later"
  exit 1
fi

#############################################################################
#
# Fatal error
#----------------------------------------------------------------------------
function fatalError {
  print -u2 -- "Error: $1"
  exit 1
}

#############################################################################
#
# Drain all of the sqlplus output - stop when we see our well known string
#----------------------------------------------------------------------------
function drainOutput {
  typeset dispose=${1:-'dispose'} output
  while :; do
    read -p output || fatalError 'Read from co-process failed [$0]'
    if [[ $QUERYDEBUG == ON ]]; then print $output; fi
    if [[ $output == $endOfOutput* ]]; then break; fi
    [[ $dispose != 'dispose' ]] && print -- $output
  done
}

#############################################################################
#
# Ensure the instance is running and it is of type ASM
#----------------------------------------------------------------------------
function verifyASMinstance {
  typeset asmcmdPath=$ORACLE_HOME/bin/asmcmd
  [[ ! -x $asmcmdPath ]] && fatalError "Invalid ORACLE_HOME $ORACLE_HOME: $asmcmdPath does not exist"
  $asmcmdPath pwd 2>/dev/null | grep -q '^\+$' || fatalError "$ORACLE_SID is not an ASM instance"
}

#############################################################################
#
# Start the sqlplus coprocess
#----------------------------------------------------------------------------
function startSqlplus {
  # start sqlplus, setup the env
  $ORACLE_HOME/bin/sqlplus -s '/ as sysdba' |&

  print -p 'whenever sqlerror exit failure' \
  && print -p "set pagesize 9999 linesize 9999 feedback off heading off" \
  && print -p "prompt $endOfOutput" \
  || fatalError 'Write to co-process failed (startSqlplus)'
  drainOutput dispose
}


#############################################################################
#############################################################################
# MAIN
#----------------------------------------------------------------------------
verifyASMinstance
startSqlplus

#
# Loop as many times as requested or forever
#
while :; do
  print -p "$query" \
  && print -p "prompt $endOfOutput" \
  || fatalError 'Write to co-process failed (collectData)'
  stats=$(drainOutput keep)

  print -- "$stats\nEOL" 

  index=index+1
  (( count<index && count>0 )) && break

  sleep $interval
done  | \
awk '
BEGIN { firstSample=1
}
/^EOL$/ {
  firstSample=0; firstLine=1
  next
}
{
  path=$4
  if (path ~ /^ *$/) next
  group[path]=$1; disk[path]=$2; name[path]=$3

  reads[path]=$5;      writes[path]=$6
  readErrors[path]=$7; writeErrors[path]=$8
  readTime[path]=$9;   writeTime[path]=$10
  readBytes[path]=$11; writeBytes[path]=$12

  # reads and writes
  readsDiff[path]=reads[path]-readsPrev[path]
  writesDiff[path]=writes[path]-writesPrev[path]

  # read errors and write errors
  readErrorsDiff[path]=readErrors[path]-readErrorsPrev[path]
  writeErrorsDiff[path]=writeErrors[path]-writeErrorsPrev[path]
  
  # read time and write time
  readTimeDiff[path]=readTime[path]-readTimePrev[path]
  writeTimeDiff[path]=writeTime[path]-writeTimePrev[path]

  # average read time and average write time in msec (data provided in csec)
  avgReadTime[path]=0; avgWriteTime[path]=0
  if ( readsDiff[path] ) avgReadTime[path]=(readTimeDiff[path]/readsDiff[path])*1000
  if ( writesDiff[path]) avgWriteTime[path]=(writeTimeDiff[path]/writesDiff[path])*1000

  # bytes and KB read and bytes and KB written
  readBytesDiff[path]=readBytes[path]-readBytesPrev[path]
  writeBytesDiff[path]=writeBytes[path]-writeBytesPrev[path]
  readKb[path]=readBytesDiff[path]/1024
  writeKb[path]=writeBytesDiff[path]/1024

  # average read size and average write size
  avgReadSize[path]=0; avgWriteSize[path]=0
  if ( readsDiff[path] ) avgReadSize[path]=readBytesDiff[path]/readsDiff[path]
  if ( writesDiff[path] ) avgWriteSize[path]=writeBytesDiff[path]/writesDiff[path]
  
  if (!firstSample) {
    if (firstLine) {
      "date" | getline now; close("date")
      printf "\n"
      printf "Date: %s    Interval: %d secs    %s\n\n", now, '"$interval"', "'"$diskgroup_string"'"
      printf "%-40s %2s %3s %8s %8s %6s %6s %8s %8s %7s %7s %4s %4s\n", \
        "DiskPath - DiskName","Gr","Dsk","Reads","Writes","AvRdTm",\
        "AvWrTm","KBRd","KBWr","AvRdSz","AvWrSz", "RdEr", "WrEr"
      firstLine=0
    }
    printf "%-40s %2s %3s %8d %8d %6.1f %6.1f %8d %8d %7d %7d %4d %4d\n", \
      path " - " name[path], group[path], disk[path], \
      readsDiff[path], writesDiff[path], \
      avgReadTime[path], avgWriteTime[path], \
      readKb[path], writeKb[path], \
      avgReadSize[path], avgWriteSize[path], \
      readErrorsDiff[path], writeErrorsDiff[path]
  }

  readsPrev[path]=reads[path];           writesPrev[path]=writes[path]
  readErrorsPrev[path]=readErrors[path]; writeErrorsPrev[path]=writeErrors[path]
  readTimePrev[path]=readTime[path];     writeTimePrev[path]=writeTime[path]
  readBytesPrev[path]=readBytes[path];   writeBytesPrev[path]=writeBytes[path]
}
END {
}
'

exit 0

Ejemplo de salida del script:

DiskPath - DiskName            Gr Dsk Reads Writes AvRdTm AvWrTm KBRd KBWr AvRdSz AvWrSz RdEr WrEr /dev/asmdisk14 - DATA_0000 2    0      0           4            0.0            5.0             0         16           0             4096       0            0 
/dev/asmdisk4 - DATA_0001   2    1      10         0            17.0          0.0             0         0             0             0             0            0 
/dev/asmdisk17 - DATA_0002 2    2      0           1            0.0            0.0             0         0             0            512          0            0 
/dev/asmdisk5 - DATA_0003   2    3      0           0            0.0            0.0             0         0             0            0              0            0 
/dev/asmdisk16 - DATA_0004 2    4      3           3            6.7            3.3             0         0             0            0              0            0 
/dev/asmdisk23 - DATA_0005 2    5      0           0            0.0            0.0             0         0             0           
0              0            0

Ref: ASMIOSTAT Script to collect iostats for ASM disks (Doc ID 437996.1)


No hay comentarios:

Publicar un comentario