いますぐ実践! Linuxシステム管理

いますぐ実践! Linux システム管理 / Vol.251 / 読者数:2487名

こんばんは、うすだです。

この土日に、息子の部屋と私の部屋を、えいやーで入れ替えました。

…いえ、入れ替えるべく、猛烈に作業を進めているのですが、 終わる気配がまったくなく、山積みのモノに囲まれた環境下で、いま書いています。

ようするに、見積りが甘かったのです。
まるで、どこぞやのプロジェクトのようです。

いまのマンションに移ってから約10年。10年分の様々な蓄積が、 お互いの部屋にありまして、次から次へと、想定外のモノが出てきます。
まるで、どこかで体験したプロジェクトのなにかのようです。

とりあえず、明日、息子の新しい本棚が届くため、 そのスペースを開ける作業は終えました。その分、 わたしの部屋にしわ寄せが来ています。
まるで、あのときのプロジェ…ああ、もういいです。

現実逃避と言われても仕方のない状態で、今回もはりきってまいります。

今回のお題 - DHCPでアドレスを割り当てたら通知する (レベル:中級)

先日、hostapd と dhcpd を使って、無線LANルータを仕立てあげる機会がありました。

うまく動いてくれましたので、そのまま24時間動かしっぱなし状態にしているのですが、 WPA2 で認証が必要になっているとはいえ、 なにかの拍子に他人が接続してしまったら…と思うと、心配で夜も眠れません。

しかし、利便性のほうが優先される場合、サービスは止められません。
かといって、24時間監視するわけにもいきません。(体が持ちません。)

じゃあ、DHCPでIPアドレスを割り当てたとき、関連する情報をメールなどで通知する、 というのはどうでしょうか。
常に監視しなくても、通知内容から、怪しいかどうかの判断くらいはできそうです。

というわけで今回は、DHCPでIPアドレスを割り当てたら、 メールかなにかでその旨を通知する、というのをやってみたいと思います。

対象となるDHCPサーバは、ご存じな方はご存じ、ISCのDHCPサーバです。

Internet Systems Consortium | DHCP
https://www.isc.org/downloads/dhcp/

Debian系だと「isc-dhcp-server」、 RedHat系だと「dhcp」という名前のパッケージがそれです。
以降は、これをインストールして使える状態になっている、 という前提で話をすすめます。

dhcpd.leases が情報源です

ISCのDHCPサーバは、自身が割り当てた情報を、 「dhcpd.leases」というファイルに記録します。
具体的なパスは、2013年11月現在、おそらく以下あたりです。

  /var/lib/dhcp/dhcpd.leases   (Debian系の場合)
  /var/lib/dhcpd/dhcpd.leases  (RedHat系の場合)

フォーマットは、テキスト形式で、ISCお得意の、いつものアレです。
割り当てごとに、以下のような内容を吐き出します。

  lease IPアドレス {
      starts 割り当て開始日時(UTC);
      ends 割り当て終了日時(UTC);
      hardware タイプ MACアドレス;
      binding state 状態;
      client-hostname ホスト名;
  ...略...
  }

日時の具体的な形式は、「曜日(0-6) 年/月/日 時:分:秒」です。
hardwareのタイプは、おそらく99.9% 「ethernet」です。
binding stateの状態は、割り当て中の「active」かそうでない「free」がほとんどです。

dhcpd.leases の具体例(抜粋)を、以下に示します。

lease 10.0.0.129 {
  starts 6 2013/11/16 06:37:31;
  ends 6 2013/11/16 06:47:31;
  tstp 6 2013/11/16 06:47:31;
  cltt 6 2013/11/16 06:37:31;
  binding state free;
  hardware ethernet 00:01:02:03:04:05;
}
lease 10.0.0.130 {
  starts 6 2013/11/16 06:35:57;
  ends 6 2013/11/16 06:45:57;
  cltt 6 2013/11/16 06:35:57;
  binding state active;
  next binding state free;
  hardware ethernet 00:01:02:03:04:06;
  client-hostname "tma-1";
}

dhcpd.leases から必要な情報を抜き出します

ファイルの中身を全部まるっと送ってしまう、 というのがもっとも情報量の減らない方法ですが、見にくかったり、 見せたくない情報もあったりという問題があります。

ですので、必要な情報を抜き出すスクリプトを書いてみましょう。
…早速ですが、書いてみました。

#!/bin/sh
while read l1 l2 l3 l4 l5 l6 l7 l8 l9; do
    case "$l1" in
        lease)
            IPADDR=$l2;;
        hardware)
            MAC=$(echo $l3 | tr -d \;);;
        client-hostname)
            NAME=$(echo $l2 | tr -d \"\;);;
        starts)
            l4=$(echo $l4 | tr -d \;)
            T1=$(date --date="$l3 $l4 UTC" "+%F %T");;
        ends)
            l4=$(echo $l4 | tr -d \;)
            T2=$(date --date="$l3 $l4 UTC" "+%F %T");;
        binding)
            STAT=$(echo $l3 | tr -d \;);;
        \})
            if [ -n "$NAME" ]; then
                echo "$IPADDR $MAC $T1 $T2 $STAT ($NAME)"
            else
                echo "$IPADDR $MAC $T1 $T2 $STAT"
            fi
            IPADDR=
            MAC=
            NAME=
            T1=
            T2=
            STAT=;;
    esac
done

…長いように見えますが、たいしたことはやっていません。

標準入力から dhcpd.leases を読み込んで、IPアドレス、MACアドレス、 割り当て開始日時、終了日時、状態 を出力するスクリプトです。

shのビルトインコマンドである「read」で1行ずつ読み込み、 先頭の単語が「lease」や「hardware」などのときに、それぞれ情報を取得します。

「}」にぶち当たったら、得た情報をechoコマンドで放出します。

ここで説明が必要っぽいのが、日時の処理です。
得られる情報は「UTC(協定世界時)」です。 JST(日本標準時)に変換しないとわかりづらいですので、そうしています。
具体的には、dateコマンドの「--date」オプションを使っています。

  $ date --date="2013/11/17 08:00:00 UTC"
  2013年 11月 17日 日曜日 17:00:00 JST

これだと出力が長いので、出力フォーマットを「%F %T」に指定しています。

  $ date --date="2013/11/17 08:00:00 UTC"
  2013-11-17 17:00:00

で、これを checkdhcp.sh というファイル名で保存したら、 いつものように実行権をつけて、実行してみてください。

  $ chmod +x checkdhcp.sh
  $ ./checkdhcp.sh < /var/lib/dhcp/dhcpd.leases
  10.0.0.129 00:01:02:03:04:05 2013-11-16 15:37:31 2013-11-16 15:47:31 free
  10.0.0.130 00:01:02:03:04:06 2013-11-16 15:35:24 2013-11-16 15:45:24 active (tma-1)

百歩譲って、見やすくなった、と思ってください。

また、お察しの通り、 dhcpd.leases の規定のフォーマットになっているという前提で書かれています。 ですので、エラー処理的なものが含まれていません。 事実上問題ないと割り切っています。ご容赦くださいませ。

更新されたら通知します

これを、ひっきりなしに実行する、ということは非現実的ですので、 よいタイミングで実行する必要があります。

ここでは安直に、 dhcpd.leases が更新されたとき通知するよう仕込んでみたいと思います。

ファイルが更新されたかどうか判断するのに、 「inotifywait」コマンドを使います。
これは、「inotify」という仕組みを使って、 ファイルの状態が変わるのを待って知らせてくれるコマンドです。

たとえば、/tmp/foo を作成し、引数に指定して実行します。

  $ touch /tmp/foo
  $ inotifywait /tmp/foo
  Setting up watches.
  Watches established.

待ち状態になりますので、別の端末から、/tmp/foo にアクセスします。

  $ cat /tmp/foo

すると、以下のメッセージが出力されて、inotifywait が終了します。

  /tmp/foo OPEN

ただ、上記では、ファイルに関する操作をすべて検知してしまいます。
そこで、「-t」オプションと操作を指定して、更新だけに限定します。

というわけで、更新されたときに情報を吐くスクリプトは、以下です。

#!/bin/sh
LEASEFILE=/var/lib/dhcp/dhcpd.leases
inotifywait -e create,modify,attrib $LEASEFILE > /dev/null 2>&1 || exit $?
while read l1 l2 l3 l4 l5 l6 l7 l8 l9; do
    case "$l1" in
        lease)
            IPADDR=$l2;;
        hardware)
            MAC=$(echo $l3 | tr -d \;);;
        client-hostname)
            NAME=$(echo $l2 | tr -d \"\;);;
        starts)
            l4=$(echo $l4 | tr -d \;)
            T1=$(date --date="$l3 $l4 UTC" "+%F %T");;
        ends)
            l4=$(echo $l4 | tr -d \;)
            T2=$(date --date="$l3 $l4 UTC" "+%F %T");;
        binding)
            STAT=$(echo $l3 | tr -d \;);;
        \})
            if [ -n "$NAME" ]; then
                echo "$IPADDR $MAC $T1 $T2 $STAT ($NAME)"
            else
                echo "$IPADDR $MAC $T1 $T2 $STAT"
            fi
            IPADDR=
            MAC=
            NAME=
            T1=
            T2=
            STAT=;;
    esac
done < $LEASEFILE

肝である while〜done の部分は、前述と同じです。
その前に、inotifywait で更新を待つようにしています。
あと、dhcpd.leases を引数で指定しなくてよくしています。

こちらも、先ほどと同様、実行権をつけて実行します。
更新されるまで、ひたすらじっと待ちます。

  $ chmod +x checkdhcp2.sh
  $ ./checkdhcp2.sh

待っていられない貴兄は、他の端末から更新したように見せかけてあげると、 情報を吐いてくださいます。

  $ sudo touch /var/lib/dhcp/dhcpd.leases

 

そして、通知といえば、なんやかんや言っても、メールでしょうか。
先ほどのスクリプトの最後の行を以下のように変更すれば、標準出力ではなく、 メールで通知してくれます。

...前略(最後の行以外は checkdhcp2.sh と同じです)...
done < $LEASEFILE | Mail -s '[dhcp] updated' root

上記では、[dhcp] updated という題名で、root 宛にメールしています。

 

ちなみに、inotify は、過去でネタにしております。

Vol.157 - inotify でディレクトリを監視してみる
http://www.usupi.org/sysad/157.html

メールなどの通知に関しては、前回ご紹介しました。

Vol.250 - アラートの通知手段をいくつか試す
http://www.usupi.org/sysad/250.html

最後、Upstartのサービスにします

まだまだ荒削りなスクリプトですが、それでも、 システム起動時に自動的に実行されて、さらに繰り返し実行されると、 当初の目的をまあまあ達成できた、と言えるのではないかと思います。

ここでは、UbuntuのUpstartを使って、サービスに仕立てあげます。
サービス名を安直に「checkdhcp」としました。
すると、設定ファイル名は自動的に「/etc/init/checkdhcp.conf」となります。 中身の例は、以下の通りです。

description "check dhcpd.leases"
start on started isc-dhcp-server
stop on stopping isc-dhcp-server
exec /some/where/checkdhcp3.sh

ザ・ミニマルな設定しかしておりません。
isc-dhcp-server サービス開始後に実行され、終了時に終了します。
exec では、実際にスクリプトのあるパスを指定してください。
そして、respawn があるので、checkdhcp3.sh が終了したら、 再び実行をしてくださいます。ありがたいです。

とりあえずいま実行したい場合は、以下のように実行します。

  $ sudo start checkdhcp
  checkdhcp start/running process PID

先ほどと同様、touch すると通知されます。
respawn が効いて、再実行もされます(PIDが変わります)。

  $ status checkdhcp
  checkdhcp start/running process 旧PID
  $ sudo touch /var/lib/dhcp/dhcpd.leases
  $ status checkdhcp
  checkdhcp start/running process 新PID

おわりに

以上、DHCPでIPアドレスを割り当てたらその旨を通知する方法を、ご紹介しました。

小規模なところでは問題ないはずですが、秒単位で割り当てられるようなところでは、 通知がパンパン来て使いモノになりません。

そういうところでは、知らないクライアントを検知したら通知するとか、 サマリを定期的に通知するとか、工夫が必要になると思います。

また、スクリプト終了から次の実行開始までの間は、 inotifywait で監視できていませんので、取りこぼす可能性があります。(→宿題へ)

さらに、前回と同じ内容でも、律儀に、空気を読まず通知します。
これは、前の状態を覚えておいて、比較すればよさそうですね。

…うーん、探すと、いろいろ突っ込みどころがありそうです。
というわけで、あれこれ動かしながら改善していただけますと幸いです。

宿題の答え

前回の宿題は、

  SSHのX11フォワーディングを使って、サーバから手元のデスクトップに
  通知を表示してみましょう。

でした。

SSHサーバの設定ファイル(/etc/ssh/sshd_config)の「X11Forwarding」 が yes になっていて、クライアントがsshコマンドで接続する際、 「-X」や「-Y」オプションを指定すれば、普通に使えます。
(あるいは、~/.ssh/config で ForwardX11 などを yes に設定します。)

たとえば、以下のように、X11フォワーディングありでサーバへログインすると、 環境変数DISPLAYが自動的に設定されます。

  client$ ssh -X server
  usu@server's password:
  ...

  server$ echo $DISPLAY
  localhost:10.0

この状態でnotify-sendコマンドを実行すると、 サーバで実行された結果がクライアントの画面に表示されます。

  server$ notify-send "$(hostname) : $(uptime)"

面白いのは、クライアントが Fedora の場合、ローカルでnotify-sendを実行すると、 画面下部にメッセージが表示されますが、サーバが Ubuntuだと、 Ubuntuと同様画面右上にメッセージが表示されます。
(notify-send がフツーに X で処理している、ということですね。)

今回の宿題

今回の宿題は、

  inotifywaitによる監視が途切れないようにしてみましょう。

です。

最後に書きましたが、スクリプト終了〜次の実行の間は、 inotifywait が実行されていないため、監視が途切れてしまいます。

常に監視して、取りこぼさないようにしてみてください。
ようは、inotifywait がずっと監視していればよい、ということです。

あとがき

モノは定期的に整理しないといけないということを、実感しております。

同じことが、ディスクにも言えるのではないでしょうか。

ただ、失うリスクが、現実のモノとは違い、格段に大きいと言えます。
そこで、整理してコンパクトにした上で、適切にバックアップを取る必要がある、 と言えるのではないでしょうか。

そういえば、ちょっと前に、/.Jで以下を読みました。

自宅以外にデータをバックアップするシンプルな方法は?
http://askslashdot.slashdot.jp/story/13/11/09/0634235/

私の場合、大事なものは、会社のサーバや、VPS、 Amazon S3などにバックアップをとっています。…大半は手動ですが。

昔は、ホーム以下をすべて別のマシンに同期していたのですが、最近は、 ディスクに関するトラブルに遭遇していないため、怠っています。

…ちょっと心に隙があるような気がしてきました。
そんなときこそ、転ばぬ先の杖的に、対策を講じるべきですよね。
どれかが壊れてもデータが消えないよう、ルールを決めたり、 自動化するようにしたいと思います。

 

あとは、整理ですね。ディスクも、現実でも…。(途方に暮れています…)

 

今回も、ここまで読んでいただき、誠にありがとうございました。
次回は、12月1日(日) の未明にお会いしましょう!

 

「いますぐ実践! Linux システム管理」の解除は、以下からできます。
http://www.usupi.org/sysad/ (まぐまぐ ID:149633)

バックナンバーは、こちらにほぼ全部そろっています。
http://www.usupi.org/sysad/backno.html

「栗日記」- それでもまだ、クリ製品が出回っていますね。うれしい。
http://www.usupi.org/kuri/ (まぐまぐ ID:126454)
http://usupi.seesaa.net/ (栗日記ブログ)
http://usupi.org/k/ (モバイル栗日記)
http://twitter.com/kuriking/ (栗つぶやき)
http://facebook.com/kuriking3 (栗顔本)


[バックナンバーのトップへ] [Linux システム管理のトップへ]

トップ

バックナンバー
    [日付順] [目的別]

プロフィール

▼ リンク

独学Linux
Linuxデスクトップ環境に関する情報が満載です。 メルマガもありますよ。
Server World
CentOS 6をサーバとしたときの設定例が、これでもかというくらいたくさん載っています。 CentOS以外のディストリビューション(Fedora, Ubuntu)も充実しています。
LINUXで自宅サーバーを構築・導入(Fedora9)
Fedora9のインストールの仕方から管理方法まで、詳しく載っています。 SearchManには情報がもりだくさんです。
マロンくん.NET
〜サーバ管理者への道〜
Linuxをサーバとして使用するための、いろいろな設定方法が載っています。 マロンくんもかわいいです。 なんといっても、マロンくんという名前がいいですね!!
日経Linux
今や数少なくなってしまったLinuxの雑誌。ニュースやガイドもあります。
Linux Square − @IT
@ITが提供する、Linux の情報が満載。 載っていない設定方法はないんじゃないでしょうか。
gihyo.jp…技術評論社
Linuxに限らず様々な技術情報が満載のサイト。 SoftwareDesign誌も、 ソフトウェア技術者は必見です。
SourceForge.JP Magazine
Linux に限らず、オープンソース関連の記事が網羅されています。
ITmediaエンタープライズ:Linux Tips 一覧
Tips というより FAQ 集でしょうか。わからないことがあれば覗きましょう。
IBM developerWorks : Linux
開発者向けですが、勉強になりますよ。
Yahoo!ニュース - Linux
Yahoo!のLinuxに関するニュース一覧です。
栗日記
システム管理とかと全然関係ありませんが、毎日栗の絵を描いています。
システム管理につかれちゃったとき、癒されたいときに、ご覧ください。:-)
WEB RANKING - PC関連
ランキングに参加してみました。押してやってください。

▼ 作ってみました

Add to Google

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本