Linux 下 java 監控 程序運行

需求是:tomcat的java進程經常100%佔用CPU,此時servlet也停止響應了,業務邏輯除了問題。

希望有一個在PC上跑的監控程序,能夠在tomcat 100%佔用cpu的時候殺死。同時tomcat自動重啓。


過程:tomcat自動重啓是通過腳本實現 start_tomcat.sh :


下一步就是要檢測tomcat的進程的PID。命令是:test.sh


拿到CPU佔用情況:

ps -p PID -o %cpu,%mem,cmd

這條命令是在java環境中執行 RunTime.exec:


.這篇博客的重點在於:

原本在bash下面執行的ps 命令,如果想通過java執行並且獲得ps輸出,需要以 exec(new String[]{"/bin/sh","-c","正常控制檯執行的命令"}) 這種形式纔可以。

參考【http://huajianhsiu.iteye.com/blog/1772775】,可能是多重重定向導致的錯誤。這個方法是可以通用的。

下面是監控源碼


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

public class Monitor {




/**
* @param args
*/
public static void main(String[] args) {

try {
double last =0;
while(true)
{
TimeUnit.SECONDS.sleep(10);
String pid =getPID();
if(pid==null||pid.trim().length()==0)
{
continue;
}
System.out.println(pid);
String info =getCPU(pid);
System.out.println(info);
double cur =Double.parseDouble(info);
if(last>80&&cur>80)
{
Kill();

}
else {
last=cur;
}
}

 
} catch (Exception e) {
 
}

 
 

}

 
public static void Kill ( ) throws Exception
{
String pid =getPID();

if(pid==null||pid.trim().length()==0)
return ;

Runtime rt = Runtime.getRuntime();
 
Process proc = rt.exec(new String[] { "/bin/sh","-c", "kill -9 "+pid});


BufferedReader stdInput = new BufferedReader(new 
    InputStreamReader(proc.getInputStream()));
  
}

public static String getPID()  throws Exception
    {
Runtime rt = Runtime.getRuntime();
 
Process proc = rt.exec(new String[] { "/bin/sh","-c", "/home/apps/test.sh"});


BufferedReader stdInput = new BufferedReader(new 
    InputStreamReader(proc.getInputStream()));


BufferedReader stdError = new BufferedReader(new 
    InputStreamReader(proc.getErrorStream()));


// read the output from the command
StringBuilder sb =new StringBuilder();
String s = null;
while ((s = stdInput.readLine()) != null) {
  sb.append(s.trim());
}


  return sb.toString().trim();

    }
 
public static String getCPU(String pid)  throws Exception
    {
Runtime rt = Runtime.getRuntime();
 
Process proc = rt.exec(new String[] {"/bin/sh","-c","ps -p "+pid+" -o %cpu,%mem,cmd"});


BufferedReader stdInput = new BufferedReader(new 
    InputStreamReader(proc.getInputStream()));


// read the output from the command
StringBuilder sb =new StringBuilder();
String s = null;
while ((s = stdInput.readLine()) != null) {
  sb.append(s);
}


String []cp =sb.toString().split(" ");
return cp[3];
   

    }

}
-----------------------------------------------------------------------------------------------------------------------------

2015年11月17日10:33:05修正:經過晚上的測試,發現上述的getCPU函數並不能準確描述當前系統的CPU佔用情況。

後來在阿里雲裏面採取了這個命令:top -bn2|grep 'Cpu(s)'|awk '{print $8}'|awk -F'%' '{print $1}'|tail -n1

取到的值爲空閒狀況;若這個值低於20,則認爲cpu忙,10s檢測一次,若連續2次都低於20,則進行重啓tomcat. 修改如下。

public static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static SimpleDateFormat sdf2 =new SimpleDateFormat("yyyy-MM-dd-HHmmss");
 
 public static void main(String[] args)
 {
   try
   {
     double last = 0.0D;
     for (;;)
     {
       TimeUnit.SECONDS.sleep(10L);
       
       String info = getCPU();
       System.out.println(sdf.format(new Date()) + "|" + info);
       double cur = Double.parseDouble(info);
       if ((last < 20.0D) && (cur < 20.0D)) {
         Kill();
       } else {
         last = cur;
       }
     }
   }
   catch (Exception e)
   {
     e.printStackTrace();
   }
 }
 
 public static void Kill()
   throws Exception
 {
   String pid = getPID();
   if ((pid == null) || (pid.trim().length() == 0)) {
     return;
   }
   Jstack(pid);
   Runtime rt = Runtime.getRuntime();
   
   Process proc = rt.exec(new String[] { "/bin/sh", "-c", "kill -9 " + pid });
   
   BufferedReader stdInput = new BufferedReader(
     new InputStreamReader(proc.getInputStream()));
 }
 
 public static void Jstack(String pid) throws Exception
 {
 Runtime rt = Runtime.getRuntime();
   
   Process proc = rt.exec(new String[] { "/bin/sh", "-c", " jstack " + pid+" > /home/apps/"+sdf2.format(new Date())+".log" });
 }
 
 
 public static String getPID()
   throws Exception
 {
   Runtime rt = Runtime.getRuntime();
   
   Process proc = rt.exec(new String[] { "/bin/sh", "-c", "/home/apps/test.sh" });
   
   BufferedReader stdInput = new BufferedReader(
     new InputStreamReader(proc.getInputStream()));
   
   BufferedReader stdError = new BufferedReader(
     new InputStreamReader(proc.getErrorStream()));
   


   StringBuilder sb = new StringBuilder();
   String s = null;
   while ((s = stdInput.readLine()) != null) {
     sb.append(s.trim());
   }
   return sb.toString().trim();
 }
 
 public static String getCPU()
   throws Exception
 {
   Runtime rt = Runtime.getRuntime();
   
   Process proc = rt.exec(new String[] { "/bin/sh", "-c", "top -bn2|grep 'Cpu(s)'|awk '{print $8}'|awk -F'%' '{print $1}'|tail -n1" });
   
   BufferedReader stdInput = new BufferedReader(
     new InputStreamReader(proc.getInputStream()));
   


   StringBuilder sb = new StringBuilder();
   String s = null;
   while ((s = stdInput.readLine()) != null) {
     sb.append(s);
   }
   return sb.toString().trim();
 }


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章