bash 错误的数组下标

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16120155/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 23:36:57  来源:igfitidea点击:

Bad array subscript

arraysbashshell

提问by James

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.

我对 Shell 比较陌生,我一直在尝试在 Shell 中使用数组,但效果不佳。我正在尝试编写一个脚本来挂起 OpenVZ 容器,如果它们在一段时间内达到某个带宽阈值。

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 }' | awk '{printf"CTOUT=%s\n", }')

        # 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.

我已经尝试了数组下标的几种变体,但我似乎无法摆脱这些错误。

回答by kojiro

So on line 38,

所以在第 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.

times[-1]在迭代期间引用一次。负索引只是最近 bash arrays 的一部分,因此这很可能是您收到错误的原因。

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

同样,在第 54 行和第 67 行中,您会遇到一次负数组下标。调整循环以避免[0 - 1].