6

作成中のスクリプトのマルチパス出力を Linux で解析しようとしていますが、正しい SED または AWK 構文を見つけて、希望どおりに取得することができません。私はさまざまなサイトやスタックオーバーフローの例を閲覧してきましたが、あまり運がありませんでした。

私は作る方法を見つけたい:

temp (360a98000572d4d2d5834566c64536b46) dm-4 NETAPP,LUN
[size=20G]
2:0:0:4  sde        8:64  [active][ready]
1:0:0:4  sdm        8:192 [active][ready]
redo (360a98000572d4d2d5834566c646c366c) dm-3 NETAPP,LUN
[size=5.0G]
2:0:0:3  sdd        8:48  [active][ready]
1:0:0:3  sdl        8:176 [active][ready]

のように見える:

temp (360a98000572d4d2d5834566c64536b46) dm-4 NETAPP,LUN [size=20G] 2:0:0:4  sde        8:64  active][ready]
temp (360a98000572d4d2d5834566c64536b46) dm-4 NETAPP,LUN [size=20G] 1:0:0:4  sdm        8:192 [active][ready]
redo (360a98000572d4d2d5834566c646c366c) dm-3 NETAPP,LUN [size=5.0G] 2:0:0:3  sdd        8:48  [active][ready]
redo (360a98000572d4d2d5834566c646c366c) dm-3 NETAPP,LUN [size=5.0G] 1:0:0:3  sdl        8:176 [active][ready]

** 編集 OK、これをさらに難しくしているのは、Netapp のデフォルト設定のないマルチパス構成を見つけたことです。これにより、NETAPP,LUN がオンラインであることが保証されなくなります。私が始めたこと:

/sbin/multipath -ll | grep -v "round-robin"| sed 's/\[feat.*//g' | sed ':a; $!N;s/\n\([^\n]*\[size\)/ \1/;ta;P;D'

これにより、メインラインにサイズが追加され、一致する他の何かが得られます。

360a98000572d4d2d5834664e68323436 dm-6 NETAPP,LUN [size=50G]
\_ 1:0:0:0  sda 8:0   [active][ready]
360a98000572d4d2d5834664e68395951 dm-7 NETAPP,LUN [size=275G]
\_ 1:0:0:7  sdb 8:16  [active][ready]

ただし、「G[$」に一致する以下の例を取得できず (テラバイトのボリュームがある場合は、T に別の行が必要になることはわかっています)、正しい出力が得られます。

以下の皆さんの提案に感謝します **編集終了

間隔をクリーンアップする方法を知っているので、正しい出力が得られたらそれを行います。マルチパス情報を開始する行はすべて「LUN」で終わります。サーバーは、各 LUN ライン (sdx デバイス) の下に 1 ~ 8 個のパスを持つことができます。「()」の前の部分は、テキスト (エイリアス) または数値のいずれかです。

4

7 に答える 7

2

一方通行:

の内容script.awk:

$1 ~ /^([[:digit:]]:){3}[[:digit:]]$/ {
    printf "%s %s\n", line, $0; 
    next;
}

##$1 ~ /temp|redo/ {
$0 ~ /LUN$/ {
    getline l;
    line = $0 " " l;
}

質問の内容を想定infileして、次のようにスクリプトを実行します。

awk -f script.awk infile

次の出力で:

temp (360a98000572d4d2d5834566c64536b46) dm-4 NETAPP,LUN [size=20G] 2:0:0:4  sde        8:64  [active][ready]                                                                                                                                
temp (360a98000572d4d2d5834566c64536b46) dm-4 NETAPP,LUN [size=20G] 1:0:0:4  sdm        8:192 [active][ready]                                                                                                                                
redo (360a98000572d4d2d5834566c646c366c) dm-3 NETAPP,LUN [size=5.0G] 2:0:0:3  sdd        8:48  [active][ready]                                                                                                                               
redo (360a98000572d4d2d5834566c646c366c) dm-3 NETAPP,LUN [size=5.0G] 1:0:0:3  sdl        8:176 [active][ready]
于 2012-08-22T20:04:15.643 に答える
1

これはうまくいくかもしれません(GNU sed):

sed '/LUN$/{N;y/\n/ /;h;d};G;s/^\([^\n]*\)\n\(.*\)/\2 \1/' file

説明:

  • /LUN$/{N;y/\n/ /;h;d}で終わる行LUNの場合、改行を追加してから次の行をパターン スペース (PS) に追加し、改行をスペースに置き換え、PS をホールド スペース (HS) に格納してから PS を削除し、次のサイクルにスターを付けます。
  • G他のすべての行 (パス行) については、改行を追加し、その後に PS の HS の内容を続けます。
  • s/^\([^\n]*\)\n\(.*\)/\2 \1/最初の改行までのものをその後に続くものと交換し、改行をスペースに置き換えます。つまり、ヘッダー情報をパス行に追加します。
于 2012-08-23T05:47:06.380 に答える
1

入力の正確な仕様はわかりませんが、次のワンライナーが役立つ場合があります。

awk '{if (/LUN$/){ prefix = $0; getline; prefix = prefix " " $0 } else {print prefix, $0} }'

  1. /LUN$/現在の行がLUNで終わっているかどうかをチェックします(正規表現と照合することにより)
  2. 一致する場合は、現在の行を次の行と連結します (getline暗黙の連結演算子を使用) 。
  3. 一致がない場合は、現在のレコードと一緒に出力しますprefix

PS:追加の行フィルタリングが必要になる場合がありますが、これは難しいことではありません。ブランチに別ifの行を追加するだけです。else

于 2012-08-22T20:00:30.727 に答える
0

これは、あなたと同様の問題のクラス全体に対する一般的な解決策です。つまり、複数の行にまたがるレコードセットを解析しますが、レコードセット間で行数が異なる場合があります。

sed '/([0-9a-f]\{33\})/ i \\' input_file | \
  awk '
    BEGIN {RS=""; FS="\n"}
    {for(i=3; i<=NF; i++) {print $1,$2,$i}}
  '

与える

temp (360a98000572d4d2d5834566c64536b46) dm-4 NETAPP,LUN [size=20G] 2:0:0:4  sde        8:64  [active][ready]
temp (360a98000572d4d2d5834566c64536b46) dm-4 NETAPP,LUN [size=20G] 1:0:0:4  sdm        8:192 [active][ready]
redo (360a98000572d4d2d5834566c646c366c) dm-3 NETAPP,LUN [size=5.0G] 2:0:0:3  sdd        8:48  [active][ready]
redo (360a98000572d4d2d5834566c646c366c) dm-3 NETAPP,LUN [size=5.0G] 1:0:0:3  sdl        8:176 [active][ready]

このソリューションのプロパティ

  • 16 進ダイジェストのレコードを識別します
  • 1 つ以上のパスを処理
  • awk では各マルチパス レコードがレコードと見なされるため、awk でより多くのロジックを実装するために簡単に拡張できます。

説明

入力データが次のようになっていると想像してください。

temp (360a98000572d4d2d5834566c64536b46) dm-4 NETAPP,LUN
[size=20G]
2:0:0:4  sde        8:64  [active][ready]
1:0:0:4  sdm        8:192 [active][ready]

redo (360a98000572d4d2d5834566c646c366c) dm-3 NETAPP,LUN
[size=5.0G]
2:0:0:3  sdd        8:48  [active][ready]
1:0:0:3  sdl        8:176 [active][ready]

これは awk で簡単に解析できます。
awkにそれを伝えるだけです..

  1. 各レコードは空白行で区切られています
  2. 各フィールドは行全体である必要があります
  3. 次に、目的の結果を得るために、すべての行 (フィールド) が使い果たされるまで、「最初の行、2 番目の行、i. 番目の行」の組み合わせを出力します。

これはまさに上記の awk-code が行っていることです:
BEGIN {RS=""; FS="\n"}はレコード sep を設定します。空白行とフィールド sep に。改行に。
{for(i=3; i<=NF; i++) {print $1,$2,$i}}は、3. の下で前に概説したことを正確に実行します。

ここで必要なのは、空白行を導入してレコードを区切ることだけ
です。このタスクには sed を使用します。前に空白行を導入する行を見つけるためのアンカーが必要なだけです。ここでは、括弧内に 16 進ダイジェストを使用します。私は常に33文字の長さを想定しています。

于 2012-08-23T11:20:37.350 に答える
0

マルチパスの性質上、LUN は 2 つだけでなく 1 つ以上のパスを持つことができます。したがって、getline() は醜いループに入る可能性があります。これは明確な awk バージョンです。考慮しなければならないのは、LUN 行、SIZE 行、および PATH 行をマークする方法だけです。

awk '/\(.*\)/ {lu=$0} /^\[size/ {size=$0} $2 ~ /sd/ {print lu, size, $0}'

ただし、 multipath -l には、ポリシーやパラメーターなど、はるかに複雑な情報が含まれる場合があります。

于 2012-08-23T02:58:48.120 に答える
0

sed を使用:

sed -n '
  # if this is header append the size line
  /LUN$/{
    N;
    s/\n/ /;
    h       # and remember this
  }; 
  # if not header then append to header
  /LUN \[/!{ 
    G; 
    s/\(.*\)\n\(.*\)/\2 \1/;
    p; #and print
  }' input_file

コメントを省く:

 sed -n ' /LUN$/{ N; s/\n/ /; h  }; /LUN \[/!{ G; s/\(.*\)\n\(.*\)/\2 \1/; p; }' input_file
于 2012-08-22T19:59:03.080 に答える
0

編集:

awk '/\[size=.*G\]/ { array[prev]++ } { prev = $0 } FNR!=NR { if ($0 in array) { line = $0; getline; line = line FS $0; next } else { print line, $0 } }' file.txt{,}

説明:

## file.txt{,}    
## this is bash shorthand for reading the same file twice

## { prev = $0 }
## keep track of the last line

## /\[size=.*G\]/ { array[prev]++ }
## if the 'size' pattern is found, add the previous line to an array
## now we have an array of lines to search for

## FNR!=NR
## perform the following actions on the second file only

## if ($0 in array)
## if the line is one of our lines that we're searching for

## line = $0; getline; line = line FS $0; next
## store the line, get the next line join it up and go onto the next record

## else { print line, $0 }
## otherwise print out the 'line' and subsequent data

結果:

temp (360a98000572d4d2d5834566c64536b46) dm-4 NETAPP,LUN [size=20G] 2:0:0:4  sde        8:64  [active][ready]
temp (360a98000572d4d2d5834566c64536b46) dm-4 NETAPP,LUN [size=20G] 1:0:0:4  sdm        8:192 [active][ready]
redo (360a98000572d4d2d5834566c646c366c) dm-3 NETAPP,LUN [size=5.0G] 2:0:0:3  sdd        8:48  [active][ready]
redo (360a98000572d4d2d5834566c646c366c) dm-3 NETAPP,LUN [size=5.0G] 1:0:0:3  sdl        8:176 [active][ready]
于 2012-08-23T11:33:59.933 に答える