#!/bin/bash 

# This script will generate a single 95th percentile figure for
# a given rrd file. It will pull all in and out values for a
# given time period and dump them to a text file. Next it checks
# line by line, which value is bigger (in or out traffic) and
# dumps the larger to a separate file. NaN values are replaced
# with the last recorded value. This final list is sorted,
# and the value 5% down from the top is taken, as is typical
# of 95th percentile billing.
# jwbensley@gmail.com

# Example
# ./95th.sh 1358502298 1358761498 /var/lib/cacti/rra/castle-cpe_traffic_in_11664.rrd

# Blank out a file and dump a given time range of values from rrd file
echo "" > rrd_values
rrdtool fetch -s $1 -e $2 $3 AVERAGE > rrd_values
# Remove the titles
sed -i 1,+1d rrd_values

# Blank out a new file;
# Now we are going to iterate through each time period dumped
# from the rrd file and see which value is bigger, in traffic
# or out traffic, then dump the bigger of the two values in 
# to this new file
echo "" > rrd_values_max

# Sometimes rrd logs "nan", we will replace those values
# with the value at the last working interval, same as
# PRIV function in rrdtool
LASTIN=0.0
LASTOUT=0.0

file="./rrd_values"
while IFS= read -r line
do
	if [ "`echo $line| awk '{printf $2}'`" == "nan" ]
	then
		INNOW="$LASTIN"
	else
		INNOW=`echo $line | awk '{printf "%f", $2}'`
		LASTIN="$INNOW"
	fi
        if [ "`echo $line| awk '{printf $3}'`" == "nan" ]
        then
		OUTNOW="$LASTOUT"
	else
		OUTNOW=`echo $line | awk '{printf "%f", $3}'`
		LASTOUT="$OUTNOW"
	fi
	echo | awk -v n1=$INNOW -v n2=$OUTNOW '{if (n1>n2) printf ("%s\n", n1); else if (n2>n1) printf ("%s\n", n2); else printf ("%s\n", n2);}' >> rrd_values_max
done < "$file"

# Now we have filled ./rrd_values_max with the MAX value from each
# time period, sorted then in desending order
sort -g -r rrd_values_max > rrd_values_max_sorted
# Remove any blank lines (typically one on the end)
sed '/^$/d' rrd_values_max_sorted > rrd_values_max_sorted_trim
# Count the number of lines of rrd values
count=`grep -c ^ rrd_values_max_sorted_trim`
# Get 5 percent of the line count value
NUM=$(echo "scale=4; ($count/100)*5" | bc)
# Round it off
NUM=$(awk -v n1=$NUM 'BEGIN {print int(n1)}')
# Now read the value from the line, 5% down from the top
# of the line count of the file
NUM=`awk -v n1=$NUM 'NR==n1' rrd_values_max_sorted_trim`
# Again, round that off
NUM=$(awk -v n1=$NUM 'BEGIN {print int(n1)}')
# Converts to Kbps
NUM=$(echo "($NUM*8)/1000" | bc)
echo -e "$NUM"

# Clean up
rm rrd_values
rm rrd_values_max
rm rrd_values_max_sorted
rm rrd_values_max_sorted_trim 
