首页 文章

Groovy执行shell命令

提问于
浏览
132

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

println "ls".execute().text

但如果发生错误,则没有结果输出 . Is there an easy way to get both the standard error and standard out? (除了创建一堆代码;创建两个线程来读取两个输入流,然后使用父流等待它们完成然后将字符串转换回文本?)

有类似的东西会很高兴;

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

7 回答

  • 18

    好的,我自己解决了;

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

    显示:

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

  • 12

    "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()
    
  • 5
    // 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()
    }
    
  • 146

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

    对于一个过程

    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中执行命令后捕获输出,因为后者是阻塞调用(SO question for reason) .

  • 35

    我发现这更像是惯用的:

    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"
    

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

  • 4
    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]
    
  • 25
    command = "ls *"
    
    def execute_state=sh(returnStdout: true, script: command)
    

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

相关问题