1

こんにちは私はawkで/proc/ Interruptsファイルからeth割り込みの数を読み取り、CPUコアごとの割り込みの総数を見つけるためのスクリプトが必要です。それから私はそれらをbashで使用したいと思います。ファイルの内容は次のとおりです。

      CPU0       CPU1       CPU2       CPU3

47:   33568      45958      46028      49191     PCI-MSI-edge    eth0-rx-0
48:     0          0          0          0       PCI-MSI-edge      eth0-tx-0
49:     1          0          1          0       PCI-MSI-edge      eth0
50:   28217      42237      65203      39086     PCI-MSI-edge    eth1-rx-0
51:     0          0          0          0       PCI-MSI-edge      eth1-tx-0
52:     0          1          0          1       PCI-MSI-edge      eth1
59:     114991     338765      77952     134850  PCI-MSI-edge eth4-rx-0
60:     429029     315813     710091      26714  PCI-MSI-edge eth4-tx-0
61:      5          2          1          5      PCI-MSI-edge     eth4
62:    1647083     208840    1164288     933967  PCI-MSI-edge eth5-rx-0
63:     673787    1542662     195326    1329903  PCI-MSI-edge eth5-tx-0
64:     5          6          7          4       PCI-MSI-edge      eth5

私はこのコードでawkを使用してこのファイルを読んでいます:

#!/bin/bash

 FILE="/proc/interrupts"

 output=$(awk 'NR==1 {
 core_count = NF 
 print core_count
 next
}
/eth/ {
 for (i = 2; i <= 2+core_count; i++)
 totals[i-2] += $i
}

END {
 for (i = 0; i < core_count; i++)
 printf("%d\n", totals[i])
}
' $FILE)

core_count=$(echo $output | cut -d' ' -f1)

output=$(echo $output | sed 's/^[0-9]*//')

totals=(${output// / })

このアプローチでは、スクリプトで並べ替えるために、コアごとの合計コア数を処理してから、COREごとの合計割り込みを処理しますが、これでは、合計配列の数のみを処理できます。

    totals[0]=22222
    totals[1]=33333

しかし、CPUコアの名前を持つタプルとしてそれらを処理する必要があります。

    totals[0]=(cPU1,2222)
    totals[1]=(CPU',3333)

名前を配列に割り当て、themnを読み取ってSEDのタプルとしてbashする必要があると思います。どうすればこれを達成できますか?

4

1 に答える 1

0

まず第一に、bashには「タプル」のようなものはありません。そして、アレイは完全にフラットです。これは、「スカラー」変数、またはスカラーの1つのレベルの配列があることを意味します。

あなたが直面している課題にはいくつかのアプローチがあります。また:

  1. 十分に新しいbash(4.2 AFAIR)を使用している場合は、連想配列(ハッシュ、マップ、またはどのように呼んでも)を使用できます。次に、CPU名がキーになり、数値が値になります。
  2. 奇数のインデックスがキー(CPU名)と偶数のキー(値)を持つプレーン配列(perlのようなハッシュ)を作成します。
  3. 2つの別々の配列を作成します。1つはCPU名を使用し、もう1つは値を使用します。
  4. =CPU名を記号(または)で値から区切って、単一の配列を作成します:

最初にアプローチ2について説明しましょう。

#!/bin/bash

FILE="/proc/interrupts"

output=$(awk 'NR==1 {
    core_count = NF
    for (i = 1; i <= core_count; i++)
        names[i-1] = $i
    next
}
/eth/ {
    for (i = 2; i <= 2+core_count; i++)
        totals[i-2] += $i
}

END {
    for (i = 0; i < core_count; i++)
        printf("%s %d\n", names[i], totals[i])
}
' ${FILE})

core_count=$(echo "${output}" | wc -l)
totals=(${output})

スクリプトを単純にするために変更したいくつかの点に注意してください。

  1. awkは、1行に1つずつ、単一のスペースで区切られた `cpu-namenumber'を出力するようになりました。
  2. コア数はawkによって出力されません(前処理出力を回避するため)が、代わりに出力の行数から推定されます。
  3. 配列は出力をフラット化するtotalsことによって作成されます—スペースと改行の両方が空白として扱われ、値を区切るために使用されます。

結果の配列は次のようになります。

totals=( CPU0 12345 CPU1 23456 ) # ...

それを繰り返すには、次のようなものを使用できます(簡単な方法):

set -- "${totals[@}}"
while [[ $# -gt 0 ]]; do
    cpuname=${1}
    value=${2}

    # ...

    shift;shift
done

それでは、アプローチ1用に変更してみましょう。

#!/bin/bash

FILE="/proc/interrupts"

output=$(awk 'NR==1 {
    core_count = NF
    for (i = 1; i <= core_count; i++)
        names[i-1] = $i
    next
}
/eth/ {
    for (i = 2; i <= 2+core_count; i++)
        totals[i-2] += $i
}

END {
    for (i = 0; i < core_count; i++)
        printf("[%s]=%d\n", names[i], totals[i])
}
' ${FILE})

core_count=$(echo "${output}" | wc -l)
declare -A totals
eval totals=( ${output} )

ご了承ください:

  1. awkの出力形式は、連想配列のセマンティクスに合わせて変更されました。
  2. totalsdeclare -A連想配列( )として宣言され、
  3. 悲しいことに、evalbashに出力を直接処理させるために使用する必要があります。

結果の配列は次のようになります。

declare -A totals=( [CPU0]=12345 [CPU1]=23456 )

そして今、あなたは使うことができます:

echo ${totals[CPU0]}

for cpu in "${!totals[@]}"; do
    echo "For CPU ${cpu}: ${totals[${cpu}]}"
done

3番目のアプローチは、さまざまな方法で実行できます。の2回の読み取りを許可できると仮定すると、次の/proc/interruptsこともできます。

FILE="/proc/interrupts"

output=$(awk 'NR==1 {
    core_count = NF
    next
}
/eth/ {
    for (i = 2; i <= 2+core_count; i++)
        totals[i-2] += $i
}

END {
    for (i = 0; i < core_count; i++)
        printf("%d\n", totals[i])
}
' ${FILE})

core_count=$(echo "${output}" | wc -l)
names=( $(cat /proc/interrupts | head -n 1) )
totals=( ${output} )

そのため、awkは再びカウントのみを出力し、名前はbashによって/proc/interrupts直接の最初の行から取得されます。または、アプローチ(2)で取得した単一の配列から分割配列を作成するか、awk出力を別の方法で解析することもできます。

結果は2つの配列になります。

names=( CPU0 CPU1 )
totals=( 12345 23456 )

そして出力:

for (( i = 0; i < core_count; i++ )); do
    echo "${names[$i]} -> ${totals[$i]}"
done

そして最後のアプローチ:

#!/bin/bash

FILE="/proc/interrupts"

output=$(awk 'NR==1 {
    core_count = NF
    for (i = 1; i <= core_count; i++)
        names[i-1] = $i
    next
}
/eth/ {
    for (i = 2; i <= 2+core_count; i++)
        totals[i-2] += $i
}

END {
    for (i = 0; i < core_count; i++)
        printf("%s=%d\n", names[i], totals[i])
}
' ${FILE})

core_count=$(echo "${output}" | wc -l)
totals=( ${output} )

これで、(通常の)配列は次のようになります。

totals=( CPU0=12345 CPU1=23456 )

そして、次のように解析できます。

for x in "${totals[@]}"; do
    name=${x%=*}
    value=${x#*=}
    echo "${name} -> ${value}"
done

(CPU名と値の分割はループで発生することに注意してください)。

于 2012-07-23T08:21:40.943 に答える