今からはじめるプログラミング50(システム監視②)

前回、画面のイメージだけで、実装がなかったので、実装したものです。

Javaで(Javaに限らないかもしれないけど)ちょっとめんどくさいのが実行結果の取得ですかね、ファイル関係は今まで散々コーディングしてるので、だいぶなれましたか?(してなかったっけ?)

というわけでコマンドをruntimeに渡してメソッドを呼ぶのはいいのですが、結果をStreamで受け取って、それを画面表示に編集する、という流れになります。

SampleFrame

---------------------------------------------------------------

package sample30;

 

import java.awt.BorderLayout;

import java.awt.Container;

import java.awt.Dimension;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.io.BufferedReader;

import java.io.InputStream;

import java.io.InputStreamReader;

 

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JScrollPane;

import javax.swing.JTextArea;

import javax.swing.JTextField;

 

/**

 * コマンドの実行確認画面

 * 

 * @author ma2

 *

 */

public class SampleFrame extends JFrame implements ActionListener {

/**

* 

*/

private static final long serialVersionUID = 1L;

JTextField txt = null;

JTextArea txtArea = null;

 

public SampleFrame() {

init();

 

}

 

/**

* 初期化

**/

private void init() {

this.setTitle("コマンドの実施");

this.setLayout(new BorderLayout());

txt = new JTextField("input command");

Container cont = this.getContentPane();

cont.add(txt, BorderLayout.NORTH);

JButton btnExec = new JButton("EXECUTE");

btnExec.setActionCommand("exec");

btnExec.addActionListener(this);

cont.add(btnExec, BorderLayout.EAST);

txtArea = new JTextArea();

JScrollPane scroll = new JScrollPane(txtArea);

cont.add(scroll);

 

this.setDefaultCloseOperation(EXIT_ON_CLOSE);

this.setSize(new Dimension( 600,480));

 

this.setVisible(true);

}

 

public static void main(String arguments) {

 

new SampleFrame();

 

}

 

@Override

public void actionPerformed(ActionEvent e) {

String command = e.getActionCommand();

System.out.println("command = " + command);

if ("exec".equals(command)) {

String input = this.txt.getText();

System.out.println("input = [" + input + "]");

try {

String returns = new String[3];

Runtime runtime = Runtime.getRuntime();

            InputStream in = null;

            BufferedReader br = null; 

            try {

                Process p = runtime.exec

                    (input);

                in = p.getInputStream();

                StringBuffer out = new StringBuffer();

                br = new BufferedReader(new InputStreamReader(in));

                String line;

                while *1 != null) {

                    out.append(line + System.lineSeparator());

                }

                returns[0] = out.toString();

                br.close();

                in.close();

                in = p.getErrorStream();

                StringBuffer err = new StringBuffer();

                br = new BufferedReader(new InputStreamReader(in));

                while *2 != null) {

                    err.append(line + System.lineSeparator());

                }

                returns[1] = err.toString();

                returns[2] = Integer.toString(p.waitFor());

               

                System.out.println("line = [" + line + "]");

                p.destroy();

              } finally {

                if (br != null) {

                    br.close();

                }

                if (in != null) {

                    in.close();

                }

            }

            StringBuffer result = new StringBuffer();

            result.append("--------------------");

            result.append( System.lineSeparator());

            result.append( returns[0]);

            result.append( System.lineSeparator());

            result.append("--------------------");

            result.append( System.lineSeparator());

            result.append( returns[1]);

            result.append( System.lineSeparator());

            result.append("--------------------");

            result.append( System.lineSeparator());

            result.append( returns[2]);

            result.append( System.lineSeparator());

            result.append("--------------------");

            txtArea.setText(result.toString());

        } catch (Exception exp) {

        exp.printStackTrace();

            System.out.println(exp);

 

}

        }

}

}

------------------------------------------------------

コードの量としては、前回と比較すると倍になってますが、わかりずらいのはProcessの扱いですかね。細かい扱いについての説明は割愛します。

実行結果を2パターンほど

正常なパターン

異常なパターン

まぁ面倒なのは、異常なパターンがかなりたくさんあることで、実際に仕事に使えるようにするには、この異常なパターンの切り分けが重要になってきます。

たとえば、これはホストが存在しないパターン(メッセージから)ですが、この戻り値を見てみると「68」とかなっています。エンジニアでないと、そもそもこの値の正体がわからない(ICMPタイプという値みたい?)、ということもありますし、え?コマンド自体が実行できてないという場合のパターンもあったり。(その場合はエクセプションかな?)

 

昔インフラの大規模システムに携わったことがありまして、

システムの監視対象の規模にもよるのかもしれませんが、

コマンドでできることと、アプリでできることの切り分けがむずかしいな。。。

と思います。

というかほとんどシェルもしくはバッチで作りました。

ワンライナーとか得意な人なら、その方がいいのかもしれないけれど、僕は業務アプリから入った人間なので、アプリでやらせてくれたらなぁ、というところも多々あり。結局プロジェクトをマネージするひとの裁量とか、あとはこのソフトを使います(ミドルウェアですかねWebsphereとかSymfowareとか)、という場合は、そのソフトの仕様に合わせてとか。

細かいアイデアをいえば、「起動している」状態ごとにフラグを監視用サーバーに置くように起動スクリプトを組んで、アプリはそのフラグを参照して状態を表示する。

みたいなことを考えるだけで、いくつバッチが必要かな、考えると「ハードが起動していない(フラグおけない、なし)」「ハードは起動(0)」「ネットワーク起動(1)」という感じのステータスがあって、

さらにそのコンピュータの提供するサービス、ファイルサーバーなのか、アプリケーションサーバーなのか、WEBサーバーなのかとか。

そのサーバーごとに、動いているべきプログラムがなんなのか、などを考えていくと、かなりいろんな知識が必要になりますよね。(うわ、めんどくさ!)

監視ソフトの仕組みがなんとなくでも想像していただけるようになれば幸いです。

*1:line = br.readLine(

*2:line = br.readLine(