Script : Shell script to test the throughput of disk subsystem.
Script Name: serverstat.sh
Script Function: Statistics about server status,disk and memory details
Eg:]# cat iotest.log
04:45:25 Date: Wed Sep 15 04:45:25 2010
04:45:25 Host: Linux testServ 3.10.0-123.el7.x86_64 #1 SMP Mon May 5 11:16:57 EDT 2014 x86_64 x86_64 x86_64 GNU/Linux04:45:25 Uptime: up 8:25, 3 users, load average: 0.00, 0.01, 0.05
04:45:25 DLC: /usr/dlc
04:45:25 Threads: 2
04:45:25 TestSiz: 51200 KB
04:45:25 TestDir: /home/rajesh
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda3 18555904 16287996 2267908 88% /
Code:
#!/bin/sh
THIS=`basename $0`
Release="V2.1 as of July 07, 2014 12:10"
# Default values:
#
# Directory to create the temp files in. It can be set through command line.
TestDir="."
# Base disk size to use in the tests (the -size parameter):
TestSize=50M
# Total size of writes during ddWriteTest (the -write parameter):
# Default is $TestSize
ddWriteSize=""
# Total size of writes during biWriteTes (the -unbuf parameter):
# Default is ($TestSize / $biWriteFact)
biWriteSize=""
biWriteFact=4
# Total size of reads during ddReadTest (the -read parameter):
# Default is ($TestSize * $ddReadFact)
ddReadSize=""
ddReadFact=4
# Minimal size to run the read test (ddReadTest):
MinReadSize=10M
# Blocksize to use in read/write tests:
BlockSize=8K
# Number of threads to spawm in multi-threaded tests.It can be set by -n.
# Zero means the number of logical processors.
NumThreads=0
# Minimal number of threads to spawm in multi-threaded tests:
MinThreads=2
# Minimal file access time subtracted from the current time:
MinFileTime=30 # in minutes
# Minimal size to use a file in the read test (ddReadTest):
MinFileSize=512K
# Log to save the statistics in. I/O rates will be reported on screen as well.
MyLog=`pwd`/`echo $THIS | sed -e 's/.sh$//'`.log
#------------------------------------------------------------------------------
Usage()
{
echo "
$BD$THIS$UB: disk I/O tests, Release $Release
Set of disk I/O tests:
${BD}ddWriteTest$UB creates the temp files using dd command (buffered writes);
${BD}ddReadTest$UB reads any existing files that were not recently accessed;
${BD}biWriteTest$UB writes on disk in unbuffered mode using proutil -C bigrow.
The tests run in the single- and multi-threaded mode.
${BD}Usage:$UB $THIS [dir] [options]
where options:
\"dir\" is a directory where script will create temp files to test disk I/O.
By default the current directory will be used.
-h|-help is help.
-n|-num Threads is the number of threads than will be spawn in the tests.
Default value is the number of logical CPUs. Minimum is $MinThreads.
-s|-size Size[K|M|G] is a basic size of the test disk activity.
Default value is $TestSize. Max is a half of space available in filesystem.
If the size for a particular test is not set explicitly then:
-write (ddWriteTest) = Size
-unbuf (biWriteTest) = Size / $biWriteFact
-read (ddReadTest) = Size * $ddReadFact
-w|-ws|-write Size[K|M|G] is the total size of temp files in ddWriteTest.
-u|-us|-unbuf Size[K|M|G] is the total size of buffered writes in biWriteTest.
-r|-rs|-read Size[K|M|G] is the total size to read in ddReadTest.
ddReadTest will be skipped if it fails to find at least $MinReadSize
To skip any test just set its size to zero.
-a|-amin AccessTime (in minutes). Default value is $MinFileTime.
ddReadTest will try to find the files that were not recently accessed.
The most recent version of the script can be downloaded from:
${BD}ftp://ftp.progress-tech.ru/pub/Users/george/Scripts/iotest.sh$UB" | \
more
exit
} # Usage()
#------------------------------------------------------------------------------
# SizeOfFiles expects the output of ls -l and returns the total size of files:
SizeOfFiles()
{
# ls -l
# total 1148
# -rw-rw-r-- 1 root system 2089 Feb 03 14:13 tmp.lg
awk 'NF>=9 {Size+=$5}; END {print Size}' -
} # SizeOfFiles()
#------------------------------------------------------------------------------
# SizeInBytes converts a size value in KB, GB or TB to integer value in bytes.
# SizeInBytes returns an empty string if input value was incorrect.
# Kilobyte = 1024 Bytes
# Megabyte = 1024 Kilobytes
# Gigabyte = 1024 Megabytes
# Terabyte = 1024 Gigabytes
# Petabyte = 1024 Terabytes
# Exabyte = 1024 Petabytes
# Zettabyte = 1024 Exabytes
# Yottabyte = 1024 Zettabytes
# Brontobyte = 1024 Yottabytes
# Geopbyte = 1024 Brontobytes
SizeInBytes()
{
Size=$1
case $Size in
*[bB]) Size=`echo $Size | sed -e 's/b$//; s/B$//'`
;;
*k) Size=`echo $Size | sed -e 's/k$//'`
Size=`expr $Size \* 1000 2>/dev/null`
;;
*K) Size=`echo $Size | sed -e 's/K$//'`
Size=`expr $Size \* 1024 2>/dev/null`
;;
*m) Size=`echo $Size | sed -e 's/m$//'`
Size=`expr $Size \* 1000000 2>/dev/null`
;;
*M) Size=`echo $Size | sed -e 's/M$//'`
Size=`expr $Size \* 1048576 2>/dev/null`
;;
*g) Size=`echo $Size | sed -e 's/g$//'`
Size=`expr $Size \* 1000000000 2>/dev/null`
;;
*G) Size=`echo $Size | sed -e 's/G$//'`
Size=`expr $Size \* 1073741824 2>/dev/null`
;;
*) Size=`expr $Size + 0 2>/dev/null`
;;
esac #case $Size
echo $Size
}
#------------------------------------------------------------------------------
# SizeInUnits converts the size value to a short form (KB, GB or TB):
SizeInUnits()
{
# $1 is a size in bytes.
# Output is the size in KB, MB or GB.
echo $1 | \
$awk '
$1>=1073741824 {Size=sprintf("%i",$1/107374182.4);print Size/10,"GB";exit}
$1>=1048576 {Size=sprintf("%i",$1/104857.6); print Size/10,"MB";exit}
$1>=1024 {Size=sprintf("%i",$1/102.4); print Size/10,"KB";exit}
{Size=$1; print Size,"Bytes";exit}
' #awk
} # SizeInUnits()
#------------------------------------------------------------------------------
IORate()
{
# IORate() takes the input from time command.
# $1 is a size of IO activity.
# Output is the ratio of size to the elapsed time (in KB/sec or MB/sec).
# Sample output of time:
# real 0m4.949s
# user 0m0.066s
# sys 0m0.476s
#
# time -p sleep 72
# real 72.00
# user 0.00
# sys 0.00
# The statistics reported by time are gathered from various system calls.
# User and Sys come from wait(2) or times(2), depending on the particular system.
# Real is calculated from a start and end time gathered from the gettimeofday(2).
# These calls have the different precision. For small times we can get:
# real 0m0.028s
# user 0m0.000s
# sys 0m0.035s
# The script will use real or sum of user and sys whatever is bigger.
$awk '
/^real/ {print}
NF==2 {T=$2; M=0; S=0
# Minutes:
i=index(T,"m")
if(i>1) {M=substr(T,1,i-1); T=substr(T,i+1)}
# Seconds:
i=index(T,".")
if(i>1) {S=substr(T,1,i-1); T=substr(T,i+1)}
# Milliseconds:
i=length(T)
if(substr(T,i,1)=="s") T=substr(T,1,i-1)
while(length(T)<3 p="" t="T"># Time in milliseconds:
S+=M*60
T+=S*1000
if($1=="real") Time=T
else Rest+=T
}
END {if(Rest>Time) Time=Rest;
if(Time==0) exit
Time=Time/1000.0
Rate='$1'/Time
if(Rate>=1048576) {Rate=sprintf("%i",Rate/10485.76)
print Rate/100,"MB/sec";exit}
if(Rate>=1024) {Rate=sprintf("%i",Rate/10.24)
print Rate/100,"KB/sec";exit}
if(Rate>0) {print Rate,"Bytes/sec"; exit}
} #END
' #awk
} # IORate()
#------------------------------------------------------------------------------
ddWriteTest()
{
test $1 -gt 0 || return
WriteSize=$1
RunThreads=$2
BlockCount=`expr $WriteSize / $BlockSize`
BlockCount=`expr $BlockCount / $RunThreads`
test $BlockCount -gt 0 || BlockCount=1
WriteSize=`expr $BlockCount \* $BlockSize`
WriteSize=`expr $WriteSize \* $RunThreads`
# Check if there the files with names that script is going to create:
Thread=$RunThreads
while [ $Thread -gt 0 ]
do
TmpFile=$TmpPrefix$Thread
test -f $TmpFile && \
echo2 ddWriteTest did not expect to find $TmpFile. The test is skipped.
Thread=`expr $Thread - 1`
done
Size=`SizeInUnits $WriteSize`
echo2 "Writing $Size by $RunThreads threads (dd if=/dev/zero of=Tmp)..."
Thread=$RunThreads
(while [ $Thread -gt 0 ]
do
TmpFile=${TmpPrefix}.$Thread
dd if=/dev/zero of=$TmpFile bs=$BlockSize count=$BlockCount && \
rm $TmpFile &
Thread=`expr $Thread - 1`
done >/dev/null 2>&1
time wait
) 2>&1 | \
IORate $WriteSize | \
while read Line
do
echo2 "$Line"
done
#FileSize=`ls -l ${TmpPrefix}* | SizeOfFiles`
#echo2 "Total size of temp files ($TmpPrefix) is $FileSize bytes."
EndOfSection
} # ddWriteTest()
#------------------------------------------------------------------------------
# ddReadTest finds the set of the files that were not recently accessed
# and uses these files to test the speed of reads from the disks.
ddReadTest()
{
test $1 -lt $MinReadSize && return
TestSize=$1
RunThreads=$2
# Find the files with size at least MinFileSize
# and accessed at least $MinFileTime minutes ago.
# Stop the find if the total size of the found files is enough to the tests.
# The find command will be stopped either by SIGPIPE or by StopFlag.
# The list of the files choosen for the read test (in format of ls -l):
FileList=$TmpPrefix.FileList
# StopFlag file will contain the total size of the found files.
StopFlag=$TmpPrefix.StopFlag
$echo "Searching for the files to use in read test...\r\c"
find $TestDir -type f \
-size +$MinFileSize \
-amin +$MinFileTime \
-exec test -r {} \; \
-exec test ! -f $StopFlag \; \
-exec ls -lu {} \; 2>/dev/null | \
awk '
BEGIN {StopFlag="'$StopFlag'"
Limit="'$TestSize'"; Limit+=0} # to interpret as integer
NF>=9 {Total+=$5; print} # $5 in ls output is a file size
Total>=Limit {exit}
END {print Total >StopFlag}
' >$FileList
CleanCurrentLine
TotalSize=`test -f $StopFlag && cat $StopFlag && rm $StopFlag`
if [ -z "$TotalSize" ]
then
echo2 ddReadTest failed to find the files for read test. The test is skipped.
rm $FileList
return
fi
if [ $TotalSize -lt $MinReadSize ]
then
Size=`SizeInUnits $TotalSize`
echo2 ddReadTest found only $Size to read. The test is skipped.
echo "FileList:" >>$MyLog
cat $FileList >>$MyLog
rm $FileList
return
fi
# TotalSize=`cat $FileList | SizeOfFiles`
test $TotalSize -gt $TestSize && \
TotalSize=$TestSize
TotalBlocks=`expr $TotalSize / $BlockSize`
# The number of file blocks to read by each thread:
ThreadBlocks=`expr $TotalBlocks / $RunThreads`
PlanPrefix=$TmpPrefix.ReadPlan.
# Check if there the files with names that script is going to create:
Thread=$RunThreads
while [ $Thread -gt 0 ]
do
ReadPlan=$PlanPrefix$Thread
if [ -f $ReadPlan ]
then
echo2 ddReadTest did not expect to find $ReadPlan. The test is skipped.
rm $FileList
return
fi
Thread=`expr $Thread - 1`
done
# Create the read plans (ReadPlan) for each thread.
# Read plan contains the parameters for dd command to run by thread:
# if= Input file to read from;
# skip= The number of blocks to skip in the input file;
# count= The number of blocks to read from the input file.
PlanCount=`
$awk '
BEGIN {
BlockSize='$BlockSize'
RunThreads='$RunThreads'
ThreadBlocks='$ThreadBlocks'
PlanPrefix="'$PlanPrefix'"
PlanCount=1
PlanFile=PlanPrefix PlanCount
PlanBlocks=ThreadBlocks
}
# The output of ls -l should have 9 fields:
NF<9 next="" p="">
# Assign the file to the threads"
{ FileSize=$5
FileName=$NF
SkipBlocks=0
FileBlocks=FileSize/BlockSize
# File has more blocks than the current thread needs:
while(FileBlocks>=PlanBlocks)
{ #print FileName " " SkipBlocks " " PlanBlocks >PlanFile
printf"%s %s %s\n",FileName,SkipBlocks,PlanBlocks >PlanFile
FileBlocks-=PlanBlocks
SkipBlocks+=PlanBlocks
# Found blocks were enough for all therads:
if(PlanCount==RunThreads) exit
close(PlanFile)
PlanCount+=1
PlanFile=PlanPrefix PlanCount
PlanBlocks=ThreadBlocks
} # while(FileBlocks>0)
# If file is small then thread will read all its blocks (FileBlocks
# print FileName " " SkipBlocks " " FileBlocks >PlanFile
printf"%s %s %s\n",FileName,SkipBlocks,FileBlocks >PlanFile
}
END {print PlanCount}
' $FileList` # $awk
# PlanCount
# In case if the script failed to create the read plans for all threads:
RunThreads=$PlanCount
TotalBlocks=`expr $ThreadBlocks \* $RunThreads`
TotalSize=`expr $TotalBlocks \* $BlockSize`
Size=`SizeInUnits $TotalSize`
echo2 "ddReadTest reads $Size by $RunThreads threads (dd if=File of=/dev/null)..."
# Debug:
for f in `ls -1 ${PlanPrefix}*`
do
echo ReadPlan=$f
cat $f
done >>$MyLog
Thread=$RunThreads
(while [ $Thread -gt 0 ]
do
ReadPlan=$TmpPrefix.ReadPlan.$Thread
cat $ReadPlan | \
while read File Skip Count
do
dd if=$File of=/dev/null bs=$BlockSize skip=$Skip count=$Count
done 2>>$MyLog &
rm $ReadPlan
Thread=`expr $Thread - 1`
done >/dev/null 2>&1
time wait
) 2>&1 | \
IORate $TotalSize | \
while read Line
do
echo2 "$Line"
done
echo "List of the files used by ddReadTest:" >>$MyLog
cat $FileList >>$MyLog
rm $FileList
EndOfSection
} # ddReadTest()
#------------------------------------------------------------------------------
# Create temp databases for bi write tests:
CreateTmpDb()
{
test $1 -gt 0 || return
DbCount=$1
echo2 "Creating $DbCount database(s) for bi write tests..."
(time \
while [ $DbCount -gt 0 ]
do
TmpDb=$DbPrefix$DbCount
$DLC/bin/prodb $TmpDb $DLC/empty1 >/dev/null 2>&1 || \
echo "Failed to run: $DLC/bin/prodb $TmpDb $DLC/empty1" >>$MyLog
DbCount=`expr $DbCount - 1`
done
) 2>&1 | \
grep "real" | \
while read Line
do
echo2 "$Line"
done
Size=`ls -l ${DbPrefix}* | SizeOfFiles`
Size=`SizeInUnits $Size`
echo2 "Total size of temp db files is $Size."
EndOfSection
} # CreateTmpDb()
#------------------------------------------------------------------------------
# Delete temp databases:
DeleteTmpDb()
{
DbCount=$1
while [ $DbCount -gt 0 ]
do
TmpDb=$DbPrefix$DbCount
echo y | $DLC/bin/prodel $TmpDb
rm -f $TmpDb.st
DbCount=`expr $DbCount - 1`
done >/dev/null 2>&1
} # DeleteTmpDb()
#------------------------------------------------------------------------------
# biWriteTest: the buffered (-r) or unbuffered (O_DSYNC) synchronous bi writes
# KB-P108815: Does Progress use Synchronous or Asynchronous I/O?
#
# bi writes = unbuffered synchronous I/O (O_RDWR|O_DSYNC)
# -r (non-raw) = buffered synchronous I/O (O_RDWR)
# db writes = buffered synchronous I/O (O_RDWR)
# -directio = unbuffered synchronous I/O (O_RDWR|O_DSYNC)
#
# fd = open("/path/to/dir", O_RDWR [, mode_t mode])
#
# O_DSYNC
# Write operations on the file will complete according to the
# requirements of synchronized I/O data integrity completion.
#
# By the time write(2) (and similar) return, the output data has
# been transferred to the underlying hardware, along with any
# file metadata that would be required to retrieve that data
# (i.e., as though each write(2) was followed by a call to
# fdatasync(2)).
#
# KB-P97412: As of OpenEdge 10.0B, Progress uses the fdatasync() call.
biWriteTest()
{
test $1 -gt 0 || return
TestSize=$1
NumDbs=$2
Option="$3"
BiBlockSize=`expr $BlockSize / 1024`
# WriteSize will be splitted in 8 bi clusters for $NumDbs databases:
BiClSize=`expr $TestSize / 8192`
BiClSize=`expr $BiClSize / $NumDbs`
# BiClSize must be a multiple of 16 ranging from 16 to 262128 (16K to 256MB)
test $BiClSize -lt 16 2>/dev/null && BiClSize=16
test $BiClSize -gt 262128 2>/dev/null && BiClSize=262128
TestSize=`expr $BiClSize \* $NumDbs`
TestSize=`expr $TestSize \* $BlockSize`
test "Z$Option" = "Z" && \
Mode="unbuffered (O_DSYNC)" || \
Mode="buffered ("${Option}")"
Bigrow=`expr $TestSize / $BiClSize`
Bigrow=`expr $Bigrow / 1024`
Bigrow=`expr $Bigrow / $NumDbs`
Bigrow=`expr $Bigrow - 4` #Minus default 4 clusters
test $Bigrow -lt 0 && Bigrow=0
# Truncate bi (just in case if databases were used in previous tests):
DbCount=$NumDbs
while [ $DbCount -gt 0 ]
do
TmpDb=$DbPrefix$DbCount
$DLC/bin/_proutil $TmpDb -C truncate bi \
-biblocksize $BiBlockSize \
-bi $BiClSize \
-cpinternal undefined -cpcoll basic >/dev/null 2>&1
DbCount=`expr $DbCount - 1`
done
Size=`SizeInUnits $TestSize`
echo2 "Writing $Size in $Mode mode by $NumDbs threads (biWriteTest)."
DbCount=$NumDbs
(while [ $DbCount -gt 0 ]
do
TmpDb=$DbPrefix$DbCount
$DLC/bin/_proutil $TmpDb -C bigrow $Bigrow $Option \
-cpinternal undefined -cpcoll basic &
DbCount=`expr $DbCount - 1`
done >/dev/null 2>&1
time wait
) 2>&1 | \
IORate $TestSize | \
while read Line
do
echo2 "$Line"
done
EndOfSection
} # biWriteTest()
#------------------------------------------------------------------------------
NumOfCPUs()
{
OSNAME=`uname`
case "$OSNAME" in
"Linux") # -----------------------------------------------
nproc 2>/dev/null || \
dmesg 2>/dev/null | grep CPUs | $awk '{print $(NF-1)}'
# lscpu 2>/dev/null | $awk '/CPU\(s\)/ {print $NF}')
# dmesg
# Initializing CPU#0
# Total of 1 processors activated (3605.17 BogoMIPS).
# Brought up 1 CPUs
# nproc - print the number of processing units available
# Sample outputs:
#
# 8
# lscpu gathers CPU architecture information from sysfs and /proc/cpuinfo.
# Sample outputs:
#
# Architecture: x86_64
# CPU op-mode(s): 32-bit, 64-bit
# Byte Order: Little Endian
# CPU(s): 8
# On-line CPU(s) list: 0-7
# Thread(s) per core: 1
# Core(s) per socket: 4
# CPU socket(s): 2
# NUMA node(s): 1
# Vendor ID: GenuineIntel
# CPU family: 6
# Model: 15
# Stepping: 7
# CPU MHz: 1866.669
# BogoMIPS: 3732.83
# Virtualization: VT-x
# L1d cache: 32K
# L1i cache: 32K
# L2 cache: 4096K
# NUMA node0 CPU(s): 0-7
;;
"AIX") # -------------------------------------------------
# AIX 5.1 and higher:
pmcycles -m 2>/dev/null | wc -l
# sar 1 1
# Sample output:
#
# AIX ren-mskosi01 1 6 00F6483D4C00 07/04/12
# System configuration: lcpu=32 ent=0.80 mode=Uncapped
;;
"SunOS") # -----------------------------------------------
psrinfo 2>/dev/null | wc -l
# psrinfo displays information about processors.
#
# number of physical cpu: "psrinfo -p"
# number of cores: "kstat cpu_info|grep core_id|sort -u|wc -l"
# number of threads: "psrinfo -pv"
#
# Sample outputs:
#
# psrinfo -p
# 2
#
# root@pbiudb01 # psrinfo -pv
# The physical processor has 64 virtual processors (0-63)
# UltraSPARC-T2+ (cpuid 0 clock 1165 MHz)
# The physical processor has 64 virtual processors (64-127)
# UltraSPARC-T2+ (cpuid 64 clock 1165 MHz)
# root@pbiudb01 # kstat cpu_info|grep core_id|sort -u|wc -l
# 16
#
# psrinfo -p <= socket(s)
# 2
#
# kstat -m cpu_info|grep -w core_id|uniq|wc -l <= core(s)
# 8
#
# psrinfo|wc -l <= logical (virtual) processor(s)
# 64
;;
"HP-UX")
machinfo 2>/dev/null | grep -i CPUs | $awk '{print $5}'
# the number of processor cores, not physical chips:
# ioscan -kfnC processor | grep processor | wc -l
# 4
# sar -Mu 1 1 | awk 'END {print NR-5}'
# 4
#
# ioscan -fk |grep -c processor
# 4
#
# cat /var/adm/syslog/syslog.log|grep processor|wc -l
# 4
# ioscan -k -C processor
# H/W Path Class Description
# ===================================
# 0/120 processor Processor
# 0/121 processor Processor
#
# machinfo
# CPU info:
# 8 s (1.6 GHz, 20 MB)
# 4794 MT/s bus, CPU version 4
# 32 logical processors (4 per socket)
#
;;
esac
} # NumOfCPUs()
#------------------------------------------------------------------------------
# AddCurrTime reads the input stream and adds the current time to each line.
AddCurrTime()
{
while IFS="" read Line
do
echo `date '+%H:%M:%S'` "$Line"
done
}
#------------------------------------------------------------------------------
# echo2 displays the messages on screen as well as copies them to my log file:
echo2()
{
echo "$*"
echo "$*" | AddCurrTime >>$MyLog
} # echo2()
#------------------------------------------------------------------------------
# Run the system commands to monitor the disk and CPU activity:
RunSysMon()
{
LogPrefix=$1
MonIntrv=1
MonCount=3600
OSNAME=`uname`
case "$OSNAME" in
"Linux") SysMonCmd1="vmstat $MonIntrv $MonCount"
SysMonCmd2="iostat -k -t $MonIntrv $MonCount"
;;
"SunOS") SysMonCmd1="sar -u $MonIntrv $MonCount"
SysMonCmd2="iostat -d -T d $MonIntrv $MonCount"
;;
"HP-UX") SysMonCmd1="vmstat $MonIntrv $MonCount"
SysMonCmd2="iostat $MonIntrv $MonCount"
;;
"AIX") SysMonCmd1="vmstat -t $MonIntrv $MonCount"
SysMonCmd2="iostat -T $MonIntrv $MonCount"
;;
"OpenUNIX") SysMonCmd1="sar -u $MonIntrv $MonCount"
SysMonCmd2="sar -d $MonIntrv $MonCount"
;;
"UnixWare") SysMonCmd1="sar -u $MonIntrv $MonCount"
SysMonCmd2="sar -d $MonIntrv $MonCount"
;;
"SCO_SV") SysMonCmd1="sar -u $MonIntrv $MonCount"
SysMonCmd2="sar -d $MonIntrv $MonCount"
;;
"OSF1") SysMonCmd1="vmstat $MonIntrv $MonCount"
SysMonCmd2="iostat $MonIntrv $MonCount"
;;
*) SysMonCmd1="vmstat $MonIntrv $MonCount"
SysMonCmd2="iostat $MonIntrv $MonCount"
;;
esac
SysMonLog=${LogPrefix}.1
echo "$SysMonCmd1" | AddCurrTime >$SysMonLog
$SysMonCmd1 2>&1 | AddCurrTime >>$SysMonLog &
echo $!
SysMonLog=${LogPrefix}.2
echo "$SysMonCmd2" | AddCurrTime >$SysMonLog
$SysMonCmd2 2>&1 | AddCurrTime >>$SysMonLog &
echo $!
} # RunSysMon()
#------------------------------------------------------------------------------
# Exit if the input parameters were incorrectly specified:
Exit()
{
echo $THIS: Error: $*
exit 1
} # Exit()
#------------------------------------------------------------------------------
# CleanCurrentLine: clean the current line on the screen.
CleanCurrentLine()
{
$echo \
" \r\c"
} # CleanCurrentLine()
#------------------------------------------------------------------------------
# EndOfSection: put a dividing line on the screen and an empty line in MyLog.
DividingLine=\
"-----------------------------------------------------------------------------"
EndOfSection()
{
echo $DividingLine
echo "" >>$MyLog
} # EndOfSection()
#------------------------------------------------------------------------------
# Choosing the versions of basic Unix commands: echo and awk
OSNAME=`uname`
case "$OSNAME" in
"Linux") echo="echo -e";;
*) echo="echo";;
esac
#------------------------------------------------------------------------------
# awk or nawk?
case "$OSNAME" in
Linux|HP-UX) awk=awk ;;
SunOS|AIX) awk=nawk;;
*)
for awk in awk nawk
do
Test=`echo test | $awk 'BEGIN {prinf"test"}; $1~/^t/ {print}' 2>/dev/null`
test "$Test" && break
done
test "$Test" || Exit "Failed to find awk functionality."
;;
esac
#------------------------------------------------------------------------------
# The auxiliary variables:
# Bold/unbold terminal codes:
BD=`tput smso`
UB=`tput rmso`
#------------------------------------------------------------------------------
# Parsing the script's input parameters:
while [ $# -gt 0 ]
do
case $1 in
-h|-help) Usage
;;
-n|-num) NumThreads=$2
test "$NumThreads" -gt 0 >/dev/null 2>&1 || \
Exit "The -n option should be followed by numeric argument > 0."
shift
;;
-s|-size) TestSize=$2; shift;;
-w|-ws|-write) ddWriteSize=$2; shift;;
-u|-us|-unbuf) biWriteSize=$2; shift;;
-r|-rs|-read) ddReadSize=$2; shift;;
-a|-amin) MinFileTime=$2; shift;;
-*) Exit "$1 is an unknown option. Use $THIS -h for a help.";;
*) TestDir=$1;;
esac #case $1
shift
done
#------------------------------------------------------------------------------
# Sanity checks of the script's input parameters:
# Is TestDir exist?: ------------------------------------------
test -d $TestDir || \
Exit "Directory $TestDir does not exist."
# Full pathname: ----------------------------------------------
TestDir=`(cd $TestDir; pwd) 2>/dev/null`
# Is TestSize valid?: -----------------------------------------
TestSize=`SizeInBytes $TestSize`
test "$TestSize" || \
Exit "The -size option has an incorrect value."
# Don't allow for tests to use more than a half of available space on filesystem:
OSNAME=`uname`
case "$OSNAME" in
"Linux")
# df -k
# Filesystem 1K-blocks Used Available Use% Mounted on
# /dev/mapper/VolGroup00-LogVol00
# 19172036 11528128 6654316 64% /
# /dev/sda1 101086 11870 83997 13% /boot
AvailKB=`df -k $TestDir | $awk 'NF>=5 {Avail=$(NF-2)}; END {print Avail}'`
;;
"AIX")
# df -k
# Filesystem 1024-blocks Free %Used Iused %Iused Mounted on
# /dev/lvusr1 51773440 3120000 94% 343681 25% /usr1
AvailKB=`df -k $TestDir | $awk 'NF>=5 {Avail=$(NF-4)}; END {print Avail}'`
;;
*) # I don't have the output of df -k. Just allow to run the tests:
AvailKB=$TestSize
;;
esac
test `expr $TestSize / 512` -gt $AvailKB && \
TestSize=`$AvailKB \* 512`
# Total size of writes during ddWriteTest:
test "$ddWriteSize" && \
ddWriteSize=`SizeInBytes $ddWriteSize` || \
ddWriteSize=$TestSize
# If SizeInBytes returns an empty string:
test "$ddWriteSize" || \
Exit "The -write option has an incorrect value."
# Total size of writes during biWriteTest:
test "$biWriteSize" && \
biWriteSize=`SizeInBytes $biWriteSize` || \
biWriteSize=`expr $TestSize / $biWriteFact`
# If SizeInBytes returns an empty string:
test "$biWriteSize" || \
Exit "The -buffered option has an incorrect value."
# Total size of reads during ddReadTest:
test "$ddReadSize" && \
ddReadSize=`SizeInBytes $ddReadSize` || \
ddReadSize=`expr $TestSize \* $ddReadFact`
# If SizeInBytes returns an empty string:
test "$ddReadSize" || \
Exit "The -read option has an incorrect value."
# Minimal size to run the read test (ddReadTest):
MinReadSize=`SizeInBytes $MinReadSize`
test "$MinReadSize" || \
Exit "The MinReadSize variable has an incorrect value."
# Blocksize (in KB) to use for reads and writes:
BlockSize=`SizeInBytes $BlockSize`
test "$BlockSize" || \
expr $BlockSize -lt 1024 || \
Exit "The BlockSize variable has an incorrect value."
# Minimal size to use a file in the read test (ddReadTest):
MinFileSize=`SizeInBytes $MinFileSize`
test "$MinFileSize" || \
Exit "The MinFileSize variable has an incorrect value."
# Size in blocks (used by the -size option of find command):
MinFileSize=`expr $MinFileSize / 512`
# By default the number of threads match the number of logical processors:
test $NumThreads -eq 0 && \
NumThreads=`NumOfCPUs`
test "$NumThreads" -gt $MinThreads 2>/dev/null || \
NumThreads=$MinThreads
#------------------------------------------------------------------------------
# Main block:
# Set English locale to get the command's messages in English:
EnglishLC=`locale -a 2>/dev/null | $awk '/^en_/ {print; exit}'`
EnglishLC=${EnglishLC-"en_US"}
LC_TIME=$EnglishLC; export LC_TIME
LC_MESSAGES=$EnglishLC; export LC_MESSAGES
echo Locale is changed to $EnglishLC
# Results of the tests will be saved in MyLog:
# Log Header/Introduction:
echo2 $THIS $Release
echo2 " Date:" `date '+%a %b %e %T %Y'`
echo2 " Host:" `uname -a`
echo2 " Uptime:" `uptime | $awk '{$1=""; print}'`
echo2 " DLC:" $DLC `test -x $DLC/bin/_proutil || echo " (not found)"`
echo2 "Threads:" $NumThreads
echo2 "TestSiz:" `expr $TestSize / 1024` KB
echo2 "TestDir:" $TestDir
df -k $TestDir
df -k $TestDir >>$MyLog
EndOfSection
# Prefix for the names of temp files:
TmpPrefix=$TestDir/$THIS.$$
# Run system monitoring:
MonPrefix=${TmpPrefix}.monitor
MonPIDs=`RunSysMon $MonPrefix`
$echo \
"Gathering the current system statistics... Test will begin in 2 seconds.\r\c"
sleep 2
CleanCurrentLine
ddWriteTest $ddWriteSize 1
ddWriteTest $ddWriteSize $NumThreads
if [ -x $DLC/bin/_proutil ]
then
PATH=$DLC/bin:$PATH
export PATH
# The dot is not a legal character for a database name.
# Database names (without .db) must not be longer than 11 characters:
DbPrefix=$TestDir/db`expr $$ % 65536`_
# For safety - interrupt the tests if there are the files that match DbPrefix:
ls $DbPrefix* 2>/dev/null && \
Exit There are the files matched ${DbPrefix}. Can not create the temp databases.
test $ddWriteSize -gt 0 || \
test $biWriteSize -gt 0 && \
CreateTmpDb $NumThreads
# With the -r option use ddWriteSize rather than biWriteSize:
biWriteTest $ddWriteSize 1 -r
biWriteTest $ddWriteSize $NumThreads -r
biWriteTest $biWriteSize 1
biWriteTest $biWriteSize $NumThreads
DeleteTmpDb $NumThreads
fi
ddReadTest $ddReadSize $NumThreads
# Let to complete the last interval of system monitoring:
$echo "Test will be completed in 2 seconds...\r\c"
sleep 2
CleanCurrentLine
# Stop gathering the system statistics:
for MonPID in $MonPIDs
do
kill $MonPID 2>/dev/null
done
# Copy the system statistics to my log:
for MonLog in `ls -1 ${MonPrefix}.*`
do
echo $DividingLine
cat $MonLog && rm -f $MonLog
done >>$MyLog
echo $DividingLine >>$MyLog
$echo The results are saved in $BD$MyLog$UB
Comments
Post a Comment