Harika komutlar yürütme


178

Groovy, mermilerin çalıştırılmasını oldukça kolay hale getirme executeyöntemini ekler String;

println "ls".execute().text

ancak bir hata oluşursa, sonuçta sonuç çıkmaz. Hem standart hatayı hem de standart çıktıyı almanın kolay bir yolu var mı? (bir grup kod oluşturmaktan başka; her iki giriş akışını okumak için iki iş parçacığı oluşturmak, daha sonra tamamlanmasını beklemek için bir üst akış kullanmak ve dizeleri metne geri dönüştürmek mi istiyorsunuz?)

Gibi bir şeye sahip olmak güzel olurdu;

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

Bu bağlantı faydalıdır. CURL demosu ile shell komutunun nasıl çalıştırılacağını gösterir.
Aniket Thakur

Yanıtlar:


207

Tamam, kendim çözdüm;

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

görüntüler:

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


13
Ortam Değişkenlerini de bu işleme ayarlamanız gerekirse, komutu kabuk içine aldığınızdan emin olun. Örneğin, env ile bir Perforce komutu çalıştırmak:envVars = ["P4PORT=p4server:2222", "P4USER=user", "P4PASSWD=pass", "P4CLIENT=p4workspace"]; workDir = new File("path"); cmd = "bash -c \"p4 change -o 1234\""; proc = cmd.execute(envVars, workDir);
Noam Manos

@paul_sns OP sorusuyla ilgili değil, ancak modern JVM'lerin koşulsuz senkronizasyonu iyi işlediğini düşünüyorum. Dolayısıyla StringBuffer'ın iş parçacığı veya yığınla sınırlı senaryolarda performansı düşürmesi olası değildir.
Pavel Grushetzky

3
Dokümanlar waitForProcessOutput () - "Çıktının tamamen tüketilmesini beklemek için waitForProcessOutput () 'u arayın" diyor. Kaynak: docs.groovy-lang.org/latest/html/groovy-jdk/java/lang/…
Srikanth

4
@srikanth waitForProcess () çıktı dokümanları da "Standart veya hata çıktısı umurumda değil ve sadece sürecin sessizce çalışmasını istiyorsanız" bu yöntemi kullanın "- Çıktı istiyorum
Bob Herrmann

waitForOrKill'den sonra bile sout ve serr kullanılamayabilir. Println yerine assert kullanılarak test edildi. Dokümanlar şöyle diyor: "Bunun için iki İş Parçacığı başlatılır, bu nedenle bu yöntem hemen geri dönecektir. WaitFor () çağrılmış olsa bile iş parçacıkları birleştirme () işlemine tabi tutulmaz . Çıktının tamamen tüketilmesini beklemek için waitForProcessOutput () öğesini arayın ."
solstice333

49

"ls".execute()bir Processnesne döndürür , bu yüzden "ls".execute().textçalışır. Herhangi bir hata olup olmadığını belirlemek için hata akışını okuyabilmeniz gerekir.

Üzerinde ekstra bir yöntem yoktur ProcessBir geçmesine izin StringBuffermetni almak için: consumeProcessErrorStream(StringBuffer error).

Misal:

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

println proc.text
println b.toString()

Bourn Again Shell script ile çalışmıyor! # / Bin / bash,
Rashmi Jain

1
Bash komut dosyalarıyla çalışıyorsanız, muhtemelen bash komutunun bir parçası olarak çağrılırsınız: "/ bin / bash script" .execute ()
Niels Bech Nielsen

32
// 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()
}

10
+1 Bu, çıktı üretilirken çıktıyı aşamalı olarak gösterir .. uzun süren bir işlem için son derece önemlidir
samarjit samanta

mholm815
Jimmy Obonyo Abor

2
Bu çözümü kullanmak için aşağıdaki satırı uygulayın:runCommand("echo HELLO WORLD")
Miron V

@ mholm815 Boru hattının kendisinden gerekli komut dosyalarını nasıl onaylayabiliriz?
Ronak Patel

25

Bunu daha deyimsel buluyorum:

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"

Başka bir yazıda bahsedildiği gibi, bunlar engelleme çağrılarıdır, ancak çıktıyla çalışmak istediğimizden, bu gerekli olabilir.


24

Yukarıda verilen cevaplara bir önemli bilgi daha eklemek için -

Bir süreç için

def proc = command.execute();

her zaman kullanmaya çalış

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

ziyade

def output = proc.in.text;

ikincisi bir engelleme çağrısı olduğu için komutları harika bir şekilde yürüttükten sonra çıkışları yakalamak için ( SO nedeni ).


6
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]

3
Bir kişinin bir cevap vermek için zaman ayırdığı ve birisinin görünürde bir nedenden ötürü onu reddettiği için gerçekten rahatsızım. eğer bu bir topluluksa, aşağı oyu açıklayan bir yorum eklemek zorunda hissetmek gerekir (herhangi bir yetkili programcının hemen göreceği çok açık bir neden olmadığı sürece).
Amos Bordowitz

6
@AmosBordowitz Birçok yanıt aşağı oy alıyor. Sorun deđil, bir dehşet. Bununla birlikte, açıklama kelimesi olmayan bir kod olduğu için olabilir - her zaman iyi karşılanmaz.
Chris Baker

@ChrisBaker neden göstermiyorsun? Siz kendiniz bunun nedeni pozitif değilsiniz.
Amos Bordowitz 05.07.2017

5
@AmosBordowitz Resmi downvote açıklayıcısı değilim, neden olmadığını söyleyemem ve başka bir bireyin yaptığı bir eylemden bahsettiğimizden emin olmadığım anlaşılır değil. Bir ihtimal önerdim. Neden aşağı oyu açıklamıyorsunuz, neden cevaptaki kodu açıklamıyorsunuz? Her halükarda, eminim hepimiz iyi olacağız.
Chris Baker

1
@ChrisBakerI asla böyle bir iddiada bulunmadı ("ama sanırım daha iyisini biliyorsun"). Bu bir ahlak meselesi, bir bilgi meselesi değil ..
Amos Bordowitz

-3
command = "ls *"

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

ancak komut başarısız olursa, işlem sonlandırılacaktır


Nereden shgeliyor?
styl3r

3
shJenkins harika DSL'in bir parçasıdır. Muhtemelen burada yararlı değil
Gi0rgi0s

4
Jenkins Groovy DSL! = Groovy
Skeeve

diğerleri belirttiği gibi, bu Jenkins DSL bir parçasıdır
jonypony3

Bu cevap, sorulan soru için geçerli değildir.
Brandon
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.