2009-12-09 150 views
1

我需要编写一个Groovy脚本来启动一个进程,读取进程出错& err流,然后等待输出特定的文本行。等待不应该是无限的,但应该在一段时间后超时。在Groovy或Java中启动一个进程并等待条件

这就是我想出来的。有没有更好的办法?

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文件很简单:

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" 

回答

1

这似乎是它的工作。可能进一步简化它有几个建议:

  1. 的等待时间queue.poll()也许应该是剩余时间:(启动+米利斯) - 现在
  2. 如果在队列中的值不必要时,线程可以检查条件并发出CountDownLatch信号。

当然,如果目标程序是Groovy脚本,你很可能只是运行在同一个JVM,并让它用的CountDownLatch什么的呼叫用户进行通信。