7
votes

If I started a process using Scala Process/ProcessBuilder. How can I get the pid of the process that was created?

I could not find any mention of the pid in the official docs: http://www.scala-lang.org/api/2.10.4/index.html#scala.sys.process.Process http://www.scala-lang.org/api/2.10.4/index.html#scala.sys.process.ProcessBuilder http://www.scala-lang.org/api/2.10.4/index.html#scala.sys.process.package

2

2 Answers

6
votes

2016: same question; I've been clicking through related questions for a few minutes, but still couldn't find any solution that is generally agreed upon. Here is a Scala version inspired by LRBH10's Java code in the answer linked by wingedsubmariner:

import scala.sys.process.Process

def pid(p: Process): Long = {
  val procField = p.getClass.getDeclaredField("p")
  procField.synchronized {
    procField.setAccessible(true)
    val proc = procField.get(p)
    try {
      proc match {
        case unixProc 
          if unixProc.getClass.getName == "java.lang.UNIXProcess" => {
          val pidField = unixProc.getClass.getDeclaredField("pid")
          pidField.synchronized {
            pidField.setAccessible(true)
            try {
              pidField.getLong(unixProc)
            } finally {
              pidField.setAccessible(false)
            }
          }
        }
        // If someone wants to add support for Windows processes,
        // this would be the right place to do it:
        case _ => throw new RuntimeException(
          "Cannot get PID of a " + proc.getClass.getName)
      }
    } finally {
      procField.setAccessible(false)
    }
  }
}

// little demo
val proc = Process("echo 'blah blah blaaah'").run()
println(pid(proc))

WARNING: scala code runner is essentially just a bash script, so when you use it to launch scala programs, it will do thousand things before actually starting the java process. Therefore, the PID of the java-process that you are actually interested in will be much larger than what the above code snippet returns. So this method is essentially useless if you start your processes with scala. Use java directly, and explicitly add Scala library to the classpath.

3
votes

The scala.sys.io.process classes are wrappers around the Java classes for starting processes, and unfortunately it is difficult to obtain the PID from this API. See the stackoverlow question for this, How to get PID of process I've just started within java program?.