9

I'm relatively new to Shell and I've been trying to use arrays in Shell and it's not working well. I'm trying to write a script to suspend OpenVZ containers should they hit a certain bandwidth threshold over a period of time.

My script:

#!/bin/bash
#Thresholds are in bytes per second and count1 must > count2
LOGDIR="/var/log/outbound_ddos"
SECS=10
THRESHOLD1=65536000
COUNT1=10
THRESHOLD2=117964800
COUNT2=2

while [ 1 ]
do
    for veid in $(/usr/sbin/vzlist -o veid -H)
    do      
        # Create the log file if it doesn't already exist
        if ! test -e $LOGDIR/$veid.log; then
            touch $LOGDIR/$veid.log
        fi

        # Parse out the inbound/outbound traffic and assign them to the corresponding variables     
        eval $(/usr/sbin/vzctl exec $veid "grep venet0 /proc/net/dev"  |  \
            awk -F: '{print $2}' | awk '{printf"CTOUT=%s\n", $9}')

        # Print the output and a timestamp to a log file
        echo $(date +%s) $CTOUT >> $LOGDIR/$veid.log

        # Read last 10 entries into arrays
        i=0
        tail $LOGDIR/$veid.log | while read time byte
        do
            times[$i]=time; bytes[$i]=byte
            let i++
        done

        # Sanity checks and calculations
        for (( i=0; i<COUNT1; i++ ))
        do
            # Sanity check on the time
            if (( times[$i] > times[$i - 1] + $SECS + 10 ))
                then continue
            fi

            # Calculate differences
            let "diff[$i] = bytes[$i+1] - bytes[$i]"
        done

        # Work out thresholds and suspend where necessary
        # Higher threshold first
        t2=0
                for (( i=COUNT1-1; i>=0; i-- ))
                do
                        if [ ! diff[$i] ]
                                then continue
                                else
                                        if (( bytes[$i] < THRESHOLD1 * SECS + bytes[$i-1] + 1 ))
                                                then continue
                        else let t2++
                                        fi
                        fi
                done
        #Lower threshold last
        t1=0
        for (( i=COUNT1-1; i>=0; i-- ))
        do
            if [ ! diff[$i] ]
                then continue
                else
                    if (( bytes[$i] < THRESHOLD1 * SECS + bytes[$i-1] + 1 ))
                        then continue
                        else let t1++
                    fi
            fi
        done

        # Suspend where necessary
        if (( ($t2 >= $COUNT2) || ($t1 >= $COUNT1) ))
            then vzctl stop veid
        fi
    done
    sleep $SECS
done

And the errors:

script.sh: line 38: times: bad array subscript
script.sh: line 54: bytes: bad array subscript
script.sh: line 67: bytes: bad array subscript

I've tried several variations of the array subscript but I can't seem to get rid of those errors.

8
  • You're missing quite a few $ all over the place. e.g. should be times[$i] for instance. Commented Apr 20, 2013 at 12:13
  • Apologies, I've amended the post. Same errors though. Commented Apr 20, 2013 at 12:18
  • @Mat actually the $ sign is not required inside an array subscript. Commented Apr 20, 2013 at 12:24
  • @kojiro: hum, indeed seems to work. Confusing though. Commented Apr 20, 2013 at 12:29
  • @Mat It's a context thing. Array subscripts are arithmetic context, same as (( )) arithmetic expressions. So OP could write times[i]=time; bytes[i++]=byte on line 30. Commented Apr 20, 2013 at 12:30

1 Answer 1

12

So on line 38,

if (( times[$i] > times[$i - 1] + $SECS + 10 ))

would refer to times[-1] once during the iteration. Negative indices are only very recently part of bash arrays, so that is most likely why you are getting the error.

Likewise with lines 54 and 67 you're hitting a negative array subscript once. Adjust your loops to avoid [0 - 1].

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.