Groovy выполнение команд оболочки
Groovy добавляет execute
метод String
чтобы сделать выполнение оболочек довольно легко;
println "ls".execute().text
но если происходит ошибка, то нет никакого результирующего вывода. есть ли простой способ получить как стандартную ошибку, так и стандарт? (кроме создания связки кода; создать два потока для чтения обоих входных потоков, а затем использовать родительский поток, чтобы дождаться их завершения, а затем преобразовать строки обратно в текст?)
было бы неплохо иметь что-то вроде:
def x = shellDo("ls /tmp/NoFile")
println "out: ${x.out} err:${x.err}"
7 ответов:
ок, решил сам;
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
// 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)
но при сбое команды процесс завершится
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]