|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | + |
| 4 | +set -e |
| 5 | + |
| 6 | + |
| 7 | +# Our dependencies - bail out if they are not found |
| 8 | +SADF=`which sadf` |
| 9 | +GNUPLOT=`which gnuplot` |
| 10 | + |
| 11 | + |
| 12 | +# Default for --sa-file is today's file |
| 13 | +# (by default sadf will show today's logs) |
| 14 | +SA_FILE="" |
| 15 | + |
| 16 | +# Default for --sa-dir |
| 17 | +SA_DIR="/var/log/sa" |
| 18 | + |
| 19 | +# Default for --type |
| 20 | +GRAPH_TYPE=CPU |
| 21 | + |
| 22 | + |
| 23 | +GNUPLOT_TERMINAL="pngcairo font \"Sans,8\" size 640,320" |
| 24 | +SAFILES_REGEX='/sar?[0-9]{2,8}(\.(Z|gz|bz2|xz|lz|lzo))?$' |
| 25 | +GRAPH_TYPES="cpu,mem,io" |
| 26 | + |
| 27 | + |
| 28 | +print_usage() |
| 29 | +{ |
| 30 | + echo " |
| 31 | +Usage |
| 32 | + sargraph2 [--type $GRAPH_TYPES] [--sa-file INFILE] [--output OUTFILE] |
| 33 | +
|
| 34 | +Examples |
| 35 | +
|
| 36 | +To plot CPU for today no arguments are needed: |
| 37 | + sargraph2 |
| 38 | +To plot MEM for 20150330: |
| 39 | + sargraph2 --type mem --sa-file /var/log/sa/sa20150330.gz |
| 40 | +To plot I/O for 20150330 to a PNG file: |
| 41 | + sargraph2 --type mem --sa-file /var/log/sa/sa20150330.gz --output io.png |
| 42 | +
|
| 43 | +" |
| 44 | +} |
| 45 | + |
| 46 | + |
| 47 | +######### OPTION PARSING ########### |
| 48 | +parsed_opts=`getopt -o "h" \ |
| 49 | + -l help,sa-dir:,sa-file:,output:,type: \ |
| 50 | + -- "$@"` |
| 51 | +eval set -- "$parsed_opts" |
| 52 | + |
| 53 | +DONE=no |
| 54 | +while [ $DONE != yes ] |
| 55 | +do |
| 56 | + case $1 in |
| 57 | + -h|--help) |
| 58 | + print_usage |
| 59 | + exit |
| 60 | + shift |
| 61 | + ;; |
| 62 | + --sa-dir) |
| 63 | + shift |
| 64 | + SA_DIR="$1" |
| 65 | + ;; |
| 66 | + --sa-file) |
| 67 | + shift |
| 68 | + SA_FILE="$1" |
| 69 | + ;; |
| 70 | + --output) |
| 71 | + shift |
| 72 | + OUT_FILE="$1" |
| 73 | + ;; |
| 74 | + --type) |
| 75 | + shift |
| 76 | + GRAPH_TYPE=`echo $1 | tr a-z A-Z` |
| 77 | + ;; |
| 78 | + --) |
| 79 | + # End of options |
| 80 | + DONE=yes |
| 81 | + ;; |
| 82 | + *) |
| 83 | + echo Unexpected argument: $1 |
| 84 | + exit 1 |
| 85 | + ;; |
| 86 | + esac |
| 87 | + |
| 88 | + shift # should shift the last arg or '--' if DONE=yes |
| 89 | +done |
| 90 | +#################################### |
| 91 | + |
| 92 | + |
| 93 | +# Decompress a file to another, or just copy it if not compressed |
| 94 | +decompress_copy() |
| 95 | +{ |
| 96 | + if [ x$# != x2 ] |
| 97 | + then |
| 98 | + echo "Function decompress_copy requires 2 arguments but got $#: $*" |
| 99 | + return 1 |
| 100 | + fi |
| 101 | + |
| 102 | + if [ -f "$1" ] |
| 103 | + then |
| 104 | + case "$1" in |
| 105 | + |
| 106 | + *.Z) uncompress -c "$1" > "$2" ;; |
| 107 | + *.gz) gzip -dc "$1" > "$2" ;; |
| 108 | + *.bz2) bzip2 -dc "$1" > "$2" ;; |
| 109 | + *.xz) xz -dc "$1" > "$2" ;; |
| 110 | + *.lz) lzip -dc "$1" > "$2" ;; |
| 111 | + *.lzo) lzop -dc "$1" > "$2" ;; |
| 112 | + |
| 113 | + *) cp "$1" "$2" ;; |
| 114 | + |
| 115 | + esac |
| 116 | + else |
| 117 | + echo "$1: file not found" 1>&2 |
| 118 | + return 1 |
| 119 | + fi |
| 120 | +} |
| 121 | + |
| 122 | + |
| 123 | + |
| 124 | + |
| 125 | +# TODO send systemd patch |
| 126 | +#soupermouf;60;2015-04-01 04:24:00;-1;5.77;0.00;2.10;0.63;0.00;91.50 |
| 127 | +#soupermouf;26846;2015-04-01 11:51:26;-1;0.00;0.00;0.00;0.00;0.00;0.00 |
| 128 | +#soupermouf;60;2015-04-01 11:52:26;-1;7.11;0.01;2.69;68.44;0.00;21.75 |
| 129 | + |
| 130 | +cpu_gnuplot() # %iowait,%user,%nice,%system,%steal |
| 131 | +{ |
| 132 | + # First make sure that the columns are where we expect them to be |
| 133 | + HEADER=`head -1 $2 | cut -d ';' -f 5-10` |
| 134 | + EXPECTED="%user;%nice;%system;%iowait;%steal;%idle" |
| 135 | + if [ "$HEADER" != "$EXPECTED" ] |
| 136 | + then |
| 137 | + echo "Headers not in right order: $HEADER" 1>&2 |
| 138 | + exit 1 |
| 139 | + fi |
| 140 | + |
| 141 | + cat > $1 <<EOF |
| 142 | +set title "sar -u" |
| 143 | +set xdata time |
| 144 | +set format x "%H:%M" |
| 145 | +set ylabel "Percentage" |
| 146 | +set yrange [0:100] |
| 147 | +set timefmt "%Y-%m-%d %H:%M:%S" |
| 148 | +set datafile separator ";" |
| 149 | +plot \ |
| 150 | + "$2" using 3:(\$9+\$7+\$6+\$5+\$8) title "%iowait" with filledcurves x1 linecolor rgb "light-gray", \ |
| 151 | + "$2" using 3:(\$9+\$7+\$6+\$5) title "%user" with filledcurves x1 linecolor rgb "dark-green", \ |
| 152 | + "$2" using 3:(\$9+\$7+\$6) title "%nice" with filledcurves x1 linecolor rgb "greenyellow", \ |
| 153 | + "$2" using 3:(\$9+\$7) title "%system" with filledcurves x1 linecolor rgb "red", \ |
| 154 | + "$2" using 3:(\$9) title "%steal" with filledcurves x1 linecolor rgb "purple" |
| 155 | +EOF |
| 156 | +} |
| 157 | + |
| 158 | + |
| 159 | +mem_gnuplot() # free,used,buffers,cached / %commit,%swpused |
| 160 | +{ |
| 161 | + # First make sure that the columns are where we expect them to be |
| 162 | + HEADER=`head -1 $2 | cut -d ';' -f 4-10` |
| 163 | + EXPECTED="kbmemfree;kbmemused;%memused;kbbuffers;kbcached;kbcommit;%commit" |
| 164 | + if [ "$HEADER" != "$EXPECTED" ] |
| 165 | + then |
| 166 | + echo "Headers not in right order: $HEADER" 1>&2 |
| 167 | + exit 1 |
| 168 | + fi |
| 169 | + HEADER=`head -1 $3 | cut -d ';' -f 4-6` |
| 170 | + EXPECTED="kbswpfree;kbswpused;%swpused" |
| 171 | + if [ "$HEADER" != "$EXPECTED" ] |
| 172 | + then |
| 173 | + echo "Headers not in right order: $HEADER" 1>&2 |
| 174 | + exit 1 |
| 175 | + fi |
| 176 | + |
| 177 | + cat > $1 <<EOF |
| 178 | +set title "sar -r" |
| 179 | +set xdata time |
| 180 | +set format x "%H:%M" |
| 181 | +set ylabel "Memory Usage in MB" |
| 182 | +set yrange [0:] |
| 183 | +set y2label "Percentage" |
| 184 | +set y2range [0:] |
| 185 | +set y2tics |
| 186 | +set timefmt "%Y-%m-%d %H:%M:%S" |
| 187 | +set datafile separator ";" |
| 188 | +set key on bottom center opaque |
| 189 | +plot \ |
| 190 | + "$2" using 3:((\$5+\$4)/1024) title "free" with filledcurves x1 linecolor rgb "light-gray", \ |
| 191 | + "$2" using 3:((\$5)/1024) title "cached" with filledcurves x1 linecolor rgb "dark-green", \ |
| 192 | + "$2" using 3:((\$5-\$8)/1024) title "buffers" with filledcurves x1 linecolor rgb "greenyellow", \ |
| 193 | + "$2" using 3:((\$5-\$8-\$7)/1024) title "used" with filledcurves x1 linecolor rgb "red", \ |
| 194 | + \ |
| 195 | + "$2" using 3:(\$10) title "%commit" with lines linecolor rgb "blue" linewidth 2 axes x1y2, \ |
| 196 | + "$3" using 3:(\$6) title "%swpused" with lines linecolor rgb "dark-magenta" linewidth 2 axes x1y2 |
| 197 | +EOF |
| 198 | +} |
| 199 | + |
| 200 | + |
| 201 | +io_gnuplot() # %KBr/s,KBw/s / rIOPS,wIOPS |
| 202 | +{ |
| 203 | + # First make sure that the columns are where we expect them to be |
| 204 | + HEADER=`head -1 $2 | cut -d ';' -f 4-8` |
| 205 | + EXPECTED="tps;rtps;wtps;bread/s;bwrtn/s" |
| 206 | + if [ "$HEADER" != "$EXPECTED" ] |
| 207 | + then |
| 208 | + echo "Headers not in right order: $HEADER" 1>&2 |
| 209 | + exit 1 |
| 210 | + fi |
| 211 | + |
| 212 | + cat > $1 <<EOF |
| 213 | +set title "sar -b" |
| 214 | +set xdata time |
| 215 | +set format x "%H:%M" |
| 216 | +set ylabel "MB/s" |
| 217 | +set yrange [0:] |
| 218 | +set y2label "IOPS" |
| 219 | +set y2range [0:] |
| 220 | +set y2tics |
| 221 | +set timefmt "%Y-%m-%d %H:%M:%S" |
| 222 | +set datafile separator ";" |
| 223 | +plot \ |
| 224 | + "$2" using 3:((\$8+\$7)*2/1024) title "rMB/s" with filledcurves x1 linecolor rgb "dark-green", \ |
| 225 | + "$2" using 3:((\$8)*2/1024) title "wMB/s" with filledcurves x1 linecolor rgb "dark-red", \ |
| 226 | + \ |
| 227 | + "$2" using 3:(\$4) title "rIOPS" with lines linecolor rgb "light-green" linewidth 2 axes x1y2, \ |
| 228 | + "$2" using 3:(\$6) title "wIOPS" with lines linecolor rgb "light-red" linewidth 2 axes x1y2 |
| 229 | +EOF |
| 230 | +} |
| 231 | + |
| 232 | + |
| 233 | + |
| 234 | + |
| 235 | +if [ x"$OUT_FILE" = x ] |
| 236 | +then |
| 237 | + # no --output passed, INTERACTIVE mode |
| 238 | + GNUPLOT_OPTS="-persist" |
| 239 | +else |
| 240 | + GNUPLOT_OPTS="-e 'set terminal $GNUPLOT_TERMINAL; set output \"$OUT_FILE\"'" |
| 241 | +fi |
| 242 | + |
| 243 | +if [ x"$SA_FILE" != x ] |
| 244 | +then |
| 245 | + # Decompress the SA file if it's compressed |
| 246 | + PLAIN_SA_FILE=`mktemp` |
| 247 | + decompress_copy "$SA_FILE" $PLAIN_SA_FILE |
| 248 | +else |
| 249 | + # If the user passed no parameter |
| 250 | + PLAIN_SA_FILE="" |
| 251 | +fi |
| 252 | +unset SA_FILE |
| 253 | + |
| 254 | +DATAFILE=`mktemp` |
| 255 | +DATAFILE2=`mktemp` |
| 256 | +GNUPLOTFILE=`mktemp` |
| 257 | + |
| 258 | +case "$GRAPH_TYPE" in |
| 259 | +"CPU") |
| 260 | + $SADF -t -d -C $PLAIN_SA_FILE -- -u > $DATAFILE |
| 261 | + cpu_gnuplot $GNUPLOTFILE $DATAFILE |
| 262 | + ;; |
| 263 | +"MEM") |
| 264 | + $SADF -t -d -C $PLAIN_SA_FILE -- -r > $DATAFILE |
| 265 | + $SADF -t -d -C $PLAIN_SA_FILE -- -S > $DATAFILE2 |
| 266 | + mem_gnuplot $GNUPLOTFILE $DATAFILE $DATAFILE2 |
| 267 | + ;; |
| 268 | +"IO") |
| 269 | + $SADF -t -d -C $PLAIN_SA_FILE -- -b > $DATAFILE |
| 270 | + io_gnuplot $GNUPLOTFILE $DATAFILE |
| 271 | + ;; |
| 272 | +*) |
| 273 | + echo "Unknown graph type, supported types are: $GRAPH_TYPES" 1>&2 |
| 274 | + exit 1 |
| 275 | +esac |
| 276 | + |
| 277 | +eval $GNUPLOT $GNUPLOT_OPTS $GNUPLOTFILE |
| 278 | + |
| 279 | + |
| 280 | +[ -f "$PLAIN_SA_FILE" ] && rm $PLAIN_SA_FILE |
| 281 | +[ -f "$GNUPLOTFILE" ] && rm $GNUPLOTFILE |
| 282 | +[ -f "$DATAFILE" ] && rm $DATAFILE |
| 283 | +[ -f "$DATAFILE2" ] && rm $DATAFILE2 |
| 284 | + |
| 285 | + |
| 286 | +exit |
| 287 | + |
| 288 | + |
| 289 | +# Local Variables: |
| 290 | +# sh-basic-offset: 4 |
| 291 | +# indent-tabs-mode: nil |
| 292 | +# sh-indent-for-case-label: 0 |
| 293 | +# sh-indent-for-case-alt: + |
| 294 | +# End: |
0 commit comments