2 回答
TA贡献1893条经验 获得超10个赞
该程序会按照您的要求复制内容。您也可以尝试评论部分。这些评论是不言自明的,我希望它能解释您的疑问。
package main
import (
"io"
"log"
"os"
"os/exec"
)
func main() {
// Execute cat command w/ arguments
// cmd := exec.Command("cat", "hello.txt")
// Execute cat command w/o arguments
cmd := exec.Command("cat")
// Attach STDOUT stream
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Println(err)
}
// Attach STDIN stream
stdin, err := cmd.StdinPipe()
if err != nil {
log.Println(err)
}
// Attach STDERR stream
stderr, err := cmd.StderrPipe()
if err != nil {
log.Println(err)
}
// Spawn go-routine to copy os's stdin to command's stdin
go io.Copy(stdin, os.Stdin)
// Spawn go-routine to copy command's stdout to os's stdout
go io.Copy(os.Stdout, stdout)
// Spawn go-routine to copy command's stderr to os's stderr
go io.Copy(os.Stderr, stderr)
// Run() under the hood calls Start() and Wait()
cmd.Run()
// Note: The PIPES above will be closed automatically after Wait sees the command exit.
// A caller need only call Close to force the pipe to close sooner.
log.Println("Command complete")
}
TA贡献1845条经验 获得超8个赞
您正在用其他 Go 类型替换进程文件描述符(通常为 )*os.File
。为了让 stdin 像流一样工作,os/exec
包需要启动一个 goroutine 在io.Reader
进程之间复制数据。这在os/exec
包中记录:
// 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.
如果您查看程序的堆栈跟踪,您会发现它正在等待 io goroutine 在以下位置完成Wait():
goroutine 1 [chan receive]:
os/exec.(*Cmd).Wait(0xc000076000, 0x0, 0x0)
/usr/local/go/src/os/exec/exec.go:510 +0x125
main.main()
因为您现在可以控制数据流,所以您可以根据需要关闭它。如果这里不需要 Stdin,那么根本就不要分配它。如果要使用它,那么您必须Close()
将其Wait()
归还。
另一种选择是确保您使用的是*os.File
,最简单的方法是使用StdinPipe
,StdoutPipe
和StderrPipe
方法,后者又使用os.Pipe()
. 这种方式确保进程只处理*os.File
,而不处理其他 Go 类型。
- 2 回答
- 0 关注
- 132 浏览
添加回答
举报