【问题标题】:Unix Shell: Summing up values, one per line but skipping every nth rowUnix Shell:汇总值,每行一个,但每隔 n 行跳过
【发布时间】:2013-10-29 21:35:32
【问题描述】:

我正在尝试设计一个 Unix shell 脚本(最好是通用 sh),它将获取一个内容为数字的文件,每行一个。这些数字是从 mpstat 获得的 CPU 空闲时间:

cat ${PARSE_FILE} | awk '{print $13}' | grep "^[!0-9]" > temp.txt

所以文件是一个列表,如果是数字,比如:

46.19
93.41
73.60
99.40
95.80
96.00
77.10
99.20
52.76
81.18
69.38
89.80
97.00
97.40
76.18
97.10

这些值的真正含义是第 1 行用于核心 1,第 2 行用于核心 2,等等...对于 X 个核心(在我的情况下为 8) - 所以每第 9 行再次用于核心 1 等...

原始文件如下所示:

10/28/2013  Linux 2.6.32-358.el6.x86_64 (host)  10/28/2013  _x86_64_    

(32 CPU)
10/28/2013  
10/28/2013  02:25:05 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest   %idle
10/28/2013  02:25:15 PM    0   51.20    0.00    2.61    0.00    0.00    0.00    0.00    0.00   46.19
10/28/2013  02:25:15 PM    1    6.09    0.00    0.50    0.00    0.00    0.00    0.00    0.00   93.41
10/28/2013  02:25:15 PM    2   25.20    0.00    1.20    0.00    0.00    0.00    0.00    0.00   73.60
10/28/2013  02:25:15 PM    3    0.40    0.00    0.20    0.00    0.00    0.00    0.00    0.00   99.40
10/28/2013  02:25:15 PM    4    3.80    0.00    0.40    0.00    0.00    0.00    0.00    0.00   95.80
10/28/2013  02:25:15 PM    5    3.70    0.00    0.30    0.00    0.00    0.00    0.00    0.00   96.00
10/28/2013  02:25:15 PM    6   21.70    0.00    1.20    0.00    0.00    0.00    0.00    0.00   77.10
10/28/2013  02:25:15 PM    7    0.70    0.00    0.10    0.00    0.00    0.00    0.00    0.00   99.20
10/28/2013  02:25:25 PM    0   45.03    0.00    1.61    0.00    0.00    0.60    0.00    0.00   52.76
10/28/2013  02:25:25 PM    1   17.82    0.00    1.00    0.00    0.00    0.00    0.00    0.00   81.18
10/28/2013  02:25:25 PM    2   29.62    0.00    1.00    0.00    0.00    0.00    0.00    0.00   69.38
10/28/2013  02:25:25 PM    3    9.70    0.00    0.40    0.00    0.00    0.10    0.00    0.00   89.80
10/28/2013  02:25:25 PM    4    2.40    0.00    0.60    0.00    0.00    0.00    0.00    0.00   97.00
10/28/2013  02:25:25 PM    5    2.00    0.00    0.60    0.00    0.00    0.00    0.00    0.00   97.40
10/28/2013  02:25:25 PM    6   22.92    0.00    0.90    0.00    0.00    0.00    0.00    0.00   76.18
10/28/2013  02:25:25 PM    7    2.40    0.00    0.50    0.00    0.00    0.00    0.00    0.00   97.10

我正在尝试设计一个脚本,它将核心数量和这个文件作为一个变量,并让我得到每个核心的平均值,但我不知道该怎么做。这是我所拥有的:

cat ${PARSE_FILE} | awk '{print $13}' | grep "^[!0-9]" > temp.txt
NUMBER_OF_CORES=8
NUMBER_OF_LINES=`awk ' END { print NR } ' temp.txt`
NUMBER_OF_VALUES=`echo "scale=0;${NUMBER_OF_LINES}/${NUMBER_OF_CORES}" | bc`
for i in `seq 1 ${NUMBER_OF_CORES}`
do
  awk 'NR % $i == 0' temp.txt
  echo Core: ${i} Average: xx
done

所以我有每个核心具有的值的数量(核心上的行),所以这是我需要跳过的每第 n 行,但我不知道如何干净地做到这一点。我基本上需要在文件中循环每个“NUMBER_OF_CORES”次,跳过每个“NUMBER_OF_CORES”行并将它们相加除以“NUMBER_OF_VALUES”。

【问题讨论】:

    标签: shell unix scripting


    【解决方案1】:

    这样可以吗?

    awk '/CPU/&&/idle/{f=1;next}f{a[$4]+=$13;b[$4]++}END{for(i in a){print i,a[i]/b[i]}}' your_file
    

    其实这里不需要核数。它将计算文件中所有可用内核的平均空闲时间

    测试:

    > cat temp
    10/28/2013  Linux 2.6.32-358.el6.x86_64 (host)  10/28/2013  _x86_64_    
    
    (32 CPU)
    10/28/2013  
    10/28/2013  02:25:05 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest   %idle
    10/28/2013  02:25:15 PM    0   51.20    0.00    2.61    0.00    0.00    0.00    0.00    0.00   46.19
    10/28/2013  02:25:15 PM    1    6.09    0.00    0.50    0.00    0.00    0.00    0.00    0.00   93.41
    10/28/2013  02:25:15 PM    2   25.20    0.00    1.20    0.00    0.00    0.00    0.00    0.00   73.60
    10/28/2013  02:25:15 PM    3    0.40    0.00    0.20    0.00    0.00    0.00    0.00    0.00   99.40
    10/28/2013  02:25:15 PM    4    3.80    0.00    0.40    0.00    0.00    0.00    0.00    0.00   95.80
    10/28/2013  02:25:15 PM    5    3.70    0.00    0.30    0.00    0.00    0.00    0.00    0.00   96.00
    10/28/2013  02:25:15 PM    6   21.70    0.00    1.20    0.00    0.00    0.00    0.00    0.00   77.10
    10/28/2013  02:25:15 PM    7    0.70    0.00    0.10    0.00    0.00    0.00    0.00    0.00   99.20
    10/28/2013  02:25:25 PM    0   45.03    0.00    1.61    0.00    0.00    0.60    0.00    0.00   52.76
    10/28/2013  02:25:25 PM    1   17.82    0.00    1.00    0.00    0.00    0.00    0.00    0.00   81.18
    10/28/2013  02:25:25 PM    2   29.62    0.00    1.00    0.00    0.00    0.00    0.00    0.00   69.38
    10/28/2013  02:25:25 PM    3    9.70    0.00    0.40    0.00    0.00    0.10    0.00    0.00   89.80
    10/28/2013  02:25:25 PM    4    2.40    0.00    0.60    0.00    0.00    0.00    0.00    0.00   97.00
    10/28/2013  02:25:25 PM    5    2.00    0.00    0.60    0.00    0.00    0.00    0.00    0.00   97.40
    10/28/2013  02:25:25 PM    6   22.92    0.00    0.90    0.00    0.00    0.00    0.00    0.00   76.18
    10/28/2013  02:25:25 PM    7    2.40    0.00    0.50    0.00    0.00    0.00    0.00    0.00   97.10
    > nawk '/CPU/&&/idle/{f=1;next}f{a[$4]+=$13;b[$4]++}END{for(i in a){print i,a[i]/b[i]}}' temp
    2 71.49
    3 94.6
    4 96.4
    5 96.7
    6 76.64
    7 98.15
    0 49.475
    1 87.295
    > 
    

    【讨论】:

    • 这里有很多很好的答案,但根据我的需要,这是最好的。它简单直接。在末尾添加“| sort -n”会按照 CPU 编号的顺序排列。
    【解决方案2】:

    countCores.sh 下面的脚本是基于你在 temp.txt 中提供的数据 这可能不是你想要的,但会给你一些想法。我不确定 您想要的总体总平均值是多少,所以我只选择显示这些值的平均值 在所有 8 个内核的第一列中。我还用 cat -n 来表示核心数。 希望这可以帮助。冯贝尔

    #!/bin/bash
    #Execute As: countCores.sh temp.txt 8
    AllCoreTotals=0
    DataFile="$1"
    NumCores="$2"
    AllCoreTotals=0
    NumLines="`cat -n $DataFile|cut -f1|tail -1|tr -d " "`"
    PrtCols="`echo $NumLines / $NumCores|bc`"
    clear;echo;echo
    echo "============================================================="
    pr -t${PrtCols} $DataFile|tr -d "\t"|tr -s " "  "+"|bc |\
    while read CoreTotal
        do
           CoreAverage=`echo $CoreTotal / $PrtCols|bc`
           echo "$CoreTotal     Core Average $CoreAverage"
           AllCoreTotals="`echo $CoreTotal + $AllCoreTotals|bc`"
           echo "$AllCoreTotals"  > AllCoreTot.tmp
        done|cat -n
    AllCoreAverage=`cat AllCoreTot.tmp`
    AllCoreAverage="`echo $AllCoreAverage / $NumCores|bc`"
    echo "============================================================="
    echo "(Col One) Total Core Average: $AllCoreAverage "
    rm $DataFile
    rm AllCoreTot.tmp
    

    【讨论】:

      【解决方案3】:

      为什么不同时对所有内核执行此操作:

      awk -f prog.awk ${PARSE_FILE}
      

      然后在prog.awk

          {   if ((NF == 13) && ($4 != "CPU"))
              {   SUM[$4] += $13;
                  CNT[$4]++;
              }
          }
      END {   for(loop in SUM)
              {   printf("CPU: %d  Total: %d  Count: %d  Average: %d\n",
                          loop, SUM[loop], CNT[loop], SUM[loop]/CNT[loop]);
              }
          }
      

      如果你想在一行上做:

      awk '{if ((NF == 13) && ($4 != "CPU")){SUM[$4] += $13;CNT[$4]++;}} END {for(loop in SUM){printf("CPU: %d  Total: %d  Count: %d  Average: %d\n", loop, SUM[loop], CNT[loop], SUM[loop]/CNT[loop]);}}'  ${PARSE_FILE}
      

      【讨论】:

        【解决方案4】:

        经过更多研究,这个 sn-p 似乎可以解决问题:

        #Parse logs to get CPU averages for cores
        PARSE_FILE=`ls ~/logs/*mpstat*`
        echo "Parsing ${PARSE_FILE}..."
        cat ${PARSE_FILE} | awk '{print $13}' | grep "^[!0-9]" > temp.txt
        NUMBER_OF_CORES=8
        NUMBER_OF_LINES=`awk ' END { print NR } ' temp.txt`
        NUMBER_OF_VALUES=`echo "scale=0;${NUMBER_OF_LINES}/${NUMBER_OF_CORES}" | bc`
        TOTAL=0
        for i in `seq 1 ${NUMBER_OF_CORES}`
        do
          sed -n $i'~'$NUMBER_OF_CORES'p' temp.txt > temp2.txt
          SUM=`awk '{s+=$0} END {print s}' temp2.txt`
          AVERAGE=`echo "scale=0;${SUM}/${NUMBER_OF_VALUES}" | bc`
          echo Core: ${i} Average: `expr 100 - ${AVERAGE}`
          TOTAL=$((TOTAL+${AVERAGE}))
        done
        TOTAL_AVERAGE=`echo "scale=0;${TOTAL}/${NUMBER_OF_CORES}" | bc`
        echo "Total Average: `expr 100 - ${TOTAL_AVERAGE}`"
        rm temp*.txt
        

        【讨论】:

          猜你喜欢
          • 2016-07-16
          • 2015-05-29
          • 2011-11-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-02-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多