我正在尝试从Golang生成一个子进程。目标是逐行读取和处理输入。这是我正在努力工作的内容:
func readStuff(scanner *bufio.Scanner) {
for scanner.Scan() {
fmt.Println("Performed Scan")
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "reading standard input:", err)
}
}
func main() {
cmd := exec.Command("/usr/local/bin/pocketsphinx_continuous", "-inmic", "yes")
out, err := cmd.StdoutPipe()
err = cmd.Start()
checkError(err)
scanner := bufio.NewScanner(out)
fmt.Println("Scanner created")
defer cmd.Wait()
go readStuff(scanner)
}
在此示例中,打印了"已创建扫描仪",但之后没有任何反应。
但是运行此命令确实会导致我期望打印到:
/usr/local/bin/pocketsphinx_continuous -inmic yes 1>out.txt
修改代码以直接复制到stdout
也可以:
cmd := exec.Command("/usr/local/bin/pocketsphinx_continuous", "-inmic", "yes")
cmd.Stdout = os.Stdout
我错过了什么阻止我阅读输出?
您可能需要检查多项内容。
-
不检查
cmd.StdoutPipe()
返回的错误代码。应该是。 -
pocketsphinx_continuous
命令需要提供-hmm
和-dict
参数。否则,它将失败,并且所有输出实际上都发送到stderr
而不是stdout
。在这里,你只读stdout
,但没有什么可读的。 -
在确保已从
stdout
读取所有数据之前,不应调用cmd.Wait()
。结果是不确定的(实际上,这是一个竞争条件(。查看有关os/exec
包的文档。如果你绝对需要在 goroutines 中完成解析,你需要在调用 goroutinecmd.Wait()
之前与 goroutine 的末尾同步。例如,您可以将函数编写为:func readStuff(scanner *bufio.Scanner, stop chan bool) { // Scanning code // ... stop<-true }
主代码为:
stop := make(chan bool) go readStuff(scanner,stop) <-stop cmd.Wait()
似乎你不需要
go readStuff(scanner)
以
cmd.Start()
做系统分叉本身所以只是
readStuff(scanner)
就足够了(不是为此生成 goroute(
这似乎工作正常,它适用于go readStuff(scanner)
,也适用于readStuff(scanner)
- 我不认为这种用法实际上需要一个goroutine,但不知道实际的上下文。
package main
import (
"bufio"
"fmt"
"os"
"os/exec"
)
func readStuff(scanner *bufio.Scanner) {
for scanner.Scan() {
fmt.Println("Performed Scan")
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "reading standard input:", err)
}
}
func main() {
cmd := exec.Command("/Users/rfay/bin/junk.sh")
out, err := cmd.StdoutPipe()
err = cmd.Start()
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to start err=%v", err)
os.Exit(1)
}
scanner := bufio.NewScanner(out)
fmt.Println("Scanner created")
defer cmd.Wait()
go readStuff(scanner)
}
这是我用于测试 junk.sh。
#!/bin/bash
for i in `seq 1 10`;
do
echo $i
sleep 1
done