2012-01-20 51 views
-1

我已經編寫了一個代碼來檢查HSQL,JBoss,Radius(AAA服務器)和MySQL是否在運行。代碼被寫入inifinte while循環現在我測試瞭如果這個服務(假設hsql)正在運行,那麼/bin/bash -c ps -ef | grep 'hsql' | wc -l將返回3,當它作爲Runtime.exec()方法中的參數傳遞時。現在我已經知道分叉進程的輸入流或errstream不能溢出。否則會導致死鎖。Runtime.exec問題Process.getInputStream和Process.waitFor()

牢記這一點我寫了這個代碼:

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.util.Date; 

public class MonitorHsqlJBossRadius { 

    public static void main(String[] args) { 
     String hsqlCmd[] = {"/bin/bash","-c","ps -ef | grep 'hsql' | wc -l "}; 
     String jbossCommand[] = {"/bin/sh","-c","ps -ef | grep 'jboss' | wc -l"}; 
     String radiusCommand[] = {"/bin/sh","-c","ps -ef | grep 'radius' | wc -l"}; 
     String mySqlCommand[] = {"/bin/sh","-c","/etc/init.d/mysqld status"}; 
     String line = null; 
     String mobNo = "(obscured)"; 
     Process process = null; 
     Runtime runtime = Runtime.getRuntime(); 
     BufferedReader reader = null; 
     SendSMS sender = new SendSMS(); 
     boolean sendMsgHsql = false; 
     boolean sendMsgJBoss = false; 
     boolean sendMsgRadius = false; 
     int itr = 1; 
     while(true) 
     { 
      try 
      { 
       process = runtime.exec(hsqlCmd); 
       reader = new BufferedReader(new InputStreamReader(process.getInputStream())); 
       while((line=reader.readLine())!=null) 
       { 
        if (!line.equals("3")) 
         sendMsgHsql = true; 
       } 

       process.waitFor(); 
       if (sendMsgHsql) 
       { 
        //sender.sendSMS("HSQL is not running "+(new Date().toString()), mobNo,1,itr); 
        System.out.println("HSQL is not running "+itr); 
       } 
       else 
        System.out.println("HSQL is running "+itr); 

       sendMsgHsql = false; 

       process = runtime.exec(jbossCommand); 
       reader = new BufferedReader(new InputStreamReader(process.getInputStream())); 
       while((line=reader.readLine())!=null) 
       { 
        if (!line.equals("3")) 
         sendMsgJBoss = true; 
       } 

       process.waitFor(); 
       if (sendMsgJBoss) 
       { 
        //sender.sendSMS("JBoss is not running "+(new Date().toString()), mobNo,2,itr); 
        System.out.println("JBoss is not running "+itr); 
       } 
       else 
        System.out.println("JBoss is running "+itr); 

       sendMsgJBoss = false; 

       process = runtime.exec(radiusCommand); 
       reader = new BufferedReader(new InputStreamReader(process.getInputStream())); 
       while((line=reader.readLine())!=null) 
       { 
        if(!line.equals("3")) 
         sendMsgRadius = true; 
       } 

       process.waitFor(); 
       if (sendMsgRadius) 
       { 
        //sender.sendSMS("Radius is not running "+(new Date().toString()), mobNo,3,itr); 
        System.out.println("Radius is not running "+itr); 
       } 
       else 
        System.out.println("Radius is running "+itr); 

       sendMsgRadius = false; 
      } 


      catch (IOException e) { 
       e.printStackTrace(); 
      } 
      catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 

      try 
      { 
       System.out.println("\n--------- "+itr+" ------------\n"); 
       itr++; 
       Thread.sleep(1000*5); 
      } 
      catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

我期待的輸出如下

 
HSQL is running/not running 1 
JBoss is running/not running 1 
MySQL is running/not running 1 
-------------------1---------------- 

HSQL is running/not running 2 
JBoss is running/not running 2 
MySQL is running/not running 2 
-------------------2---------------- 

等等...

Howevere我」沒有像這樣得到輸出。有時HSQL的狀態消息不會被打印,或者有時JBoss狀態消息不會被打印。即使有時我得到的輸出像

 
------------------1---------------------- 

打印此狀態消息後。我想說的是,這似乎是一些競爭條件或一些同步問題。

+0

對不起,未格式化的代碼發佈.... –

+1

請以可讀的方式格式化您的代碼。你可以在這裏看到如何做到這一點:http://stackoverflow.com/editing-help#code –

回答

1

試圖通過解析ps的輸出來確定進程是否正在運行通常不是一個好主意。典型的錯誤是grep processname匹配(至少)兩個進程:processname和grep進程本身。

這樣做的通常的方法是:

  • 啓動進程時,寫的PID到文件
  • 檢查過程中時,從文件中讀取PID,看看它是否存在通過發送一個信號

一個更健壯和優雅的做法是讓流程打開一個套接字並檢查這個套接字是否可用,但在這種情況下,你不想在你的代碼中添加這個代碼服務器。但是,您要檢查的進程已經偵聽TCP端口。我會編寫試圖連接到此端口的代碼(通常,jboss的端口80,mysql的3306,hsql的端口9001)使用UDP時,Radius更加棘手。您可以嘗試執行身份驗證,或者您可以使用特定的radius服務器查找特定的特徵。

0

我不相信你的代碼由於競爭條件或同步而掛起。我無法訪問您的服務器,因此我無法運行您的代碼,但我懷疑您正在運行的進程是阻塞的,因爲它們正在寫入他們的標準錯誤,並且您沒有閱讀它。

Runtime.getRuntime().exec()創建的進程的標準錯誤流中讀取是可能的,但是從這個流中讀取必須在單獨的線程中完成。相反,我會推薦使用ProcessBuilder。在我看來,ProcessBuilder最顯着的好處是它可以將流程的標準錯誤重定向到與標準輸出相同的流中。這意味着你只有一個流可以讀取,並且不需要單獨的線程。

我還會注意到,您正在打開各種BufferedReader s但未關閉它們。我建議你在完成它們後關閉它們。

最後,我建議你不要重複幾乎相同的代碼三次。應該可以編寫一個方法,使命令行作爲String數組參數運行,使用ProcessBuilder運行命令行,並返回該命令的輸出是否爲3