当我执行go exec命令时,它卡住了,我不知道为什么?
Go代码:
func main() {
cmd := exec.Command("/bin/bash", "test.sh")
_, err := cmd.Output()
//err := cmd.Run()
if err != nil {
fmt.Println(err)
} else {
fmt.Println("out")
}
}
如代码所示,如果使用Run(),则没关系。
test.sh:
#!/bin/bash
./sleep.sh &
它调用另一个shell脚本,在后台运行sleep.sh
sleep.sh:
#!/bin/bash
while true
do
echo hello >> test.txt
sleep 30
done
它永远不会退出,总是在后台运行。
你可以看到它实际上不会向stdout输出任何东西,但是Output()会Stuck,Run()就可以了。 Go show Output()的源代码将调用Run()。所以为什么?
程序停滞时的一些GDB信息:
(gdb) info goroutines
1 waiting runtime.gopark
2 waiting runtime.gopark
3 waiting runtime.gopark
4 waiting runtime.gopark
* 5 syscall syscall.Syscall
(gdb) goroutine 5 bt
#0 syscall.Syscall () at /usr/local/go/src/syscall/asm_linux_amd64.s:19
#1 0x00000000004acf2f in syscall.read (fd=4, p= []uint8 = {...}, n=4254696, err=...) at /usr/local/go/src/syscall/zsyscall_linux_amd64.go:783
#2 0x00000000004ac73d in syscall.Read (fd=4, p= []uint8 = {...}, n=859530501352, err=...) at /usr/local/go/src/syscall/syscall_unix.go:160
#3 0x0000000000487703 in os.(*File).read (f=0xc82002c030, b= []uint8 = {...}, n=859530919936, err=...) at /usr/local/go/src/os/file_unix.go:211
#4 0x0000000000484f3a in os.(*File).Read (f=0xc82002c030, b= []uint8 = {...}, n=0, err=...) at /usr/local/go/src/os/file.go:95
#5 0x00000000004a5c6f in bytes.(*Buffer).ReadFrom (b=0xc8200140e0, r=..., n=0, err=...) at /usr/local/go/src/bytes/buffer.go:173
#6 0x0000000000482160 in io.copyBuffer (dst=..., src=..., buf= []uint8, written=0, err=...) at /usr/local/go/src/io/io.go:375
#7 0x0000000000481fa4 in io.Copy (dst=..., src=..., written=0, err=...) at /usr/local/go/src/io/io.go:351
#8 0x000000000047262b in os/exec.(*Cmd).writerDescriptor.func1 (~r0=...) at /usr/local/go/src/os/exec/exec.go:232
#9 0x00000000004726cd in os/exec.(*Cmd).Start.func1 (c=0xc820088000, fn={void (error *)} 0xc820029fb8) at /usr/local/go/src/os/exec/exec.go:340
#10 0x0000000000456241 in runtime.goexit () at /usr/local/go/src/runtime/asm_amd64.s:1721
#11 0x000000c820088000 in ?? ()
#12 0x000000c82000c140 in ?? ()
#13 0x0000000000000000 in ?? ()
答案 0 :(得分:1)
您所看到的是正常行为,但它有点不寻常。你的程序forks / bin / bash会发生什么,它会分叉test.sh,它会分配sleep.sh。现在你正在等待输出,这意味着你执行的命令的标准输出/ bin / bash,它已经分叉了test.sh,然后返回。
那么,当您调用cmd.Run时,为什么这会有不同的行为?因为你的程序分叉/ bin / bash,然后分叉test.sh,然后返回。你的程序没有等待读取程序的输出,它只是查找/ bin / bash的退出状态,它会立即返回。
以下是一些练习: