#!/bin/bash TARGET="$1" function everythingelse() { #Verify that one parameter was passed if [ -z "$TARGET" ]; then echo "Syntax Error: must specify target directory" exit 1 fi #Verify that it is a valid directory if [ ! -d "$TARGET" ]; then echo "ERROR: Invalid directory ${TARGET}" exit 1 fi #Verify that it is a writeable directory if [ ! -w "$TARGET" ]; then echo "ERROR: You do not have write permissions to ${TARGET}" exit 1 fi #Verify that it is a readable directory if [ ! -r "$TARGET" ]; then echo "ERROR: You do not have read permissions to ${TARGET}" exit 1 fi #Verify that is an executable directory if [ ! -x "$TARGET" ]; then echo "ERROR: You do not have execute permissions to ${TARGET}" exit 1 fi if [ -z $(which bonnie++) ]; then echo "ERROR: Could not find bonnie++ in PATH, please install bonnie++" exit 1 fi #Verify that it is a valid fstab entry IN_FSTAB=$(egrep ".*[ \\t]*${TARGET}[ \\t]*.*" /etc/fstab | tail -n1 | wc -l) if [ $IN_FSTAB -eq 0 ]; then echo "ERROR: Could not find mountpoint ${TARGET}" exit 1 fi #Verify that it is mounted IN_MTAB=$(egrep ".*[ \\t]*${TARGET}[ \\t]*.*" /etc/mtab | tail -n1 | wc -l) if [ $IN_MTAB -eq 0 ]; then #Attempt to mount the directory echo "${TARGET} is not mounted, attempting to mount" mount "${TARGET}" >/dev/null 2>/dev/null if [ $? -ne 0 ]; then echo "ERROR: could not mount ${TARGET}" exit 1 fi fi #Grab the device information from fstab FSTAB_LINE=$(egrep ".*[ \\t]*${TARGET}[ \\t]*.*" /etc/fstab | tail -n1) DEVICE=$(echo "${FSTAB_LINE}" | awk '{print $1}') FSTYPE=$(echo "${FSTAB_LINE}" | awk '{print $3}') #Confirm the test echo -n "Start bonnie benchmark on ${DEVICE}? (y/N) " read answer if [ "$answer" != "y" ] && [ "$answer" != "Y" ]; then echo "Cancelled by user" exit 1 fi #Unmount the directory echo -n "Unmounting filesystem on ${DEVICE}........" umount ${TARGET} >/dev/null 2>/dev/null if [ $? -ne 0 ]; then echo "ERROR: Could not unmount ${TARGET}" exit 1 fi echo "OK" if [ "$FSTYPE" = "ext3" ]; then #Tune2fs the filesystem echo -n "Setting dir_index on ${DEVICE}........" tune2fs -O dir_index ${DEVICE} >/dev/null 2>/dev/null if [ $? -ne 0 ]; then echo "ERROR: Could not set dir_index on filesystem" exit 1 fi echo "OK" #Optimize directories echo -n "Optimizing directories on ${DEVICE}........" fsck.ext3 -n -D ${DEVICE} >/dev/null 2>/dev/null if [ $? -ne 0 ]; then echo "Could not optimize directories on ${DEVICE}, please run fsck on the filesystem to fix any errors" exit 1 fi echo "OK" fi #Get a temp dir name and make it MYTMPDIR=/tmp/bonnie_bench_$(date +%s%N | sha1sum | awk '{print $1}') mkdir $MYTMPDIR || (echo "ERROR: Could not make tmp directory ${MYTMPDIR}" && exit 1) #Logic to set readahead IS_MD=$(echo ${DEVICE} | egrep -c 'md[0-9]') IS_HDD=$(echo ${DEVICE} | egrep -c '[sh]d[a-z][0-9]') RA_DEVS="" if [ $IS_MD -eq 1 ]; then RA_DEVS=$(mdadm -D ${DEVICE} | grep active | egrep -o '[sh]d[a-z]' | sort -u) elif [ $IS_HDD -eq 1 ]; then RA_DEVS=$(echo ${DEVICE} | egrep -o '[sh]d[a-z]') else echo "ERROR: Unknown device type: ${DEVICE}" exit 1 fi for RAVALUE in 16384 32768 65536; do echo "========================================" echo "Beginning test for read-ahead value: ${RAVALUE}" #Set the readahead for any applicable devices for RA_DEV in ${RA_DEVS}; do blockdev --setra ${RAVALUE} /dev/${RA_DEV} >/dev/null 2>/dev/null if [ $? -ne 0 ]; then echo "ERROR: Could not set readahead on ${RA_DEV}" exit 1 fi done #Dump all caches if [ -f /proc/sys/vm/drop_caches ]; then echo -n "Dumping system cache......." (sync && echo "3">/proc/sys/vm/drop_caches) if [ $? -ne 0 ]; then echo "ERROR: Could not drop caches" exit 1 fi echo "OK" fi #Mount the filesystem mount ${TARGET} >/dev/null 2>/dev/null if [ $? -ne 0 ]; then echo "ERROR: Could not mount fs on ${DEVICE}" exit 1 fi #Actually run bonnie bonnie++ -d ${TARGET} -n 128 -u 0 -r $(free -m | grep ^Mem | awk '{print $2}') -s $(echo 2*$(free -m | grep ^Mem |awk '{print $2}')|bc) -f -b > ${MYTMPDIR}/run.${RAVALUE}.out #Unmount the filesystem umount ${TARGET} >/dev/null 2>/dev/null if [ $? -ne 0 ]; then echo "ERROR: Could not unmount fs on ${DEVICE}" exit 1 fi done #Write the data necessary to make the graphs PLOTFILE_RO="${MYTMPDIR}/plotdata_ro" PLOTFILE_BO="${MYTMPDIR}/plotdata_bo" PLOTFILE_BI="${MYTMPDIR}/plotdata_bi" echo "#x rewrite_output" > ${PLOTFILE_RO} echo "#x block_output" > ${PLOTFILE_BO} echo "#x block_input" > ${PLOTFILE_BI} X=23 for RAVALUE in 16384 32768 65536; do RESULT_LINE=$(tail -n1 "${MYTMPDIR}/run.${RAVALUE}.out") BLOCK_OUTPUT=$(echo "scale=2;$(echo \"${RESULT_LINE}\"|cut -d, -f5)/1000" | bc) RW_OUTPUT=$(echo "scale=2;$(echo \"${RESULT_LINE}\"|cut -d, -f7)/1000" | bc) BLOCK_INPUT=$(echo "scale=2;$(echo \"${RESULT_LINE}\"|cut -d, -f11)/1000" | bc) echo "${X} ${BLOCK_OUTPUT}" >> "${PLOTFILE_BO}" X=$(($X + 2)) echo "${X} ${BLOCK_INPUT}" >> "${PLOTFILE_BI}" X=$(($X + 2)) echo "${X} ${RW_OUTPUT}" >> "${PLOTFILE_RO}" X=$(($X + 2)) X=$(($X + 19)) done #Make the output graph PLOT_IMG="bonnie_out.png" gnuplot << EOF set terminal png set output "${PLOT_IMG}" set title "Bonnie Output Benchmark on $(hostname):${TARGET}" set xlabel "Disk readahead in sectors" set ylabel "Speed in M/sec" set xtics ( "16384" 25, "32768" 50, "65536" 75 ) set xrange [0:100] set xtics nomirror set grid set boxwidth 1 set style fill plot \ "${PLOTFILE_BO}" title "Block Output" with boxes fs solid,\ "${PLOTFILE_RO}" title "Rewrite Output" with boxes fs solid EOF #Make the input graph PLOT_IMG="bonnie_in.png" gnuplot << EOF set terminal png set output "${PLOT_IMG}" set title "Bonnie Input Benchmark on $(hostname):${TARGET}" set xlabel "Disk readahead in sectors" set ylabel "Speed in M/sec" set xtics ( "16384" 25, "32768" 50, "65536" 75 ) set xrange [0:100] set xtics nomirror set boxwidth 1 set style fill plot \ "${PLOTFILE_BI}" title "Block Input" with boxes fs solid EOF #Write the data necessary for text column output COLFILE="${MYTMPDIR}/coldata" echo "" > "${COLFILE}" for RAVALUE in 16384 32768 65536; do RESULT_LINE=$(tail -n1 "${MYTMPDIR}/run.${RAVALUE}.out") BLOCK_OUTPUT=$(echo "scale=2;$(echo \"${RESULT_LINE}\"|cut -d, -f5)/1000" | bc) RW_OUTPUT=$(echo "scale=2;$(echo \"${RESULT_LINE}\"|cut -d, -f7)/1000" | bc) BLOCK_INPUT=$(echo "scale=2;$(echo \"${RESULT_LINE}\"|cut -d, -f11)/1000" | bc) echo "${RAVALUE}|${BLOCK_OUTPUT}|${RW_OUTPUT}|${BLOCK_INPUT}" >> ${COLFILE} done #Make a column text output and print it while also saving it to bonnie.out ( echo "Readahead|Block Output|Rewrite Output|Block Input" echo "==|==|==|==" cat "${COLFILE}" ) | column -s '|' -t | tee bonnie.out rm -fr "${MYTMPDIR}"