【问题标题】:Bash - Script goes from 3% CPU usage to 100% when run for a long timeBash - 脚本长时间运行时 CPU 使用率从 3% 变为 100%
【发布时间】:2014-01-29 10:37:10
【问题描述】:

我编写了一个收集一些系统统计信息的脚本。这与压力测试一起运行,以便可以收集有关系统的 sats。收集的统计数据包括 CPU 使用率(使用 sar)、内存使用率(使用 free)、中断等。正在收集的每个数据点都通过将其置于后台而产生到单独的进程中。进行了一些后处​​理以将此数据移动到 csv 文件,以便可以在电子表格中打开它。后期处理也发生在衍生过程中。该脚本在收集的样本之间有一个睡眠间隔。但是,在此时间间隔内,后台进程仍在运行。

我观察到,当这个脚本运行很长时间时,单独这个脚本的 CPU 使用率逐渐从 3% 左右增加到几乎 100% 。这是一个令人不安的场景,因为不允许分析脚本占用如此多的 CPU 时间。 (我使用“top”来记录每个进程的 CPU 使用情况”)。

另一个有趣的观察是,在压力测试中运行的重型进程占用的 CPU 时间比这个脚本要少(在它的使用率超过 90% 之后)。

如何解决?我在这里缺少什么吗?请指教。

在下面添加一些代码位。以下是主循环。

while true
do

    if [ $exitstatus = 0 ]
    then
        exitScript
    fi
    let itr++
    echo -e "\n Interation: $itr\n"

    if [ "$3" = "ALL" ]
    then
        export CALC_INTERRUPTS=1
        printTitle "sar"
        processCommand "sar" &

        #printTitle "free"
        processCommand "free" &

        printTitle "interrupts"
        processCommand "interrupts" &

        printTitle "underflows"
        processCommand "underflows" &


        #printTitle "clocktree"
        processCommand "clocktree" &

    else    
        if [ $itr -eq 1 ]
        then
            shift 2
        fi
        for com in "$@"
        do
            printTitle "$com"
            processCommand "$com" &

        done
    fi
    #printTimestamp > $TEMP_LOC/sys.log
    cat /var/log/syslog > $TEMP_LOC/sys.log
    if [ $exitstatus = 0 ]
    then
        exitScript
    fi
    sleep $interval
    #Wait for background jobs from the last iteration to finish     
    for job in `jobs -p`
    do      
        wait $job 
    done

    cat $TEMP_LOC/*.temp >> $TEMP_LOC/monitor.log
    rm -f $TEMP_LOC/*.temp

    if [ $(($itr % 180)) -eq 0 ] 
    then
        takeDump
    fi

done

fi

以下是CPU使用率的记录和后期处理(使用sar)-

processCommand()
{

case "$1" in
sar)
    printTimestamp>> $TEMP_LOC/$1.temp
    #echo -n " Logging CPU stats............ "
    exe="sar -P ALL 1 1"
    $exe > $TEMP_LOC/temp_sar

    echo -e "\n\n Processes using more than 1% of CPU time: " >> $TEMP_LOC/$1.temp
    top -b -n 1 > $TEMP_LOC/temp_top



    #delete all lines except current CPU statistics
    sed -i "5,8! d" $TEMP_LOC/temp_sar
    #replace all spaces with commas
    sed -i  's/[[:space:]]\+/,/g' $TEMP_LOC/temp_sar

    Cpu=0
    while [ -s $TEMP_LOC/temp_sar ]
    do
        #if file does not exist then add the header 
        if [ ! -f $TEMP_LOC/Cpu$Cpu.csv ]
        then
            printf "time,$Cpu.us,$Cpu.ni,$Cpu.sy,$Cpu.wa,$Cpu.st,$Cpu.id,$Cpu.total\n"  >> $TEMP_LOC/Cpu$Cpu.csv
        fi
        #remove  CPU number 
        stats=`sed -n '1p' $TEMP_LOC/temp_sar | cut -d ',' --complement -f 2`

        idle=`echo $stats | cut -d ',' -f 7`
        #calculate totale CPU usage as 100-idle
        total_usage=$(bc <<< "100.00-$idle")
        echo "$stats,$total_usage" >> $TEMP_LOC/Cpu$Cpu.csv

        sed -i '1d' $TEMP_LOC/temp_sar
        let Cpu++

    done

    ;;

代码的其他部分也类似地工作。定期拍摄该参数的快照并对其进行一些后期处理。

【问题讨论】:

  • 能发一下脚本内容吗
  • 您是否将所有数据都保存在内存中?您是覆盖 CSV 文件还是只是追加新数据?
  • 线程数逐渐增加?另请注意,总 CPU% 是 top 中的 CPU%/CPU-cores。
  • @choroba,是的,所有数据都在内存中。我挂载 RAMFS 并将所有临时数据保存在上面。
  • @krampstudio,脚本很大(大约 500 行左右)。要我粘贴整个内容吗?

标签: linux bash cpu cpu-usage


【解决方案1】:

尝试在 /proc“文件”上使用单个 awk,而不是使用多个工具,例如 free,sar,ps -C...

time awk ' /MemTotal/ {print $2}; /SwapCached/ {print $2}; /processor/ {print $NF}' /proc/meminfo /proc/cpuinfo 
1933536
17840
0
1

real    0m0.002s
user    0m0.000s
sys 0m0.000s

使用单个脚本而不在 shell 上保留变量,您将避免一些内存/cpu 泄漏,例如您忘记在每个循环中清理的 shell 变量,然后您对其执行一些 grep..

【讨论】:

  • 内存泄漏会导致 CPU 使用率飙升吗?
  • no.. 但是如果这个 shell 脚本的内存在增长,可能会暴露一些不断使用的变量而没有被清理,并且操纵巨大的变量会使 CPU 使用率飙升 ps。对不起英语不好
  • 感谢 BrenoZan。会尝试相同的:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-22
  • 2019-02-12
  • 1970-01-01
相关资源
最近更新 更多