golang exec.Command read std input

匿名 (未验证) 提交于 2019-12-03 01:38:01

问题:

I have a go program that should invoke a ruby script.

I have a runCommand function:

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)     } } 

I invoke it like this:

runCommand("ruby", "-e", "require 'foo'") 

It works for most cases, except if there is a gets or any similar operation in the child process that needs to pause for an input.

I have tried setting cmd.Stdin = os.Stdin, but it does not wait for input.

What am I doing wrong?

回答1:

The following program seems do what you ask for (my runCommand is almost identical to yours. I just changed the = to := for the err line.) Are you doing something differently?

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)     } } 


回答2:

You might need to use a pseudoterminal. You can do this in go with this library: 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   `) } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!