2

我正在将 Bash shell 脚本移植到 Groovy。大多数构造都可以轻松转换(例如转换mkdir "$foo"foo.mkdir(). 但是,我对此感到困惑:

#!/bin/bash
sleep 60 > /tmp/output.log 2>&1 < /dev/null

运行它时,让我们检查以下文件描述符sleep

$ ls -l /proc/$(pgrep sleep)/fd
total 0
lr-x------ 1 user user 64 Feb 25 13:40 0 -> /dev/null
l-wx------ 1 user user 64 Feb 25 13:40 1 -> /tmp/output.log
l-wx------ 1 user user 64 Feb 25 13:40 2 -> /tmp/output.log

可以通过这种方式在 Groovy 中运行进程(根据此页面):

#!/usr/bin/groovy
def log = new FileOutputStream("/tmp/output.log")
def sleep = "sleep 60".execute()
sleep.waitForProcessOutput(log, log)

和文件描述符sleep

$ ls -l /proc/$(pgrep sleep)/fd
total 0
lr-x------ 1 user user 64 Feb 25 13:41 0 -> pipe:[522455]
l-wx------ 1 user user 64 Feb 25 13:41 1 -> pipe:[522456]
l-wx------ 1 user user 64 Feb 25 13:41 2 -> pipe:[522457]

可以看出,文件描述符与其他东西相关联(可能是 Groovy 进程)。因为这将用于长期运行的过程,所以我想去掉 Groovy 作为中间人。

所以,我的问题是:如何将文件重定向到文件stdin和文件stdoutstderr以便可以分离外部进程并且不需要运行 Groovy?

编辑:这个问题不是Groovy 中捕获进程输出的重复,因为该问题涉及重定向stdout和Groovy 进程本身stderrstdoutand 。stderr从@tim_yates 的回答可以看出,这是完全不同的事情。

4

2 回答 2

2

ProcessBuilder.redirectOutput()从 Java 7 开始可以解决这个问题。而且因为它是标准的 Java,所以也可以在 Groovy 中使用。

#!/usr/bin/groovy
def sleep = new ProcessBuilder('sleep', '60')
                    .redirectOutput(new File('/tmp/output.log'))
                    .redirectErrorStream(true)
                    .redirectInput(new File('/dev/null'))
                    .start();

结果:

$ ls -l /proc/$(pgrep sleep)/fd
total 0
lr-x------ 1 user user 64 Feb 26 11:44 0 -> /dev/null
l-wx------ 1 user user 64 Feb 26 11:44 1 -> /tmp/output.log
l-wx------ 1 user user 64 Feb 26 11:44 2 -> /tmp/output.log

ProcessBuilder.start()返回 a java.lang.Process,由 Groovy 修饰。诸如此类的方法waitForOrKill仍然有效。

于 2015-02-26T11:13:25.063 回答
0

为什么不直接利用外壳?让它做它被设计做的事情。以机智:

#!/usr/bin/groovy
def sleep = (["sh", "-c", "sleep 60 > /tmp/output.log 2>&1 < /dev/null"] as String[]).execute()

如果您需要以编程方式指定输出文件,则只需使用 GString:

#!/usr/bin/groovy
def outfile = "/tmp/output.log"
String[] sleepCmd = ["sh", "-c", "sleep 60 > ${outfile} 2>&1 < /dev/null"]
def sleep = sleepCmd.execute()

(编辑两个示例以使用String[]而不是String

于 2015-02-25T22:07:36.630 回答