当os/exec 遇到 管道通讯时的问题

75 views
Skip to first unread message

莫比斯拉皮

unread,
Feb 14, 2014, 4:19:59 AM2/14/14
to golang...@googlegroups.com
两个简单的测试程序:
1. 守护进程 manage.go
package main

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

func main() {
    cmd := exec.Command("./stdin")
    stdout, err := cmd.StdoutPipe()
    if err != nil {
        fmt.Println("mange", err)
        return
    }
    go func() {
        w, err := cmd.StdinPipe()
        if err != nil {
            fmt.Println(err)
            return
        }
        for {
            //cmd.Stdout.Write([]byte("aaaaaa\n"))
            c, err := w.Write([]byte("aaaaa"))
            fmt.Println(c, err)
            <-time.After(time.Second)
        }
    }()
    go io.Copy(os.Stdout, stdout)

    cmd.Run()
    cmd.Wait()
    fmt.Println("over")

}


2. 测试程序 stdin.go

package main

import (
    "fmt"
    "os"
    "time"
)

func main() {
    var b = make([]byte, 128)
RELOAD:
    c, err := os.Stdin.Read(b)
    if err != nil {
        <-time.After(time.Second)
        goto RELOAD
    }
    fmt.Println("stdin Print:", string(b[:c]), b, err)

}




运行时这样:
go build stdin.go
go run manage.go



问题时这样:

编译后得到的stdin 程序, 如果我直接运行(./stdin 或者  echo "xxxxx" | ./stdin ) 是可以很好的保证管道通讯。但, 当我用manage.go ,通过exec.Command 函数,将stdin 作为子进程启动时,管道会被断开。

我需要manage 能使根据需要向stdin 传递特殊指令。 先不考虑 socket 通讯和http通讯。

莫比斯拉皮

unread,
Feb 14, 2014, 5:04:55 AM2/14/14
to golang...@googlegroups.com
已经解决了,

问题原自    cmd.StdinPipe() 的用法,看源码中, StdinPipe 在第一次被调用时, 会检查cmd.Stdin 参数是否复制,如果有将会抛出错误, 后续不会有参数传递进去。
另外一个原因是cmd.StdinPipe必须在cmd.Start 或者cmd.Run 之前并且 在同一个线程内执行一次.然后它反馈的变量就可以灵活使用了

修改后的manage.go 代码:


package main

import (
    "fmt"
    "io"
    "os"
    "os/exec"
    //"time"

)

func main() {
    cmd := exec.Command("./stdin")
    stdout, err := cmd.StdoutPipe()
    if err != nil {
        fmt.Println("mange", err)
        return
    }
    stdin, err := cmd.StdinPipe()

    if err != nil {
        fmt.Println(err)
        return
    }

    //os.NewFile(fd, name)
    cmd.Start()

    go io.Copy(os.Stdout, stdout)

    stdin.Write([]byte("bbbbbb\n"))
    stdin.Write([]byte("bbbbbb\n"))

    stdin.Write([]byte("bbbbbb\n"))

    stdin.Write([]byte("bbbbbb\n"))

    cmd.Wait()
    fmt.Println("over")
 
}




在 2014年2月14日星期五UTC+8下午5时19分59秒,莫比斯拉皮写道:
Reply all
Reply to author
Forward
0 new messages