I need to write a Groovy script which launches a process, reads the processes out & err streams, and wait for a particular line of text to be outputted. The wait should not be indefinite, but should time out after a while.
This is what I came up with. Is there a better way?
def proc = "groovy test.groovy".execute(null, new File("."))
def timeout = 10 * 1000
printProcessOutput(proc, timeout) {line, count ->
false /* replace with evaluation of some actual condition */
}
def printProcessOutput(proc, millis, condition) {
def queue = new java.util.concurrent.LinkedBlockingQueue()
def out = new StreamReader(new InputStreamReader(proc.inputStream), queue)
def err = new StreamReader(new InputStreamReader(proc.errorStream), queue)
def outThread = new Thread(out); outThread.start()
def errThread = new Thread(err); errThread.start()
def start = System.currentTimeMillis()
def end = start
def count = 0
while (end < start + millis) {
def line = queue.poll(10, java.util.concurrent.TimeUnit.MILLISECONDS)
if (line) {
println line
count++
if (condition(line, count)) {
break
}
}
end = System.currentTimeMillis()
}
out.kill(); try { outThread.interrupt() } catch (ex) { }
err.kill(); try { errThread.interrupt() } catch (ex) { }
def temp = []
queue.drainTo(temp)
temp.each { println "TEMP: $it" }
}
class StreamReader implements Runnable {
final def reader
final def queue
volatile def killed = false
public StreamReader(reader, queue) {
this.reader = reader
this.queue = queue
}
def void run() {
def buff = new BufferedReader(reader)
def line = buff.readLine()
while (!killed && line != null) {
queue.offer(line)
line = buff.readLine()
}
}
def kill() {
killed = true
}
}
test.groovy file is simply:
def rand = new Random()
def delta = 5 * 60 * 1000
def start = System.currentTimeMillis()
def end = start
while (end < start + delta) {
if (rand.nextBoolean()) {
System.err.println("ERR " + new Date())
} else {
System.out.println("OUT " + new Date())
}
Thread.sleep(100)
end = System.currentTimeMillis()
}
println "Done"