コード情報:

コード情報:

このbashスクリプトがあります。

gunzip -c /var/log/cisco/cisco.log-$(date +%Y%m%d).gz | awk '/ath_bstuck_tasklet/ { print $4 }' | sort | uniq -c > /tmp/netgear_beacon.txt
echo "There are  `wc -l /tmp/netgear_beacon.txt | awk '{print $1}'` Stuck beacon; resetting" >> /tmp/netgear_beacon.txt

gunzip -c /var/log/cisco/cisco.log-`date +%Y%m%d`.gz | awk '/Virtual device ath0 asks to queue packet/ { print $4 }' | sort | uniq -c > /tmp/netgear_buffer_queue.txt
echo "There are  `wc -l /tmp/netgear_buffer_queue.txt | awk '{print $1}'`  routers with 'Virtual device ath0 asks to queue packet' errors" >> /tmp/netgear_buffer_queue.txt

gunzip -c /var/log/cisco/cisco.log-`date +%Y%m%d`.gz | awk '/CMS_MSG_DNSPROXY_RELOAD/ { print $4 }' | sort | uniq -c > /tmp/netgear_dns.txt
echo "There are  `wc -l /tmp/netgear_dns.txt | awk '{print $1}'`  routers with 'DNS Proxy Issue' errors" >> /tmp/netgear_dns.txt

gunzip -c /var/log/cisco/cisco.log-$(date +%Y%m%d).gz | awk '/beacon/ { print $4 }' | sort | uniq -c > /tmp/netgear_beacon_frame.txt
echo "There are  `wc -l /tmp/netgear_beacon_frame.txt | awk '{print $1}'` routers with beacon frame errors" >> /tmp/netgear_beacon_frame.txt

gunzip -c /var/log/cisco/cisco.log-$(date +%Y%m%d).gz | awk '/ACK/ { print $4 }' | sort | uniq -c | awk -v x=50 '$1 >= x' > /tmp/netgear_ACK.txt
echo "There are  `wc -l /tmp/netgear_ACK.txt | awk '{print $1}'` routers with more than 50 ACK" >> /tmp/netgear_ACK.txt

gunzip私は毎回コマンドを繰り返さないようにしました。一度だけ実行し、すべての段階で使用します。変数を考えていますが、これはベストプラクティスですか?

答え1

「ベストプラクティス」はありません。理解し、仕事をより簡単にすることをしましょう。

共通部分を抽出して残りの部分をパラメータ化することは、次の問題です。

lines="`gunzip -c /var/log/cisco/cisco.log-$(date +%Y%m%d).gz`"
#gunzip would always output the same thing on the same day, so 
#just run it once and store the results in a variable
grepAndLog(){
  local regex="$1" file="$2" msg="$3" filter="${4:-cat}"
  #^names for positional parameters

  printf "%s\n" "$lines" | grep "$regex" | cut -d' ' -f4 | sort | uniq -c | eval "$filter"  > "/tmp/$file"
  local count=`wc -l < "/tmp/$file"`   
  echo "There are $count "" $msg" >> "/tmp/$file"
}
grepAndLog ath_bstuck_tasklet netgear_bacon.txt \
 'Stuck beacon; resetting'
grepAndLog netgear_buffer_queue netgear_buffer_queue.txt \
 "routers with 'Virtual device ath0 asks to queue packet' errors"
grepAndLog CMS_MSG_DNSPROXY_RELOAD netgear_dns.txt \
 " routers with 'DNS Proxy Issue' errors"
grepAndLog ath_bstuck_tasklet netgear_bacon.txt \
 " routers with beacon frame errors"
grepAndLog ACK netgear_ACK.txt \
 " routers with more than 50 ACK" 'awk -v x=50 "\$1 >= x"'

それでも主にシェルソリューションです。しかし、IMOではより読みやすく、長さも40%以上短いです。

コード情報:

代わりにawk式を使用していますgrep "$regex" | cut -d' ' -f4。それに加えて、このgrepAndLog関数はスクリプトの各行で実行する作業を一般化したものです。いくつかの入力(gunzipの出力)があり、それを式(引数$regex)に対してgrepし、結果行を出力し、ソートし、addプレフィックスをとして計算されます。次に、最初は一定で、最後では異なるメッセージに行$file数(代わりに追加wc -l < "$file")を追加します()。wc -l "$file" | awk ...$msg

最後の行では、単にgrepを使用するのではなく、その上に別のフィルタを使用しています。if関数はそれの分岐を生成するのではなく、cat4番目の引数を持たない一般的な場合に暗黙のデフォルトの追加フィルタとして使用します。local filter="${4:-cat}"つまり、4番目の引数にコンテンツが提供される関数ローカル変数フィルタを生成することを意味します。 、またはcat4番目の引数が指定されていない場合)。cat4番目の引数が指定された場合はオーバーライドされますgrepAndLog

答え2

ここで最良の方法は、次のawkような。

gunzip -c /var/log/cisco/cisco.log-$(date +%Y%m%d).gz | awk '
/ath_bstuck_tasklet/ { netgear_beakon[$4] = 1 }
/Virtual device ath0 asks to queue packet/ { netgear_buffer_queue[$4] = 1 }
...
/ACK/ { netgear_ACK[$4] ++ }
END {
  n=0; for(k in netgear_beakon) n++; print n,"Stuck beacon; resetting";
  n=0; for(k in netgear_buffer_queue) n++; print n,"routers with Virtual device ath0 asks to queue packet";
  ...
  n=0; for(k in netgear_ACK) n+=(netgear_ACK[k]>=50); print n,"routers with more than 50 ACK"
}'

ファイルを複数回読み込むだけでなく、何度もsort実行する必要はありません。uniqこれは、配列内の各一意の項目を保存(または計算)し、各配列のキーを繰り返して項目数を計算します。

関連情報