Linux サーバに信号灯を取り付け、状況を視覚的に判断できるようにしました。
障害を伝える手段
サーバに問題が発生した時、管理者にそれを知らせる手段を考えてみます。
- メールを送る
- 音を鳴らす
- 光る
手軽で実用性が高いのはメールだと思います。特に携帯電話へメールを送信すれば、 PC が手元になくても障害を知ることができます。しかし、メールでは遅延して届かないとも限りません。手元にサーバがある状態に限定されますが、できる限り迅速に障害を知るには、音や光が有効ではないかと思うのです。
音に関しては PC に内蔵のビープ用スピーカを鳴らせば簡単に実現できます (方法についてはけんども日記: Linux でビープ音を鳴らすをご覧ください) 。では光ならどうすればいいのでしょうか。今回は可視性の優れる信号灯を使うことにしました。
信号灯とは?
一般家庭には存在しないものなので、信号灯と聞いても思い浮かばないかもしれません。信号灯は主に工場内の機械などに取り付けてあるものです。信号灯にもさまざまな種類があり、よくあるのは赤、橙、緑などのランプがついたタワー型です。
購入
工場の機械に使われるようなものをどうやって入手するか…。ですが、検索すればすぐに見つかるもので、製造元のパトライトのオンラインショップで扱っています。 PC で制御するためのリレーユニットもあわせて購入しました。また、信号灯の電源として AC アダプタ。 PC とリレーユニットとの接続にシリアルケーブルも忘れてはいけません。 4 万円弱の出費になってしまいました。
- 信号灯 (パトライト LE-302P)
- パトライトのオンラインショップ、ぱっとクルで購入しました。直径 50mm 、赤橙緑の 3 段という一般的なモデルです。
- パソコン出力リレーユニット (パトライト PHC-100A)
- これも信号灯と同時に購入しました。 PC とシリアルケーブルで接続し、簡単なプロトコルでリレーを制御できます。リレーは独立して 8 チャンネルあるため、信号灯以外の機器も接続すればあわせて制御することができるでしょう。
- AC アダプタ (24V 0.5A)
- 秋月電子のオンラインショップで購入しました。今回は DC24V で稼働する信号灯を選んだため、 AC アダプタが必要になりました。
- DC ジャック
- 上記 AC アダプタの出力コネクタを接続するジャックです。これも秋月電子で購入できます。
- シリアルケーブル (ストレート D-Sub 9 ピン)
- PC とリレーユニットの接続必要なシリアルケーブルです。接続先の端子がどちらもオスなので、ケーブルはメス - メスを選ぶ必要があります。
動作確認と設置
動作確認
念のため、まずは信号灯と AC アダプタを直接接続し、点灯することを確認しました。確認ができたら、リレーユニットに接続し、ターミナルからコマンド (取扱説明書に載っています) を送ってみます。以下は 1 番目のシリアルポートに接続したリレーユニットの全てのリレーを On にします。「カチッ」というリレーの動作音とともに信号灯の 3 段全てが点灯すれば成功です。
しかし、一般のユーザではアクセス権がないため Permission denied と表示されてしまうかもしれません。アクセス権を確認します。
crw-rw---- 1 root dialout 4, 64 Jun 15 10:33 /dev/ttyS0
この結果は環境によって異なると思います。この例ではグループが dialout になっているので、 /etc/group の dialout で始まる行の最後に許可したいユーザを追加します。
また、 devfs を使用している環境では /dev/ttyS0 は /dev/tts/0 へのシンボリックリンクになっています。その場合は /dev/tts/0 のグループを確認し、同様に /etc/group を編集すれば問題ありません。
ラックへの取り付け
付属の L 型金具で 19 インチラックの背面に取り付けました。ネジ穴のピッチは若干異なりますが、問題なく取り付け可能です。
色と役割
道路の信号機と同じように、工場の信号灯の色にも意味があります。例えば、正常に流れているときは緑のみ点灯、警告は橙、異常発生時は赤といった具合です。私は以下のように使っています。
- 緑
- 外部へ公開するための接続が確立されているとき点灯。切断されると消灯。
- 橙
- エラー用のログファイルを監視し、それが更新されればしばらくの間点灯。
- 赤
- 決めたポートを監視し、ポートが閉じれば点灯。再び開くと消灯。
ログファイル監視とポート監視は次にサンプルスクリプトを公開しています。
Perl によるサーバ監視スクリプト
荒々しいかもしれませんが、サーバを監視してリレーユニットを動かすための Perl スクリプトです。
その他、 swatch でログの内容を監視してリレーを動かすというアイデアも浮かびます。
ファイル監視スクリプト
指定したファイルを監視し、ファイルが更新されれば 2 番目のリレーを 3 秒間 On にします。
#!/usr/bin/perl use strict; use warnings; my $file = '監視するファイル'; my $modify = (stat($file))[9]; while (1) { if (time() - $modify <= 2) { system "echo -n '@??102!' > /dev/ttyS0"; sleep 3; $modify = (stat($file))[9]; while (time() - $modify <= 2) { sleep 2; $modify = (stat($file))[9]; } system "echo -n '@??002!' > /dev/ttyS0"; } else { sleep 2; } $modify = (stat($file))[9]; }
ポート監視スクリプト
指定したポートを 5 秒間隔で順番に監視し、閉じていれば 1 番目のリレーを On にします。閉じたポートが再び開くまでリレーは Off になりません。ご覧のとおり、監視するのは TCP のみです。 UDP も対象にするには手直しが必要です。
#!/usr/bin/perl use Socket; use strict; use warnings; my $hostname = 'サーバ名もしくは IP アドレス'; my $temp_dir = '/var/tmp/scan'; # このディレクトリはあらかじめ用意しておく my @port_list = (22, 25, 53, 80, 110, 5432); # 監視するポート my $protocol = getprotobyname('tcp'); my $ipaddr = inet_aton($hostname) or die "$hostnameの取得失敗:$!"; while (1) { foreach my $port (@port_list) { socket(SOCKET, PF_INET, SOCK_STREAM, $protocol) or die "socket失敗:$!"; my $paddr = pack_sockaddr_in($port, $ipaddr); if (connect(SOCKET, $paddr)) { if (-e "$temp_dir/$port") { system "rm $temp_dir/$port"; opendir(DIR, $temp_dir); if (readdir(DIR) !~ /[0-9]/) { system "echo -n '@??001!' > /dev/ttyS0"; } closedir(DIR); } } else { unless (-e "$temp_dir/$port") { system "touch $temp_dir/$port"; system "echo -n '@??101!' > /dev/ttyS0"; } } close SOCKET or die "close失敗:$!"; sleep 5; } }
おわりに
シリアル接続のリレーユニットを使用することで、信号灯の制御はとても簡単に実現できました。しかし、問題がないわけでもありません。今回は監視対象となるサーバ自身で信号灯の制御を行いました。もし、サーバに致命的な問題が発生してしまうと信号灯が制御できなくなる可能性があります。より確実にするには、別に監視専用のマシンを用意すべきだと思います。