请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

2-4demo中,win10下子协程还是输出了,没有强制结束任务

package main

//@todo exit status 1 hello,2s,在win下,子协程里sleep10秒还是,还是能输出hello
import (
	"context"
	"fmt"
	"os/exec"
	"runtime"
	"time"
)

//将子进程的输出输出给结构体,供父进程查看
type result struct {
	err    error
	output []byte
}

/*要完成的任务:
一个任务运行太久,怎样kill掉
1. 在一个协程里执行一个command,sleep4;echo hello
2. 在main方法里,1秒的时候,kill 上面的command

*/
func main() {
	var (
		ctx        context.Context
		cancelFunc context.CancelFunc
		cmd        *exec.Cmd
		//定义channel 供两个协程传递
		resultChan chan *result
		res        *result
	)
	resultChan = make(chan *result, 1000)

	/*上下文,左边开头的上下文,继承了右边括号里的上下文,
	context里有一个channel byte,channel会放在context对象中,cancelFunc会把这个channel关掉,而子进程的返回值是一个cmd指针,而通过cmdContext构造的对象,实际内部也维护了context对象,且通过select语法监听ctx的Done(),也就是监听这个channel是否被关闭,也就说主进程一旦调用了cancelFunc,这个channel就会被关闭,会被CommandContext返回的cmd监听到(通过select),然后就执行kill 子进程pid杀掉
	*/
	ctx, cancelFunc = context.WithCancel(context.TODO())
	go func() {
		var (
			output []byte
			err    error
		)
		//select {case <-ctx.Done()}
		cmd = exec.CommandContext(ctx, "C:\\Program Files\\Git\\bin\\sh.exe", "-c", "sleep 10;echo hello,2s")
		//执行捕获输出,将结果通过channel传递给main协程
		output, err = cmd.CombinedOutput()
		resultChan <- &result{
			err:    err,
			output: output,
		}
	}()

	//一秒后取消上下文,子协程没有时间输出 hello,2s,会被直接kill
	time.Sleep(1 * time.Second)
	cancelFunc()
	//在main协程里,等待子协程的退出,并打印任务执行结果

	res = <-resultChan


	fmt.Println(res.err, string(res.output))

	fmt.Println(runtime.NumCPU())
}

输出

GOROOT=C:\Go #gosetup
GOPATH=C:\Users\volvo\go #gosetup
C:\Go\bin\go.exe build -o C:\Users\volvo\AppData\Local\Temp\___go_build_GoCrontab_forceCloseCommand.exe GoCrontab/forceCloseCommand #gosetup
C:\Users\volvo\AppData\Local\Temp\___go_build_GoCrontab_forceCloseCommand.exe #gosetup
exit status 1 hello,2s

4

Process finished with exit code 0

请问这是为啥?

正在回答 回答被采纳积分+3

2回答

kakifuu 2020-10-18 22:18:22

可以看看这个 https://yuerblog.cc/2018/07/23/golang-command-context-not-exit-problem/

0 回复 有任何疑惑可以回复我~
我真的是太难了哦 2020-04-05 21:12:26

你这里 日志

exit status 1 hello,2s

不就是退出了?

0 回复 有任何疑惑可以回复我~
  • 提问者 牙小木 #1
    起的新协程里调用了一个bash命令:cmd = exec.CommandContext(ctx, "C:\\Program Files\\Git\\bin\\sh.exe", "-c", "sleep 10;echo hello,2s"),这个命令会sleep 10s,才输出helo,2s
    但是我在下面已经取消了这个context,
    time.Sleep(1 * time.Second)
    所以我理解不应该出现hello,2s,是直接把执行\Git\\bin\\sh.exe", "-c", "sleep 10;echo hello,2s的kill掉
    回复 有任何疑惑可以回复我~ 2020-04-06 16:40:13
  • 我真的是太难了哦 回复 提问者 牙小木 #2
    没问题,我本地执行的结果
    `signal: killed 
    12
    `
    没有输出hello
    回复 有任何疑惑可以回复我~ 2020-04-11 22:52:10
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信