サーバー監視システムを電子工作した話 その2
こんにちは!
今回は前回の続きとして、Arduinoを使ったサーバー監視システムについて書いていきます。前回も軽く触れたとおり、その2の主な話題ソフトウェアまわりのことについてです。まだ前回の記事を読んでいない方は、先にそちらに目を通していただけるとわかりやすいので、まずはこちらをご覧ください。
ソースコード
まずはなにはなくともソースコードですね。下記のGitHubのリポジトリでソースは公開しているので、興味のある方はこちらをご覧ください。ただ、基本的に自分が開発したついでにGitHubにプッシュしているだけで、他の誰かがつかうことを想定していないことはご了承ください。まあ、そもそもこれを使いたい人がいるとはあまり思っていないのでw、あくまでもご参考用って感じですね。
上記のリポジトリを読んでいただければわかるとおり、今回は全ての機能を含んだ単独のプログラムとして実装しているわけではなく、各機能を別々のプログラミング言語で実装しています。具体的に使っている言語は「シェルスクリプト」「Processing(Javaベース)」「Arduino言語(C言語ベース)」の3つ。今回の記事では、全体の構成と、それぞれのプログラムの役割について書いていきます。
全体の構成
前回の記事でも掲載したように、システム全体の構成は下記のような形になっています。
前章で書いたそれぞれのプログラムの役割分担としては
シェルスクリプト:SystemDの状態のチェック→ファイル出力
Processing: SystemDの状態ファイルを読み込み→Arduinoへのシリアル通信
Arduino: 受け取ったシリアル通信データを元にLEDを光らせる
という感じですね。もしかしたらもっとシンプルにコードを組めるのかも知れませんが、とりあえずぱっと思いついた構成ということでこのような形にしています。それぞれのプログラムの処理内容としてはざっくりと以下のような感じ。
シェルスクリプト「daemon_ck.sh」
シェルスクリプトで書いている主な処理内容はLinuxのプロセス管理プロセス「SystemD」にアクセスして、指定したサーバープログラムが正常に動いているかどうかを確認するというものです。その確認結果をテキストファイルとして保存するまでをこのプログラムが担っています。
分量自体は三つのプログラムの中でも最も短く、処理内容も単純です。ここだけならば大したサイズでもないので、以下に記述しておきます。
#!/bin/bash
SERVICES=("sshd" "x11vnc" "vpnserver" "apache2" "smbd")
OUTPUT=`cat Filepath`
rm $OUTPUT
for SERVICE in ${SERVICES[@]}
do
systemctl status $SERVICE | grep running
if [ $? = 0 ]; then
echo "$SERVICE 1" >> $OUTPUT
else
echo "$SERVICE 0" >> $OUTPUT
fi
done
わかる人が見ればひと目でわかる処理なのであまり詳細には説明しませんが、各サーバーソフトの文字列を配列に保存し、systemctlで状態をチェックして、「running」状態になっているかどうかを確認するというものですね。あとはファイルへの書き込み処理です。ちなみに、Filepathという名前の別ファイルを準備し、出力テキストデータを置いておくファイルの場所を指定するという形にしています(Filepath自体はgitignore設定しているのでGitHubにはアップロードしていません)。
そして、このプログラムに対してcrontabを使って定期的に実行するように設定。そこまでリアルタイム性が求められるわけでもないので、1分刻みとか5分刻みで実行しておけばいいと思います(処理としては負荷がかかるようなものでもないので、あまりナイーブになる必要はないとも思いますが)。
ちなみにcrontabの設定自体は下記。
*/5 * * * * cd /home/{User名}/Programs/daemon_ck; ./daemon_ck.sh
これは5分ごとに実行するとした場合の記述ですね。ここでは「daemon_ck.sh」は「~/Programs/daemon_ck」フォルダ内にあるとしています。シェルスクリプトと同じフォルダにあるFilePathにアクセスしなければならないので、一度cdでそのフォルダに移動してから実行する形としています。
ちなみに、この部分をシェルスクリプトで書いた理由は、「systemctl」コマンドでSystemDにアクセスする必要があったためです。他の言語でも出来るのかも知れませんが、他の言語からSystemDにアクセスするのは権限関係がちょっとめんどくさそうだったので、シンプルにシェルスクリプトを使うことにしました。このせいで全体の構成がちょっと複雑になった感はあるので、改善の余地はあるのかも知れません。
Processing「daemon_ck.pde」
このシステムの主な処理を担っているのがこのProcessingで記述した「daemon_ck.pde」です。Processingとは、主にビジュアル化や導入の容易さに強みを持つプログラミング言語(&開発環境)です。起源的にもシステム的にもArduinoとの親和性が高く、ArduinoをPC経由で動かしたり連携する際にはよく使われる言語みたいですね。
言語文法自体はJavaをベースにしていて、それに加えて容易にグラフィックや視覚効果を追加できるライブラリを搭載したもののようです。詳しくは下記のwikipediaも合わせてご覧ください。
Arduinoを使いはじめてからは、このProcessingもちょくちょく使っているのですが、開発環境の整備やグラフィックの実装が楽なのが良いですね。正直僕はこれまでJavaはほとんどつかったことがなかったのですが、それでも比較的気軽に使えるようにはなったので、プログラミングの入門としても適しているのかも知れません。
で、本題ですが、この今回のプログラムの主な機能は、シェルスクリプトが吐き出したテキストデータを読み込んで、データを処理した上でシリアル通信でArduinoに送信するまでとなります。データ処理の内容としては、各ソフト(5つ)が起動しているかどうか(ON or OFF)の情報を、二進法の「00000」から「11111」の数値に変換するというものです(10進法の0~31)。
それぞれの桁の数字が各ソフトの状態と対応しており、そのソフトが動いていれば「0」、異常があれば「1」となるというわけですね。たとえば、SSHとapacheに異常がある場合は「01001」(=9)が送信させると言った感じです。
また、これは本来の機能とは無関係ですが、LEDの状態を模擬したソフトウェアランプのようなモノも実装しています。文字で説明するのはちょっと難しいので、スクリーンショットをみていただくのが良いと思います。。
プログラムが動いている間はこんな感じのウィンドウを表示します(このときは人為的にapacheとvpnサーバーを止めてテストしています)。物理的なランプはarduinoとLEDで実装するわけですが、それと同じようなものをソフトウェア的に再現するイメージです。こういうものをサクッと実装できるのがProcessingの魅力だと感じますね。
Arduino「Daemon_LED.ino」
ここでようやっとarduinoが出てくるわけですね。Arduinoの動作のプログラムには公式サイトで配布しているArduino IDE(Integrated Development Environment:統合開発環境)という環境を使います。コーディングからArduinoへの書き込み、ライブラリの管理などをこれ一つでできてしまうので、基本的にはこれが使えれば問題なしって感じです。
前回の記事でも軽く触れましたが、Arduinoのプログラミングはc言語をベースとしてものなので、プログラミングの基本的な知識があれば割と簡単に使えちゃいます。個人的には、Arduinoが広く使われるようになったのはこの環境の整備によるものが大きいんじゃないかなぁとは思っています。各入出力ポート(ピン)との数値のやり取りやピン入力値の変数への取り込みなんかも普通のプログラムとまったく同じように使えるので、物理世界とコンピューターの中を非常にシンプルな形で繋いでくれるようなイメージですね。
また、このIDEは純正のarduinoだけではなく、その廉価版コピー品はもちろん、互換性のあるマイコンでも使えたりするのでこれがあるだけでいろいろと可能性が広がりますね!有名どころだと、wifiモジュールを搭載したesp8266やwifiとbluetoothを搭載したesp32なんかですね。これらもそのうち使っていきたいところです。
このプログラムの機能は、Processingから受け取った0~31のデータを分解し、その結果を元に各LEDが繋がったピンに「HIGH or LOW」の出力を与えるというものです。プログラムとしては多少分量はありますが、やっている事自体は極めて単純です。ここの部分はソフトウェア的に書くことがあまりないので、次回のハードウェア編のところで詳しく書いていきたいと思います。
まとめ
今回はArduinoを使ったサーバー管理システムのソフトウェア部分を解説しました。一見すると複雑ですが、それぞれの機能で分解していけば割とシンプルに理解できると思います。
次回はハードウェア部分について書いていくつもりです。ブレッドボードを使った試作から、ユニバーサル基板にはんだ付けした実装までを書くつもりなので、興味のあるかたはそちらもご覧いただければと思います。
それでは、また!
この記事が気に入ったらサポートをしてみませんか?