- PR -

dhcpの払い出し数を数えるbashを作りたいんですが

投稿者投稿内容
SEが好き
常連さん
会議室デビュー日: 2006/03/04
投稿数: 26
投稿日時: 2006-06-03 15:31
◆環境
・ISCのDHCPサーバを構築してます。
・OSはRedhat9

◆やりたいこと
dhcpサーバで、リース範囲ごとの払い出し数をカウントするシェルを作りたい。
【結果の例】
scope192.168.1.0 lease 35
scope10.1.1.0 lease 23

◆方法
dhcpd.leaseasで払い出し状況が確認できるので、このファイルから抜き出せばいいと思います。

◆dhcpd.leaseasの概要
lease 192.168.1.200 {
・・・・
binding state active;
・・・・
}
lease 192.168.1.199 {
・・・・
binding state free;
・・・・
}
lease 192.168.1.198 {
・・・・
binding state free;
・・・・
}
・・・・・今度は10.1.1.0のセグメントです。
lease 10.1.1.200 {
・・・・
binding state free;
・・・・
}
※dhcpd.leaseasファイルは払い出しをしていなくても、表示されます。(上記のfree)
※払い出しているかどうかは"active"か"free"を見て判断します。

◆悩み
grep -c で数を数える場合、
@「lease」をキーワードとすると、払いだしていないものもカウントしてしまう。
A「active」をキーワードとすると、どのリース範囲かわかりません。

アドバイスをいただけると助かります。
よろしくお願いします。

[ メッセージ編集済み 編集者: SEが好き 編集日時 2006-06-03 15:33 ]
Java僧
ぬし
会議室デビュー日: 2003/11/06
投稿数: 261
投稿日時: 2006-06-03 21:04
grepは複数行をうまく扱えませんね。
perlで書いてしまった方が簡単かも。
SEが好き
常連さん
会議室デビュー日: 2006/03/04
投稿数: 26
投稿日時: 2006-06-04 06:45
アドバイスありがとうございます。

perlというのは、言語ではなくコマンドのことですよね。
(「bashをやめてperlで書いたら?」と言われたことがあったものですから)

perlコマンドを調べたのですが、よく分かりません。具体的な書き方をアドバイスいただけないかな?と思いますが、いかがでしょうか。
Java僧
ぬし
会議室デビュー日: 2003/11/06
投稿数: 261
投稿日時: 2006-06-04 12:26
perlは言語でもありコマンドでもあります。(この辺まではmanでわかるかな)
#「bashをやめてperlで書いたら?」は表現として正しくないかも。

「よくわかりません」との事ですが、何がわからないのか明示しないと説明は無理です。
perlの解説だけで1冊の本ができるぐらいですから。(700ページ以上ある!)
http://www.amazon.co.jp/exec/obidos/ASIN/4873110963/qid=1149389748/sr=8-7/ref=sr_8_xs_ap_i7_xgl15/503-0108254-5247912

perlが解説書が多いと思ってお勧めしたんですが、perlにこだわる必要もないですね。
awkでも簡単に書けます。

gawk '/^lease/ {printf $2} /^ binding state/ {print "\t",$3}' /var/lib/dhcp/dhcpd.leases

Linux/UNIXはこういうツールが抜群に充実しています。
小さなツールを組み合わせて使うのが醍醐味ですよ。
ちいにぃ
大ベテラン
会議室デビュー日: 2002/05/28
投稿数: 244
投稿日時: 2006-06-04 16:18
awk で途中まで書いてみました。
BEGIN {
scope_list[s++] = "192.168.1.";
scope_list[s++] = "10.1.1.";
for (s in scope_list) {
print "(debug) scope=" scope_list[s];
}
}

/^lease [0-9.]+ {/ {
match($0, /[0-9.]+/);
ip = substr($0, RSTART, RLENGTH);
}
/binding state active/ {
active_list[active_count++] = ip;
print "(debug) active ip=" ip
}

END {
for (i in active_list) {
ip = active_list[i];
for (s in scope_list) {
scope = scope_list[s];
if (index(ip, scope) == 1) {
print "(debug) match scope=" scope " ip=" ip
scope_active[scope]++;
}
}
}

for (scope in scope_active) {
print "scope " scope " lease" scope_active[scope];
}
}

実行例
$ awk -f dhcpd.awk < dhcpd.leases
(debug) scope=192.168.1.
(debug) scope=10.1.1.
(debug) active ip=192.168.1.200
(debug) active ip=192.168.1.198
(debug) active ip=10.1.1.200
(debug) match scope=192.168.1. ip=192.168.1.200
(debug) match scope=192.168.1. ip=192.168.1.198
(debug) match scope=10.1.1. ip=10.1.1.200
scope 10.1.1. lease1
scope 192.168.1. lease2
SEが好き
常連さん
会議室デビュー日: 2006/03/04
投稿数: 26
投稿日時: 2006-06-05 14:45
ご丁寧な回答ありがとうございます。
感激しております。

がんばってやってみます。
ちいにぃ
大ベテラン
会議室デビュー日: 2002/05/28
投稿数: 244
投稿日時: 2006-06-07 18:26
awk, perl, pythonの3つのスクリプト言語で同じ処理を書いてみました。
いずれも Red Hat 9 で使えると思います。

インデントは全角空白に置き換えています。
スクリプトを使うときは全角空白1個を半角空白2個に置き換えてください。

なお、dhcpd.confのrangeは任意のIPアドレスの範囲を指定できますが、
このスクリプトでは対応していません。
範囲がClass A/B/Cのように8bit単位で区切られることを想定しています。
任意の範囲に対応するには scope_listの定義とscope_listとipの照合処理の修正が必要です。

************************************************ awk版
BEGIN {
  debug = 1

  scope_list[s++] = "192.168.1.";
  scope_list[s++] = "10.1.1.";
  if (debug) {
    for (s in scope_list) {
      print "(debug) scope=" scope_list[s];
    }
  }
}

/^lease [0-9.]+ {/ {
  ip = $2;
}

/binding state active/ {
  active_list[active_count++] = ip;
  if (debug) print "(debug) active ip=" ip
}

END {
  for (i in active_list) {
    ip = active_list[i];
    for (s in scope_list) {
      scope = scope_list[s];
      if (index(ip, scope) == 1) {
        if (debug) print "(debug) match scope=" scope " ip=" ip
        scope_active[scope]++;
      }
    }
  }

  for (scope in scope_active) {
    print "scope " scope " lease " scope_active[scope];
  }
}

************************************************ awk版 実行例
$ awk -f dhcpd.awk < dhcpd.leases
(debug) scope=192.168.1.
(debug) scope=10.1.1.
(debug) active ip=192.168.1.200
(debug) active ip=192.168.1.198
(debug) active ip=10.1.1.200
(debug) match scope=192.168.1. ip=192.168.1.200
(debug) match scope=192.168.1. ip=192.168.1.198
(debug) match scope=10.1.1. ip=10.1.1.200
scope 10.1.1. lease 1
scope 192.168.1. lease 2

************************************************ perl版
use strict;

my $debug = 1;

my @scope_list = (
  '192.168.1.',
  '10.1.1.',
);

if ($debug) {
  for my $scope (@scope_list) {
    printf "(debug) scope=%s\n", $scope;
  }
}

my $ip;
my @active_list;
while (<>) {
  chomp;
  if ($_ =~ /^lease ([0-9.]+)/) {
    $ip = $1;
  }
  if ($_ =~ /binding state active/) {
    push @active_list, ($ip);
    if ($debug) { printf "(debug) active ip= %s\n", $ip; }
  }
}

my %scope_active;
for my $ip (@active_list) {
  for my $scope (@scope_list) {
    if (index($ip, $scope) == 0) {
      if ($debug) { printf "(debug) match scope=%s ip=%s\n", $scope, $ip; }
      $scope_active{$scope}++;
    }
  }
}

for my $scope (keys %scope_active) {
  printf "scope %s lease %d\n", $scope, $scope_active{$scope};
}

************************************************ perl版 実行例
$ perl dhcpd.pl < dhcpd.leases
(debug) scope=192.168.1.
(debug) scope=10.1.1.
(debug) active ip= 192.168.1.200
(debug) active ip= 192.168.1.198
(debug) active ip= 10.1.1.200
(debug) match scope=192.168.1. ip=192.168.1.200
(debug) match scope=192.168.1. ip=192.168.1.198
(debug) match scope=10.1.1. ip=10.1.1.200
scope 10.1.1. lease 1
scope 192.168.1. lease 2

************************************************ python版
#
# -*- coding: iso-8859-1 -*-

import sys
import re

debug = 1

scope_list = (
  '192.168.1.',
  '10.1.1.',
  )

if debug:
  for scope in scope_list:
    print '(debug) scope=%s' % scope

ip = ''
active_list = []
for rawline in sys.stdin:
  line = rawline.rstrip('\n')
  matched = re.match('^lease ([0-9.]+)', line)
  if matched:
    ip = matched.group(1)
  if line.find('binding state active') >= 0:
    active_list.append(ip)
    if debug: print '(debug) active ip= %s' % ip

scope_active = {}
for ip in active_list:
  for scope in scope_list:
    if ip.startswith(scope):
      if debug: print '(debug) match scope=%s ip=%s' % (scope, ip)
      if not scope in scope_active:
        scope_active[scope] = 0
      scope_active[scope] += 1

for scope in scope_active:
  print 'scope %s lease %d' % (scope, scope_active[scope])

************************************************ python版 実行例
$ python dhcpd.py < dhcpd.leases
(debug) scope=192.168.1.
(debug) scope=10.1.1.
(debug) active ip= 192.168.1.200
(debug) active ip= 192.168.1.198
(debug) active ip= 10.1.1.200
(debug) match scope=192.168.1. ip=192.168.1.200
(debug) match scope=192.168.1. ip=192.168.1.198
(debug) match scope=10.1.1. ip=10.1.1.200
scope 10.1.1. lease 1
scope 192.168.1. lease 2
SEが好き
常連さん
会議室デビュー日: 2006/03/04
投稿数: 26
投稿日時: 2006-06-14 00:18
ちいにぃ様 
ご丁寧に書いていただいていたんですね。ありがとうございます。
私のレベルをはるか超えてしまっているので、ゆっくり読ませていただきます。

スキルアップ/キャリアアップ(JOB@IT)