2015-05-13 15 views
6

Bir ruby ​​komut dosyasını çağırması gereken bir programım var.golang exec.Command std girişini oku

func runCommand(cmdName string, arg ...string) { 
    cmd := exec.Command(cmdName, arg...) 
    cmd.Stdout = os.Stdout 
    cmd.Stderr = os.Stderr 
    cmd.Stdin = os.Stdin 
    err = cmd.Run() 
    if err != nil { 
     fmt.Printf("Failed to start Ruby. %s\n", err.Error()) 
     os.Exit(1) 
    } 
} 

Ben bunu böyle çağırmak:

Bir runCommand işlevi var

Bir gets veya çocuk sürecinde benzer herhangi bir işlem yapılmazsa dışında çoğu durum için çalışır
runCommand("ruby", "-e", "require 'foo'") 

bir giriş için duraklatması gerekiyor.

cmd.Stdin = os.Stdin'u ayarlamayı denedim, ancak girişi beklemiyor.

Neyi yanlış yapıyorum?

+0

Ruby'de 'gets' olduğunda, konsolunuzdan giriş girebilir misiniz? Ruby bunun için bekler mi? Girişinizi girdikten sonra Enter'a basar mısınız? – icza

+0

'gets' bir akışın ortasındadır ve ruby ​​komut dosyasını çalıştırırsam bir girdi bekler. Evet, girdiden sonra enter tuşuna bastım. Benim gerçek usecase ruby ​​tarafında 'pry' çağırmaktır, ve benim beklentim' cmd.Run() '' pry' REPL tamamlamak için beklerdi. –

+0

Kodunuzdan [bu basit Go uygulamasını] (http://play.golang.org/p/0eWjtN2RWG) çalıştırırsam, mükemmel çalışır, girişi bekler ve çıktıyı düzgün şekilde yazdırır. Ruby kodunda bir şey olduğunu söyleyebilirim. – icza

cevap

4

aşağıdaki program istemek ne görünüyor (benim runCommand seninkinden hemen hemen aynıdır sadece err hattı için := için = değişti..) Farklı bir şey mi yapıyorsun?

package main 

import (
    "fmt" 
    "os" 
    "os/exec" 
) 

func main() { 
    runCommand("ruby", "-e", `puts "Running"; $in = gets; puts "You said #{$in}"`) 
} 

func runCommand(cmdName string, arg ...string) { 
    cmd := exec.Command(cmdName, arg...) 
    cmd.Stdout = os.Stdout 
    cmd.Stderr = os.Stderr 
    cmd.Stdin = os.Stdin 
    err := cmd.Run() 
    if err != nil { 
     fmt.Printf("Failed to start Ruby. %s\n", err.Error()) 
     os.Exit(1) 
    } 
} 
+0

Teşekkürler - Sonunda bunun geçerli bir kod olduğunu ve sorunun başka bir yerde olduğunu öğrendim (birden fazla yönlendirme düzeyine sahiptim ve bir tanesini kaçırdım). –

2

pseudoterminal kullanmanız gerekebilir. Bu kütüphane ile seferde yapabilirsiniz: github.com/kr/pty:

package main 

import (
    "bufio" 
    "io" 
    "log" 
    "os" 
    "os/exec" 

    "github.com/kr/pty" 
) 

func runCommand(cmdName string, arg ...string) { 
    cmd := exec.Command(cmdName, arg...) 
    tty, err := pty.Start(cmd) 
    if err != nil { 
     log.Fatalln(err) 
    } 
    defer tty.Close() 

    go func() { 
     scanner := bufio.NewScanner(tty) 
     for scanner.Scan() { 
      log.Println("[" + cmdName + "] " + scanner.Text()) 
     } 
    }() 
    go func() { 
     io.Copy(tty, os.Stdin) 
    }() 

    err = cmd.Wait() 
    if err != nil { 
     log.Fatalln(err) 
    } 
} 

func main() { 
    log.SetFlags(0) 
    runCommand("ruby", "-e", ` 
puts "Enter some text" 
text = gets 
puts text 
    `) 
} 
+0

Bu kütüphaneyi bilmiyordum, +1 beni golang'da bir psödoterminalle tanıştırıyor. Yukarıdaki yorumda belirttiğim gibi sorun başka bir yerdi. Teşekkürler. –