2

JavaでUnixコマンド(ps私の場合)を定期的に実行する方法はありますか? 私が書いたループ:

while( this.check )
{
    try 
    {
            ProcessBuilder pb = new ProcessBuilder("ps");
            Process proc;

            System.out.println(" * * Running `ps` * * ");

            byte[] buffer;
            String input;

            proc = pb.start();
            BufferedInputStream osInput = 
                new BufferedInputStream(proc.getInputStream());

            //prints 0 every time after the first
            System.out.println(osInput.available());

            buffer = new byte[osInput.available()];
            osInput.read(buffer);
            input = new String(buffer);
            for( String line : input.split("\n"))
            {
                if( line.equals("") )
                    continue;
                this.handlePS(line);
            }

            proc.destroy();
            try 
            {
                Thread.sleep(10000);
            } 
            catch (InterruptedException ie) 
            {
                ie.printStackTrace();
            }
        } 
        catch (IOException ioe) 
        {
            ioe.printStackTrace();
        }
    }
}

動作しません。最初は完全に正常に実行されますが、その後は毎回入力ストリームから 0 バイトが利用可能になります。コマンドを試してみたいのwatchですが、この Solaris ボックスにはそれがありません。Java アプリケーションに PID があるかどうかを知る必要があるため、cron ジョブを使用できません。何か案は?

前もって感謝します。

編集: cron ジョブを使用できません

編集:Thread終了後に同じタイプ(PS)の新しいものを作成しているので、毎回新しい ProcessBuilder を確実に作成しています。

編集:混乱の原因となったので、機能しなかったループを元に戻しました。

4

3 に答える 3

3

ループがどこにあるかはわかりませんが、ループを通過するたびに新しいProcオブジェクト (したがって新しい) を作成する必要があります。InputStreamそうしないと、常に最初の呼び出しの結果を見ることになります。の javadocProcessBuilderは、毎回それらのいずれかを作成する必要がないことを示しています。

呼び出し時に入力ストリームの準備ができていない競合状態が発生する場合もありますavailable()。結果を出力する前に、入力ストリームが EOF に達したことを確認する必要があります (たとえば、top ではなく、ps で発生します)。

「ps」の出力が(ASCII以外で)どのようなエンコーディングであるかはわかりませんが、エンコーディングも適切に処理していません。"ps" はおそらく ASCII であるため、これはかなり安全ですが、他のコマンド (および他の入力ストリーム) に対してはそうではないかもしれません。

于 2009-06-24T19:00:35.830 に答える
1

したがって、問題は、ps の実行が終了する前に入力ストリームをチェックしていることだと思います。追加してみてください:

proc.waitFor()

osInput.available() を呼び出す前に。

これが私がそれをどのように実装したかです:

    TimerTask task = new TimerTask() {

        private void work() throws Exception {
            System.out.println("Now");
            ProcessBuilder pb = new ProcessBuilder("ps");
            Process p = pb.start();
            p.waitFor();
            BufferedReader reader
                = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                // Process line
                System.out.println(line);
            }
        }

        @Override
        public void run() {
            try {
                work();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };

    Timer timer = new Timer();
    long period = 5000;
    timer.scheduleAtFixedRate(task, 0, period);
于 2009-06-24T19:21:39.940 に答える