簡體   English   中英

Java - 如何檢查 Linux 上是否正在運行另一個(非 Java)進程

[英]Java - how to check whether another (non-Java) process is running on Linux

我對此有一些奇怪的問題。

我們正在使用 Xvfb 虛擬桌面管理器,並希望在我繼續之前確保它正在運行。 使用純 shell,我可以輕松做到這一點:

    ps -ef | grep Xvfb | grep -v grep

這正是我所需要的,一行包含有關 Xvfb proc 的信息。 接下來,我想將其合並到我的 Java 程序中並解析結果並存儲正在運行的 Xvfb 進程的 PID。 所以我正在嘗試這個:

    String line;
    try {
      Process p = Runtime.getRuntime().exec("ps -ef | grep Xvfb | grep -v grep");
      BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
      while ((line = input.readLine()) != null)
      {
        System.out.println(line);
      }
    } catch (Exception err) {
      System.out.println(err);
    }

奇怪的是,如果我使用“ps -ef”,當我運行我的應用程序時,我會得到大量進程轉儲到我的控制台。 但是如果我使用 | grep 縮小返回的進程列表,我得到零結果。 input.readLine() 每次都得到 null。

我也試過:

    ps -ef | grep Xvfb | grep -v grep | awk {'print $2'}

只需獲取進程ID。 此外,沒有運氣。

有沒有其他人經歷過這個或知道我做錯了什么?

你正試圖用“|” 這是一個特定於shell的管道函數,因此您無法在Java進程中執行此操作。 您可以嘗試使用pidof Xvfb來獲取進程ID。

也許Runtime.getRuntime().exec()嘗試執行程序,因為它在參數中。 也就是說,它使用參數-ef|運行程序ps grep等等。因此,該程序失敗,因為它不明白發生了什么。

如果需要運行管道命令,則應該顯式調用shell:

Runtime.getRuntime().exec(new String[] {"sh", "-c", "ps -ef | grep Xvfb | grep -v grep"});

當你直接執行你的命令字符串時,你沒有得到一個shell,它是處理管道的shell。 所以,你會執行像“/ bin / sh -e \\”ps -ef |這樣的東西 grep Xvfb | grep -v grep \\“”

有很多方法可以做到這一點。 您可以使用java.lang.ProcessBuilder和“pgrep”來獲取進程ID(PID),例如: pgrep -fl java | awk {'print $1'} pgrep -fl java | awk {'print $1'} 或者,如果您在Linux下運行,則可以查詢/proc目錄。

我知道,這似乎很糟糕,而且不便攜,甚至執行不力,我同意。 但是因為Java實際上是在VM中運行的,出於一些荒謬的原因,我在JDK工作超過15年之后無法弄清楚,這就是為什么不可能看到JVM空間以外的東西,如果你真的很荒謬想一想。 你可以做其他一切,甚至分叉和加入子進程( 當世界不知道線程線程時 ,那些是多任務處理的可怕方式,這到底是什么!Java發生了什么?! :)。

這將是我所知道的一個巨大的討論,但無論如何,我已經在我的項目中使用了一個非常好的API並且它足夠穩定(它是OSS所以你仍然需要在真正信任API之前對你使用的每個版本進行壓力測試): https ://github.com/jezhumble/javasysmon

JavaDoc: httpcom.jezhumble.javasysmon.OsProcess ,搜索com.jezhumble.javasysmon.OsProcess類,她會做的伎倆。 希望它有所幫助,祝你好運。

不確定這是否有幫助,但我只需要檢查我的應用程序的另一個實例是否在 Linux 中運行,所以我實現了這個,它可以返回另一個實例的計數或 PID(所以我可以把它放在前面並停止加載新實例)。

public long checkIsAlreadyRunning(){
    //Check if app is already running
     long lngCountOfInstances = 0; //Use this to hold how many already running
     String strProcessName = "AG2_GetData";
     //If it is required to also capture app running from within NetBeans, remove the .jar
     so("ps -ef|grep " + strProcessName);
     try{
         long lngPid = ProcessHandle.current().pid();//PID of this instance of the application
         long lngPidOfRunning = 0; //Holder for PID of already running instance
         System.out.println(lngPid+""); //Only for verification
         
         Runtime rt = Runtime.getRuntime();
         String[] cmd = {"/bin/sh", "-c", "ps -ef|grep " + strProcessName };
         Process proc = rt.exec(cmd);

         delay_ms(2);//found I needed small delay to ensure buffer was ready
         
         BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
         
         String strLineIn;
         StringBuilder strOutput = new StringBuilder();
         String strProcessId = "";
         while ((strLineIn = reader.readLine()) != null) {                   
            if(!strLineIn.contains("grep") && !strLineIn.contains(String.valueOf(lngPid))) {//ignore is PID is current, or line contais grep 
                strOutput.append(strLineIn + "\r\n");//Only here for debuging
                lngCountOfInstances++;
            }
         }
         reader.close(); //always close the reader
         String strReturn = removeDuplicates(strOutput.toString()," "); // remove duplicate spaces frm reteun
         String[] strArray = strReturn.split(" ");
         if(strArray.length>2){lngPidOfRunning = isLong(strArray[1]);}//Aray index 1 will be PID, isLong checks if valid long and if yes, retunrs long, esle 0;
         System.out.println(lngPidOfRunning + " --> " + strReturn); //Only here for debuging
     }
     catch(Exception ex){
         ex.printStackTrace();
         err(ex.getMessage(), ex); //remove this, I use function to log messages and stacktraces to file
     }
     //return lngPidOfrunning; //Use this is you would like to use the PID to bring running instance to front
     return lngCountOfInstances; //use this if you just want to get count of running instances
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM