Groovy执行shell命令

Groovy将execute方法添加到String中,以使执行shell相当容易;

println "ls".execute().text

但是如果发生错误,则不会产生输出。是否有一种简单的方法可以同时得到标准错误和标准?(除了创建一堆代码来;创建两个线程来读取两个输入流,然后使用父流等待它们完成,然后将字符串转换回文本?)

如果能有这样的东西就好了;

 def x = shellDo("ls /tmp/NoFile")
println "out: ${x.out} err:${x.err}"
368038 次浏览

"ls".execute()返回一个Process对象,这就是为什么"ls".execute().text可以工作。您应该能够读取错误流,以确定是否有任何错误。

Process上有一个额外的方法,允许你传递一个StringBuffer来检索文本:consumeProcessErrorStream(StringBuffer error)

例子:

def proc = "ls".execute()
def b = new StringBuffer()
proc.consumeProcessErrorStream(b)


println proc.text
println b.toString()

我自己解出来的;

def sout = new StringBuilder(), serr = new StringBuilder()
def proc = 'ls /badDir'.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println "out> $sout\nerr> $serr"

显示:

out> err> ls: cannot access /badDir: No such file or directory

// a wrapper closure around executing a string
// can take either a string or a list of strings (for arguments with spaces)
// prints all output, complains and halts on error
def runCommand = { strList ->
assert ( strList instanceof String ||
( strList instanceof List && strList.each{ it instanceof String } ) \
)
def proc = strList.execute()
proc.in.eachLine { line -> println line }
proc.out.close()
proc.waitFor()


print "[INFO] ( "
if(strList instanceof List) {
strList.each { print "${it} " }
} else {
print strList
}
println " )"


if (proc.exitValue()) {
println "gave the following error: "
println "[ERROR] ${proc.getErrorStream()}"
}
assert !proc.exitValue()
}

在以上提供的答案中添加一个更重要的信息-

对于流程来说

def proc = command.execute();

总是尝试使用

def outputStream = new StringBuffer();
proc.waitForProcessOutput(outputStream, System.err)
//proc.waitForProcessOutput(System.out, System.err)

而不是

def output = proc.in.text;

在groovy中执行命令后捕获输出,因为后者是一个阻塞调用(为什么要问这个问题)。

def exec = { encoding, execPath, execStr, execCommands ->


def outputCatcher = new ByteArrayOutputStream()
def errorCatcher = new ByteArrayOutputStream()


def proc = execStr.execute(null, new File(execPath))
def inputCatcher = proc.outputStream


execCommands.each { cm ->
inputCatcher.write(cm.getBytes(encoding))
inputCatcher.flush()
}


proc.consumeProcessOutput(outputCatcher, errorCatcher)
proc.waitFor()


return [new String(outputCatcher.toByteArray(), encoding), new String(errorCatcher.toByteArray(), encoding)]


}


def out = exec("cp866", "C:\\Test", "cmd", ["cd..\n", "dir\n", "exit\n"])


println "OUT:\n" + out[0]
println "ERR:\n" + out[1]

我觉得这个更地道:

def proc = "ls foo.txt doesnotexist.txt".execute()
assert proc.in.text == "foo.txt\n"
assert proc.err.text == "ls: doesnotexist.txt: No such file or directory\n"

正如另一篇文章提到的,这些是阻塞调用,但由于我们想要处理输出,这可能是必要的。

command = "ls *"


def execute_state=sh(returnStdout: true, script: command)

但是如果命令失败,进程将终止