(注意)不是Go Inter-Process Communication的欺骗,它询问 System V IPC。(尾注)
使用os/exec,如何与另一个进程进行交互通信?我想获取进程的 stdin 和 stdout 的 fd,并使用这些 fd 写入和读取进程。
我发现的大多数示例都涉及运行另一个进程,然后获取结果输出。
这是我正在寻找的 python 等效项。
p = subprocess.Popen("cmd", stdin=subprocess.PIPE, stdout=subprocess.PIPE)
(child_stdin, child_stdout) = (p.stdin, p.stdout)
Run Code Online (Sandbox Code Playgroud)
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", n, line)
}
Run Code Online (Sandbox Code Playgroud)
I see by strace that dc is receiving and answering as expected:
[pid 8089] write(4, "12 23 +p\n", 9 <unfinished ...>
...
[pid 8095] <... read resumed> "12 23 +p\n", 4096) = 9
...
[pid 8095] write(1, "35\n", 3 <unfinished ...>
Run Code Online (Sandbox Code Playgroud)
but I don't seem to be getting the results back into my calling program:
0 ::
Run Code Online (Sandbox Code Playgroud)
(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.
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
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
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\n"))
out := make([]byte, 1024)
n, _ := stdout.Read(out)
fmt.Println("OUTPUT:", string(out[:n]))
// prints "OUTPUT: 46"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3735 次 |
| 最近记录: |