Groovy执行shell命令

Groovy执行shell命令,groovy,Groovy,Groovy将execute方法添加到String中,使shell的执行变得相当容易 println "ls".execute().text 但如果发生错误,则不会有结果输出有没有一种简单的方法可以同时获取标准错误和标准错误?(除了创建一组代码之外;创建两个线程来读取两个输入流,然后使用父流等待它们完成,然后将字符串转换回文本?) 有这样的东西会很好 def x = shellDo("ls /tmp/NoFile") println "out: ${x.out} err:${x.err}"

Groovy将
execute
方法添加到
String
中,使shell的执行变得相当容易

println "ls".execute().text
但如果发生错误,则不会有结果输出有没有一种简单的方法可以同时获取标准错误和标准错误?(除了创建一组代码之外;创建两个线程来读取两个输入流,然后使用父流等待它们完成,然后将字符串转换回文本?)

有这样的东西会很好

 def x = shellDo("ls /tmp/NoFile")
 println "out: ${x.out} err:${x.err}"
“ls.execute()
返回一个
进程
对象,这就是
“ls.execute()”文本
工作的原因。您应该能够读取错误流以确定是否存在任何错误

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这样的文件或目录

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

// 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 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)


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

+1这将在生成输出时以增量方式显示输出。这对于长时间运行的进程非常重要@mholm815要使用此解决方案,请发出以下行:
runCommand(“echo HELLO WORLD”)
@mholm815我们如何从管道本身批准所需的脚本?如果您还需要为此过程设置环境变量,请确保将命令包装在shell中。例如,使用env vars运行Perforce命令:
envVars=[“P4PORT=p4server:2222”、“P4USER=user”、“P4PASSWD=pass”、“P4CLIENT=p4workspace”];workDir=新文件(“路径”);cmd=“bash-c\”p4更改-o 1234\”;proc=cmd.execute(envVars,workDir)
@paul_sns与OP问题无关,但我认为现代JVM可以很好地处理无争用同步。因此,StringBuffer不太可能在线程或堆栈受限的情况下降低性能。文档说,我们应该使用waitForProcessOutput()-“等待输出被完全使用,调用waitForProcessOutput()。来源:@srikanth waitForProcess()输出文档也会说“如果您不关心标准或错误输出,只希望进程以静默方式运行,请使用此方法”-我希望输出sout和serr即使在waitForOrKill之后也可能不可用。使用断言而不是println进行测试。文档说:“为此,启动了两个线程,因此此方法将立即返回。即使调用了waitFor(),线程也不会被join()。要等待输出被完全使用,请调用waitForProcessOutput()。”这很有用。演示了如何使用cURL演示运行shell命令。我真的很恼火,有人花时间给出答案,而有人只是无缘无故地否决了它。如果这是一个社区,你应该觉得有义务添加一条注释(除非这是一个非常明显的原因,任何有能力的程序员都会立即看到)来解释否决票。@AmosBordowitz很多答案都会被否决票。没关系,投了一票反对票。也就是说,这可能是因为它的代码没有任何解释——并不总是很受欢迎。@ChrisBaker那么为什么不指出它呢?你自己也不肯定这是原因。@AmosBordowitz我不是官方的否决票解释人,我不能告诉你为什么不,我不确定是可以理解的,因为我们谈论的是另一个人采取的行动。我提出了一种可能性。为什么不解释否决票,当然,为什么不解释答案中的代码?无论如何,我相信我们都会没事的。@ChrisBakerI从来没有这样说过(“但我想你知道得更清楚”)。这是一件体面的事情,而不是知识的事情。
sh
来自哪里?
sh
是詹金斯groovy DSL的一部分。Jenkins Groovy DSL可能没有用!=Groovyas和其他人说过的一样,这是Jenkins DSL的一部分。这个答案不适用于所问的问题。它不适用于Bourn Shell脚本#/bin/bash,如果使用bash脚本,您可能会调用bash作为命令的一部分:“/bin/bash script.execute()
command = "ls *"

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