How do I find the process ID (pid) of a process st

2020-01-27 06:03发布

问题:

If I get a process object in Java through Runtime.getRuntime().exec(...), or ProcessBuilder.start(), I can wait for it through Process.waitFor(), which is like Thread.join(), or I could kill it with Process.destroy(), which is like the deprecated Thread.stop().

BUT: How do I find the pid of the Process Object? I don't see a method for doing that in The Official Documentation. Can I do this in Java? If so, how?

回答1:

This guy calls out to bash to get the PID. I'm not sure if there is an java solution to the problem.

/**
 * Gets a string representing the pid of this program - Java VM
 */
public static String getPid() throws IOException,InterruptedException {

  Vector<String> commands=new Vector<String>();
  commands.add("/bin/bash");
  commands.add("-c");
  commands.add("echo $PPID");
  ProcessBuilder pb=new ProcessBuilder(commands);

  Process pr=pb.start();
  pr.waitFor();
  if (pr.exitValue()==0) {
    BufferedReader outReader=new BufferedReader(new InputStreamReader(pr.getInputStream()));
    return outReader.readLine().trim();
  } else {
    System.out.println("Error while getting PID");
    return "";
  }
}

Source: http://www.coderanch.com/t/109334/Linux-UNIX/UNIX-process-ID-java-program



回答2:

Similar to the other tools mentioned, there is the jps command line tool that comes with the Java runtime. It spits out the PIDs of all running JVMs. The benefit is the output one needs to parse is confined to only the JVM processes.



回答3:

Leo, after looking into this issue for about a week myself I think Jhurtado's approach is likely the "best" approach we can manage in Java right now. "best" is in quotes because it has the very nasty side effect of basically being a "guess" at what your child PID is.

If your Java app is spawning native processes quickly in a high-load system, there is NO guarantee that the PID you pickup in your diff calculation is the PID of the Process started by the current Thread or that the PID of the process you pick was even spawned by our app (maybe the host system was already running that process anyway).

That being said, if you are not spawning dozens of processes or the native Process you are spawning is really unique (some custom util you ship with your app) then this approach works fine in which case the PID of the native process you are looking for is the one you want.

On windows you can use 'tasklist' as Jhurtado pointed out to get the full list of PIDs and filter for the one you want (using the /FI filter switch didn't work for me in testing).

On any *nix system you can use "ps ax | grep " where NAME is some process name like 'nginx' or 'httpd' that you want to filter for to get your list.

Additionally, if you need to kill stray processes (for example, on VM exit) on *nix you can of course use "kill -9 " and on Windows, interestingly enough, you can use 'taskkill '.

Hardly optimal unfortunately.



回答4:

I ran into the same issue as you. I found a pretty decent solution, I recommend a slight sleep before it thought to ensure the process has officially started up.

Process p = Runtime.getRuntime().exec("cmd /c tasklist");
StringWriter writer = new StringWriter();
IOUtils.copy(p.getInputStream(), writer);
String theString = writer.toString();
//System.out.println(theString);
id = findLastString("javaw.exe                     .{1,} Console                    1", theString);
System.out.println(id);

where findLastString is defined as

public static String findLastString(String pattern, String in) {
     Pattern p = Pattern.compile(pattern);
     Matcher matcher = p.matcher(in);
     String it= "";
     while(matcher.find()) {
       it = matcher.group();
       try {
        Thread.sleep(10);
       } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
       }
     }
     int firstIndex=pattern.indexOf(".{1,}");
     int lastIndex=it.substring(firstIndex).indexOf(pattern.substring(pattern.indexOf(".{1,}")+5))+firstIndex;
     String dotOn = it.substring(pattern.indexOf(".{1,}"));

     it=it.substring(firstIndex, lastIndex);
     return it;
 }

Basically this will get the list of running processes, and find the most recently ran one with, in this instance, the name javaw.exe (My program was starting a separate java process). You can replace javaw.exe with the name of the process, which you can find by using Task Manager. You will need to get the Apache common IO jar too.



回答5:

I think in Java your best shot is to get the tasklist before and after spawning your child process. Make a diff and get your PID.

you can get the Tasklist by issuing a Runtime.getRuntime.exec("tasklist");
Notice that tasklist.exe is not included with Windows XP Home edition, but still you can download it.