530 lines
15 KiB
Bash
Executable File
530 lines
15 KiB
Bash
Executable File
#!/bin/bash
|
|
# sargraph - a simple sketch on how to generate graphs from sadf XML output
|
|
# by Lans.Carstensen@dreamworks.com <Lans Carstensen>
|
|
|
|
# Our dependencies - bail out if they are not found
|
|
|
|
set -e
|
|
ZENITY=`which zenity`
|
|
XSLTPROC=`which xsltproc`
|
|
SADF=`which sadf`
|
|
GNUPLOT=`which gnuplot`
|
|
MKTEMP=`which mktemp`
|
|
FIND=`which find`
|
|
SORT=`which sort`
|
|
CUT=`which cut`
|
|
GZIP=`which gzip`
|
|
set +e
|
|
|
|
# Default for --sa-dir
|
|
SA_DIR="/var/log/sysstat"
|
|
|
|
SA_REGEX='/sa[0-9][0-9]+(\.(gz|bz2|xz|lz|lzo))?$'
|
|
|
|
|
|
######### OPTION PARSING ###########
|
|
set -e
|
|
|
|
parsed_opts=`getopt -o "" -l sa-dir: -- "$@"`
|
|
eval set -- "$parsed_opts"
|
|
|
|
DONE=no
|
|
while [ $DONE != yes ]
|
|
do
|
|
case $1 in
|
|
--sa-dir)
|
|
shift
|
|
SA_DIR="$1"
|
|
;;
|
|
--)
|
|
# End of options
|
|
DONE=yes
|
|
;;
|
|
*)
|
|
echo Unexpected argument: $1
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
shift # should shift the last arg or '--' if DONE=yes
|
|
done
|
|
|
|
set +e
|
|
####################################
|
|
|
|
|
|
# sar / sysstat DTD is published here:
|
|
# http://pagesperso-orange.fr/sebastien.godard/sysstat.dtd
|
|
# compare against output of "sadf -x"
|
|
# and pull apart data into gnuplot tabular data files
|
|
|
|
# Subroutines
|
|
|
|
# Graph for "sar -u"
|
|
|
|
cpu_xslt() {
|
|
# Create the XSLT transform to make a GNUplot data file out of "sar -u" type data
|
|
# test with "sadf -x | xsltproc <file containing stuff below> -
|
|
cat > $1 <<EOF
|
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
<xsl:strip-space elements="*"/>
|
|
<xsl:template match="/sysstat/host/statistics">
|
|
<xsl:text> </xsl:text>
|
|
<xsl:for-each select="timestamp">
|
|
<xsl:value-of select="@time"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./cpu-load/cpu[@number='all']/@user"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./cpu-load/cpu[@number='all']/@nice"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./cpu-load/cpu[@number='all']/@system"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./cpu-load/cpu[@number='all']/@iowait"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./cpu-load/cpu[@number='all']/@steal"/>
|
|
<xsl:text> </xsl:text>
|
|
</xsl:for-each>
|
|
</xsl:template>
|
|
</xsl:stylesheet>
|
|
EOF
|
|
}
|
|
|
|
cpu_gnuplot() {
|
|
# Create the GNUplot rendering file, largely based on "isag" Tk script from sysstat package
|
|
#set yrange [0:100]
|
|
cat > $1 <<EOF
|
|
set term x11
|
|
set title "sar -u"
|
|
set ylabel "Percent"
|
|
set timefmt "%H:%M:%S"
|
|
set xdata time
|
|
set format x "%H:%M"
|
|
plot "$2" using 1:2 t "%user" with line, "$2" using 1:3 t "%nice" with line, "$2" using 1:4 t "%system" with line, "$2" using 1:5 t "%iowait" with line, "$2" using 1:6 t "%steal" with line
|
|
pause mouse
|
|
EOF
|
|
}
|
|
|
|
# To output to a file change the gnuplot routines to say something like:
|
|
# set term svg
|
|
# ...
|
|
# set output "/tmp/test.svg"
|
|
# plot ...
|
|
|
|
# Graph for "sar -q"
|
|
|
|
rq_xslt() {
|
|
# Create the XSLT transform to make a GNUplot data file out of "sar -q" type data
|
|
# test with "sadf -x | xsltproc <file containing stuff below> -
|
|
cat > $1 <<EOF
|
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
<xsl:strip-space elements="*"/>
|
|
<xsl:template match="/sysstat/host/statistics">
|
|
<xsl:text> </xsl:text>
|
|
<xsl:for-each select="timestamp">
|
|
<xsl:value-of select="@time"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./queue/@runq-sz"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./queue/@plist-sz"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./queue/@ldavg-1"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./queue/@ldavg-5"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./queue/@ldavg-15"/>
|
|
<xsl:text> </xsl:text>
|
|
</xsl:for-each>
|
|
</xsl:template>
|
|
</xsl:stylesheet>
|
|
EOF
|
|
}
|
|
|
|
rq_gnuplot() {
|
|
cat > $1 <<EOF
|
|
set term x11
|
|
set title "sar -q"
|
|
set ylabel ""
|
|
set timefmt "%H:%M:%S"
|
|
set xdata time
|
|
set format x "%H:%M"
|
|
plot "$2" using 1:2 t "runq-sz" with line, "$2" using 1:3 t "plist-sz" with line, "$2" using 1:4 t "ldavg-1" with line, "$2" using 1:5 t "ldavg-5" with line, "$2" using 1:6 t "ldavg-15" with line
|
|
pause mouse
|
|
EOF
|
|
}
|
|
|
|
# Graph for "sar -q", but w/o the process list size
|
|
|
|
rqnoplistsz_xslt() {
|
|
# Create the XSLT transform to make a GNUplot data file out of "sar -q" type data
|
|
# test with "sadf -x | xsltproc <file containing stuff below> -
|
|
cat > $1 <<EOF
|
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
<xsl:strip-space elements="*"/>
|
|
<xsl:template match="/sysstat/host/statistics">
|
|
<xsl:text> </xsl:text>
|
|
<xsl:for-each select="timestamp">
|
|
<xsl:value-of select="@time"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./queue/@runq-sz"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./queue/@ldavg-1"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./queue/@ldavg-5"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./queue/@ldavg-15"/>
|
|
<xsl:text> </xsl:text>
|
|
</xsl:for-each>
|
|
</xsl:template>
|
|
</xsl:stylesheet>
|
|
EOF
|
|
}
|
|
|
|
rqnoplistsz_gnuplot() {
|
|
cat > $1 <<EOF
|
|
set term x11
|
|
set title "sar -q"
|
|
set ylabel ""
|
|
set timefmt "%H:%M:%S"
|
|
set xdata time
|
|
set format x "%H:%M"
|
|
plot "$2" using 1:2 t "runq-sz" with line, "$2" using 1:3 t "ldavg-1" with line, "$2" using 1:4 t "ldavg-5" with line, "$2" using 1:5 t "ldavg-15" with line
|
|
pause mouse
|
|
EOF
|
|
}
|
|
|
|
# Graph for "sar -b"
|
|
|
|
io_xslt() {
|
|
# Create the XSLT transform to make a GNUplot data file out of "sar -b" type data
|
|
# test with "sadf -x | xsltproc <file containing stuff below> -
|
|
cat > $1 <<EOF
|
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
<xsl:strip-space elements="*"/>
|
|
<xsl:template match="/sysstat/host/statistics">
|
|
<xsl:text> </xsl:text>
|
|
<xsl:for-each select="timestamp">
|
|
<xsl:value-of select="@time"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./io/tps"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./io/io-reads/@rtps"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./io/io-writes/@wtps"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./io/io-reads/@bread"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./io/io-writes/@bwrtn"/>
|
|
<xsl:text> </xsl:text>
|
|
</xsl:for-each>
|
|
</xsl:template>
|
|
</xsl:stylesheet>
|
|
EOF
|
|
}
|
|
|
|
io_gnuplot() {
|
|
cat > $1 <<EOF
|
|
set term x11
|
|
set title "sar -b"
|
|
set ylabel "ops/s"
|
|
set timefmt "%H:%M:%S"
|
|
set xdata time
|
|
set format x "%H:%M"
|
|
plot "$2" using 1:2 t "rtps" with line, "$2" using 1:3 t "wtps" with line, "$2" using 1:4 t "bread/s" with line, "$2" using 1:5 t "bwrtn/s" with line
|
|
pause mouse
|
|
EOF
|
|
}
|
|
|
|
# Graph for "sar -n NFS"
|
|
|
|
nfsclient_xslt() {
|
|
# Create the XSLT transform to make a GNUplot data file out of "sar -n NFS" type data
|
|
# test with "sadf -x | xsltproc <file containing stuff below> -
|
|
cat > $1 <<EOF
|
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
<xsl:strip-space elements="*"/>
|
|
<xsl:template match="/sysstat/host/statistics">
|
|
<xsl:text> </xsl:text>
|
|
<xsl:for-each select="timestamp">
|
|
<xsl:value-of select="@time"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./network/net-nfs/@call"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./network/net-nfs/@retrans"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./network/net-nfs/@read"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./network/net-nfs/@write"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./network/net-nfs/@access"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./network/net-nfs/@getatt"/>
|
|
<xsl:text> </xsl:text>
|
|
</xsl:for-each>
|
|
</xsl:template>
|
|
</xsl:stylesheet>
|
|
EOF
|
|
}
|
|
|
|
nfsclient_gnuplot() {
|
|
cat > $1 <<EOF
|
|
set term x11
|
|
set title "sar -n NFS"
|
|
set ylabel "ops/s"
|
|
set timefmt "%H:%M:%S"
|
|
set xdata time
|
|
set format x "%H:%M"
|
|
plot "$2" using 1:2 t "call/s" with line, "$2" using 1:3 t "retrans/s" with line, "$2" using 1:4 t "read/s" with line, "$2" using 1:5 t "write/s" with line, "$2" using 1:6 t "access/s" with line, "$2" using 1:7 t "getatt/s" with line
|
|
pause mouse
|
|
EOF
|
|
}
|
|
|
|
# Graph for "sar -B"
|
|
|
|
paging_xslt() {
|
|
# Create the XSLT transform to make a GNUplot data file out of "sar -B" type data
|
|
# test with "sadf -x | xsltproc <file containing stuff below> -
|
|
cat > $1 <<EOF
|
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
<xsl:strip-space elements="*"/>
|
|
<xsl:template match="/sysstat/host/statistics">
|
|
<xsl:text> </xsl:text>
|
|
<xsl:for-each select="timestamp">
|
|
<xsl:value-of select="@time"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./paging/@pgpgin"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./paging/@pgpgout"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./paging/@fault"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./paging/@majflt"/>
|
|
<xsl:text> </xsl:text>
|
|
</xsl:for-each>
|
|
</xsl:template>
|
|
</xsl:stylesheet>
|
|
EOF
|
|
}
|
|
|
|
paging_gnuplot() {
|
|
cat > $1 <<EOF
|
|
set term x11
|
|
set title "sar -B"
|
|
set ylabel "pages/s"
|
|
set timefmt "%H:%M:%S"
|
|
set xdata time
|
|
set format x "%H:%M"
|
|
plot "$2" using 1:2 t "pgpgin/s" with line, "$2" using 1:3 t "pgpgout/s" with line, "$2" using 1:4 t "fault/s" with line, "$2" using 1:5 t "majflt/s" with line
|
|
pause mouse
|
|
EOF
|
|
}
|
|
|
|
# Graph for "sar -r"
|
|
|
|
memuse_xslt() {
|
|
# Create the XSLT transform to make a GNUplot data file out of "sar -r" type data
|
|
# test with "sadf -x | xsltproc <file containing stuff below> -
|
|
cat > $1 <<EOF
|
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
<xsl:strip-space elements="*"/>
|
|
<xsl:template match="/sysstat/host/statistics">
|
|
<xsl:text> </xsl:text>
|
|
<xsl:for-each select="timestamp">
|
|
<xsl:value-of select="@time"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./memory/memfree"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./memory/memused"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./memory/buffers"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./memory/cached"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./memory/swpfree"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./memory/swpused"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./memory/swpcad"/>
|
|
<xsl:text> </xsl:text>
|
|
</xsl:for-each>
|
|
</xsl:template>
|
|
</xsl:stylesheet>
|
|
EOF
|
|
}
|
|
|
|
memuse_gnuplot() {
|
|
cat > $1 <<EOF
|
|
set term x11
|
|
set title "sar -r"
|
|
set ylabel "kB"
|
|
set timefmt "%H:%M:%S"
|
|
set xdata time
|
|
set format x "%H:%M"
|
|
plot "$2" using 1:2 t "kbmemfree" with line, "$2" using 1:3 t "kbmemused" with line, "$2" using 1:4 t "kbbuffers" with line, "$2" using 1:5 t "kbcached" with line, "$2" using 1:6 t "swpfree" with line, "$2" using 1:7 t "swpused" with line, "$2" using 1:8 t "swpcad" with line
|
|
pause mouse
|
|
EOF
|
|
}
|
|
|
|
# Graph for "sar -S"
|
|
|
|
swapuse_xslt() {
|
|
# Create the XSLT transform to make a GNUplot data file out of "sar -r" type data
|
|
# test with "sadf -x | xsltproc <file containing stuff below> -
|
|
cat > $1 <<EOF
|
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
<xsl:strip-space elements="*"/>
|
|
<xsl:template match="/sysstat/host/statistics">
|
|
<xsl:text> </xsl:text>
|
|
<xsl:for-each select="timestamp">
|
|
<xsl:value-of select="@time"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./memory/swpfree"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./memory/swpused"/>
|
|
<xsl:text> </xsl:text>
|
|
<xsl:value-of select="./memory/swpcad"/>
|
|
<xsl:text> </xsl:text>
|
|
</xsl:for-each>
|
|
</xsl:template>
|
|
</xsl:stylesheet>
|
|
EOF
|
|
}
|
|
|
|
swapuse_gnuplot() {
|
|
cat > $1 <<EOF
|
|
set term x11
|
|
set title "sar -S"
|
|
set ylabel "kB"
|
|
set timefmt "%H:%M:%S"
|
|
set xdata time
|
|
set format x "%H:%M"
|
|
plot "$2" using 1:2 t "swpfree" with line, "$2" using 1:3 t "swpused" with line, "$2" using 1:4 t "swpcad" with line
|
|
pause mouse
|
|
EOF
|
|
}
|
|
|
|
|
|
SA_FILES=`$FIND "$SA_DIR" -type f -printf '%T@,%p\n' \
|
|
| grep -E "$SA_REGEX" | $SORT -n -r | $CUT -d, -f2`
|
|
|
|
# Main loop
|
|
|
|
DONE=no
|
|
while [ $DONE != yes ]
|
|
do
|
|
|
|
# Prompt for sa file
|
|
|
|
SA_FILE=`$ZENITY --list --text "Select data source" \
|
|
--column "sa file" $SA_FILES`
|
|
|
|
if [ "$SA_FILE" == "" ]
|
|
then
|
|
exit
|
|
fi
|
|
|
|
if echo $SA_FILE | grep '.gz$'
|
|
then
|
|
UNCOMPRESSED_SA_FILE=`mktemp`
|
|
gzip -dc $SA_FILE > $UNCOMPRESSED_SA_FILE
|
|
SA_FILE=$UNCOMPRESSED_SA_FILE
|
|
fi
|
|
|
|
|
|
# Prompt for graph
|
|
|
|
GRAPH=`$ZENITY --list --text "Select a graph" --column "Graph Type" "CPU" "Run Queue" "Run Queue w/o Process List Size" "IO Transfer Rate" "NFS Client" "Paging Stats" "Memory Utilization" "Memory Utilization (Swap)"`
|
|
|
|
case "$GRAPH" in
|
|
"CPU")
|
|
XSLTFILE=`mktemp`
|
|
cpu_xslt $XSLTFILE
|
|
DATAFILE=`mktemp`
|
|
$SADF -t -x $SA_FILE -- -u | $XSLTPROC --novalid $XSLTFILE - > $DATAFILE
|
|
GNUPLOTFILE=`mktemp`
|
|
cpu_gnuplot $GNUPLOTFILE $DATAFILE
|
|
$GNUPLOT $GNUPLOTFILE
|
|
;;
|
|
"Run Queue")
|
|
XSLTFILE=`mktemp`
|
|
rq_xslt $XSLTFILE
|
|
DATAFILE=`mktemp`
|
|
$SADF -t -x $SA_FILE -- -q | $XSLTPROC --novalid $XSLTFILE - > $DATAFILE
|
|
GNUPLOTFILE=`mktemp`
|
|
rq_gnuplot $GNUPLOTFILE $DATAFILE
|
|
$GNUPLOT $GNUPLOTFILE
|
|
;;
|
|
"Run Queue w/o Process List Size")
|
|
XSLTFILE=`mktemp`
|
|
rqnoplistsz_xslt $XSLTFILE
|
|
DATAFILE=`mktemp`
|
|
$SADF -t -x $SA_FILE -- -q | $XSLTPROC --novalid $XSLTFILE - > $DATAFILE
|
|
GNUPLOTFILE=`mktemp`
|
|
rqnoplistsz_gnuplot $GNUPLOTFILE $DATAFILE
|
|
$GNUPLOT $GNUPLOTFILE
|
|
;;
|
|
"IO Transfer Rate")
|
|
XSLTFILE=`mktemp`
|
|
io_xslt $XSLTFILE
|
|
DATAFILE=`mktemp`
|
|
$SADF -t -x $SA_FILE -- -b | $XSLTPROC --novalid $XSLTFILE - > $DATAFILE
|
|
GNUPLOTFILE=`mktemp`
|
|
io_gnuplot $GNUPLOTFILE $DATAFILE
|
|
$GNUPLOT $GNUPLOTFILE
|
|
;;
|
|
"NFS Client")
|
|
XSLTFILE=`mktemp`
|
|
nfsclient_xslt $XSLTFILE
|
|
DATAFILE=`mktemp`
|
|
$SADF -t -x $SA_FILE -- -n NFS | $XSLTPROC --novalid $XSLTFILE - > $DATAFILE
|
|
GNUPLOTFILE=`mktemp`
|
|
nfsclient_gnuplot $GNUPLOTFILE $DATAFILE
|
|
$GNUPLOT $GNUPLOTFILE
|
|
;;
|
|
"Paging Stats")
|
|
XSLTFILE=`mktemp`
|
|
paging_xslt $XSLTFILE
|
|
DATAFILE=`mktemp`
|
|
$SADF -t -x $SA_FILE -- -B | $XSLTPROC --novalid $XSLTFILE - > $DATAFILE
|
|
GNUPLOTFILE=`mktemp`
|
|
paging_gnuplot $GNUPLOTFILE $DATAFILE
|
|
$GNUPLOT $GNUPLOTFILE
|
|
;;
|
|
"Memory Utilization")
|
|
XSLTFILE=`mktemp`
|
|
memuse_xslt $XSLTFILE
|
|
DATAFILE=`mktemp`
|
|
$SADF -t -x $SA_FILE -- -r | $XSLTPROC --novalid $XSLTFILE - > $DATAFILE
|
|
GNUPLOTFILE=`mktemp`
|
|
memuse_gnuplot $GNUPLOTFILE $DATAFILE
|
|
$GNUPLOT $GNUPLOTFILE
|
|
;;
|
|
"Memory Utilization (Swap)")
|
|
XSLTFILE=`mktemp`
|
|
swapuse_xslt $XSLTFILE
|
|
DATAFILE=`mktemp`
|
|
$SADF -t -x $SA_FILE -- -S | $XSLTPROC --novalid $XSLTFILE - > $DATAFILE
|
|
GNUPLOTFILE=`mktemp`
|
|
swapuse_gnuplot $GNUPLOTFILE $DATAFILE
|
|
$GNUPLOT $GNUPLOTFILE
|
|
;;
|
|
*)
|
|
# If you click "Cancel", you end up here
|
|
DONE=yes
|
|
;;
|
|
esac
|
|
|
|
[ -f "$UNCOMPRESSED_SA_FILE" ] && rm $UNCOMPRESSED_SA_FILE
|
|
[ -f "$GNUPLOTFILE" ] && rm $GNUPLOTFILE
|
|
[ -f "$DATAFILE" ] && rm $DATAFILE
|
|
[ -f "$XSLTFILE" ] && rm $XSLTFILE
|
|
done
|
|
|
|
exit
|
|
|
|
# Local Variables:
|
|
# sh-basic-offset: 4
|
|
# indent-tabs-mode: nil
|
|
# sh-indent-for-case-label: 0
|
|
# sh-indent-for-case-alt: +
|
|
# End:
|