「已注销」 2016-09-30 20:13 采纳率: 0%
浏览 170
已采纳

去:与另一个进程的双向通信?

(note) not a dupe of Go Inter-Process Communication which is asking about System V IPC. (end note)

Using os/exec, how do I interactively communicate with another process? I'd like to get fd's for the process's stdin and stdout, and write to and read from the process using those fds.

Most examples I have found involve running another process and then slurping the resulting output.

Here's the python equivalent of what I'm looking for.

p = subprocess.Popen("cmd", stdin=subprocess.PIPE, stdout=subprocess.PIPE)
(child_stdin, child_stdout) = (p.stdin, p.stdout)

As a tangible example, consider opening a pipe to dc, sending the line 12 34 +p and receiving the line 46.

(update)

func main() {
  cmd := exec.Command("dc")
  stdin, err := cmd.StdinPipe()
  must(err)
  stdout, err := cmd.StdoutPipe()
  must(err)

  err = cmd.Start()
  must(err)

  fmt.Fprintln(stdin, "2 2 +p")

  line := []byte{}
  n, err := stdout.Read(line)

  fmt.Printf("%d :%s:
", n, line)
}

I see by strace that dc is receiving and answering as expected:

[pid  8089] write(4, "12 23 +p
", 9 <unfinished ...>
...
[pid  8095] <... read resumed> "12 23 +p
", 4096) = 9
...
[pid  8095] write(1, "35
", 3 <unfinished ...>

but I don't seem to be getting the results back into my calling program:

0 ::

(update)

As per the accepted answer, my problem was not allocating the string to receive the response. Changing to line := make([]byte, 100) fixed everything.

  • 写回答

1条回答 默认 最新

  • doupi6737 2016-09-30 20:18
    关注

    An exec.Cmd has fields for the process stdin, std, and stderr which you can assign.

        // Stdin specifies the process's standard input.
        // If Stdin is nil, the process reads from the null device (os.DevNull).
        // If Stdin is an *os.File, the process's standard input is connected
        // directly to that file.
        // Otherwise, during the execution of the command a separate
        // goroutine reads from Stdin and delivers that data to the command
        // over a pipe. In this case, Wait does not complete until the goroutine
        // stops copying, either because it has reached the end of Stdin
        // (EOF or a read error) or because writing to the pipe returned an error.
        Stdin io.Reader
    
        // Stdout and Stderr specify the process's standard output and error.
        //
        // If either is nil, Run connects the corresponding file descriptor
        // to the null device (os.DevNull).
        //
        // If Stdout and Stderr are the same writer, at most one
        // goroutine at a time will call Write.
        Stdout io.Writer
        Stderr io.Writer
    

    If you want a pre-made pipe to connected to any of those, you can use the *Pipe() methods

    func (c *Cmd) StderrPipe() (io.ReadCloser, error)
    func (c *Cmd) StdinPipe() (io.WriteCloser, error)
    func (c *Cmd) StdoutPipe() (io.ReadCloser, error)
    

    A basic example using the dc program (sans error checking):

    cmd := exec.Command("dc")
    stdin, _ := cmd.StdinPipe()
    stdout, _ := cmd.StdoutPipe()
    cmd.Start()
    
    stdin.Write([]byte("12 34 +p
    "))
    
    out := make([]byte, 1024)
    n, _ := stdout.Read(out)
    
    fmt.Println("OUTPUT:", string(out[:n]))
    
    // prints "OUTPUT: 46"
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥30 软件自定义无线电该怎样使用
  • ¥15 R语言mediation包做中介分析,直接效应和间接效应都很小,为什么?
  • ¥15 Jenkins+k8s部署slave节点offline
  • ¥15 微信小游戏反编译后,出现找不到分包的情况
  • ¥15 如何实现从tello无人机上获取实时传输的视频流,然后将获取的视频通过yolov5进行检测
  • ¥15 WPF使用Canvas绘制矢量图问题
  • ¥15 用三极管设计一个单管共射放大电路
  • ¥15 孟德尔随机化r语言运行问题
  • ¥15 pyinstaller编译的时候出现No module named 'imp'
  • ¥15 nirs_kit中打码怎么看(打码文件是csv格式)