我有这段代码
subProcess := exec.Cmd{
Path: execAble,
Args: []string{
fmt.Sprintf("-config=%s", *configPath),
fmt.Sprintf("-serverType=%s", *serverType),
fmt.Sprintf("-reload=%t", *reload),
fmt.Sprintf("-listenFD=%d", fd),
},
Dir: here,
}
subProcess.Stdout = os.Stdout
subProcess.Stderr = os.Stderr
logger.Info("starting subProcess:%s ", subProcess.Args)
if err := subProcess.Run(); err != nil {
logger.Fatal(err)
}
然后我做os.Exit(1)来停止主进程
我可以从子流程
获得输出但我也想把stdin放到
我试试
subProcess.Stdin = os.Stdin
但它不起作用
答案 0 :(得分:22)
我做了一个简单的程序(用于测试)。它读取一个数字并写出给定的数字。
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello, What's your favorite number?")
var i int
fmt.Scanf("%d\n", &i)
fmt.Println("Ah I like ", i, " too.")
}
这是修改后的代码
package main
import (
"fmt"
"io"
"os"
"os/exec"
)
func main() {
subProcess := exec.Command("go", "run", "./helper/main.go") //Just for testing, replace with your subProcess
stdin, err := subProcess.StdinPipe()
if err != nil {
fmt.Println(err) //replace with logger, or anything you want
}
defer stdin.Close() // the doc says subProcess.Wait will close it, but I'm not sure, so I kept this line
subProcess.Stdout = os.Stdout
subProcess.Stderr = os.Stderr
fmt.Println("START") //for debug
if err = subProcess.Start(); err != nil { //Use start, not run
fmt.Println("An error occured: ", err) //replace with logger, or anything you want
}
io.WriteString(stdin, "4\n")
subProcess.Wait()
fmt.Println("END") //for debug
}
您对这些行感兴趣
stdin, err := subProcess.StdinPipe()
if err != nil {
fmt.Println(err)
}
defer stdin.Close()
//...
io.WriteString(stdin, "4\n")
//...
subProcess.Wait()
上述行的说明
输出
START
你好,你最喜欢的号码是什么? 啊我也喜欢4 END
答案 1 :(得分:3)
虽然这个问题有点旧,但这是我的回答:
这个问题当然是特定于平台的,因为标准IO的处理方式取决于操作系统的实现,而不取决于Go语言。 然而,作为一般经验法则(由于某些操作系统占主导地位),"您提出的要求是不可能的" 。
在大多数现代操作系统中,您可以管道标准流(如@mraron的答案),您可以将它们分离(这是守护程序的工作方式),但您不能将它们重新分配或委托给另一个进程。 / p>
我认为这种限制更多是出于安全考虑。仍然不时发现允许远程执行代码的错误,想象一下如果操作系统允许重新分配/委托STDIN / OUT,那么这些漏洞的后果将是灾难性的。
答案 2 :(得分:1)
虽然你不能直接执行此操作,因为@AlexKey先前写过,你仍然可以做一些解决方法。如果操作系统阻止你管道你自己的标准流谁关心所有你需要2个通道和2个goroutine
var stdinChan chan []byte
var stdoutChan chan []byte
//when something happens in stdout of your code just pipe it to stdout chan
stdoutChan<-somehowGotDataFromStdOut
然后你需要两个功能,正如我之前提到的那样
func Pipein(){
for {
stdinFromProg.Write(<-stdInChan)
}
}
stdout的相同想法
答案 3 :(得分:1)
Go文档中现在提供了一个更新的示例:https://golang.org/pkg/os/exec/#Cmd.StdinPipe
如果子进程在关闭stdin之前没有继续,则io.WriteString()
调用需要包装在一个匿名函数中:
func main() {
cmd := exec.Command("cat")
stdin, err := cmd.StdinPipe()
if err != nil {
log.Fatal(err)
}
go func() {
defer stdin.Close()
io.WriteString(stdin, "values written to stdin are passed to cmd's standard input")
}()
out, err := cmd.CombinedOutput()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", out)
}