質問
Groovyは execute
メソッドを String
に追加して、シェルの実行をかなり簡単にします。
println "ls".execute().text
ただし、エラーが発生した場合、結果の出力はありません。 標準エラーと標準出力の両方を取得する簡単な方法はありますか?(大量のコードを作成する以外に、2つのスレッドを作成して両方の入力ストリームを読み取り、次に親ストリームを使用してそれらを待つ完了したら、文字列をテキストに戻しますか?)
次のようなものがあると便利です。
def x = shellDo("ls /tmp/NoFile")
println "out: ${x.out} err:${x.err}"
解決
わかりました、自分で解決しました;
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>誤り> ls:/ badDirにアクセスできません:そのようなファイルまたはディレクトリはありません
他のヒント
" ls" .execute()
は Process
オブジェクトを返すため、" ls" .execute()。text
は機能します。 。エラーが発生したかどうかを判断するために、エラーストリームを読み取ることができるはずです。
Process
には、 consumeProcessErrorStream(StringBuffer error)
。 StringBuffer
を渡してテキストを取得できる追加のメソッドがあります。
例:
def proc = "ls".execute()
def b = new StringBuffer()
proc.consumeProcessErrorStream(b)
println proc.text
println b.toString()
// 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()
}
上記の回答にもう1つの重要な情報を追加するには-
プロセスの場合
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の理由の質問)。
これはもっと慣用的だと思います:
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"
別の投稿で言及されているように、これらはブロッキング呼び出しですが、出力を処理したいので、これが必要になる場合があります。
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]
command = "ls *"
def execute_state=sh(returnStdout: true, script: command)
ただし、コマンドが失敗した場合、プロセスは終了します