Golang exec.Command read std input

I have a go program that should call 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 call it like this:

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

It works in most cases, except when the child process has gets or any similar operation that must be paused for input.

I tried to set cmd.Stdin = os.Stdin , but it does not cmd.Stdin = os.Stdin for input.

What am I doing wrong?

+7
go
source share
2 answers

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

 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) } } 
+5
source share

You may need pseudoterminal . You can do this in 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 `) } 
+2
source share

All Articles