Run a System Process from Scala

Here’s an example on how to run a System process from Scala.

+ ProcessBuilder simplifies the creation of the Process object
+ A Scala Actor reads the console output buffer concurrently
+ reactWithin allows us to timeout if the process hangs
+ receiveWithin in the main thread, guards us in case the Actor gets stuck

In this case we show the output of ls -1

One thing to notice is the continue val to exit the loop. At the time of writing, Scala 2.7 doesn’t support the break statement to exit loops. Support for break is expected in Scala 2.8

object Main {
    import java.io._
    import scala.actors._
    import scala.actors.Actor._
 
    private val caller = self
    private val WAIT_TIME = 2000
 
    private val reader = actor {
        println("created actor: " + Thread.currentThread)
        var continue = true
        loopWhile(continue){
            reactWithin(WAIT_TIME) {
                case TIMEOUT =>
                    caller ! "react timeout"
                case proc:Process =>
                    println("entering first actor " + Thread.currentThread)
                    val streamReader = new java.io.InputStreamReader(proc.getInputStream)
                    val bufferedReader = new java.io.BufferedReader(streamReader)
                    val stringBuilder = new java.lang.StringBuilder()
                    var line:String = null
                    while({line = bufferedReader.readLine; line != null}){
                        stringBuilder.append(line)
                        stringBuilder.append("\n")
                    }
                    bufferedReader.close
                    caller ! stringBuilder.toString
            }
        }
    }
 
    def run(command:String){
        println("gonna runa a command: " + Thread.currentThread)
        val args = command.split(" ")
        val processBuilder = new ProcessBuilder(args: _* )
        processBuilder.redirectErrorStream(true)
        val proc = processBuilder.start()
 
        //Send the proc to the actor, to extract the console output.
        reader ! proc
 
        //Receive the console output from the actor.
        receiveWithin(WAIT_TIME) {
                case TIMEOUT => println("receiving Timeout")
                case result:String => println(result)
        }
    }
 
    def main(args: Array[String]) :Unit = {
        println("Hello, world!")
        run("ls -1")
        System.exit(0)
    }
}

This entry was posted in Scala and tagged . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

2 Comments

  1. Posted December 2, 2010 at 4:23 pm | Permalink

    Thanks for writing this up!

    I hope that it’s OK that I’m using it for some code in a project. Since I didn’t call System.exit at the end of my app, my JVM never exited. Took me a few minutes (being new to Scala and actors) to find the missing “continue = false” in the actor block 🙂

    Thanks!

  2. Posted January 12, 2012 at 1:27 pm | Permalink

    Do you mind if I use your code in an open source project I’m working on? Here’s the project URL at Github: https://github.com/alvinj/Sarah

    Thanks,
    Al

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*