[英]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: http : com.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.