Golang解决linux下 cmd.Start 执行shell指令僵尸进程无法回收的解决方案。
封装好的 linux下shell指令执行函数, windows内powershell,cmd同理。
使用
commandExample := `node ./val.js`
pid, out, err := CmdExec(commandExample)
// TODO use pid,out,err
func CmdExec(args ...string) (int, string, error) {
ctx := context.Background()
args = append([]string{"-c"}, args...)
cmd := exec.CommandContext(ctx, os.Getenv("SHELL"), args...)
cmd.SysProcAttr = &syscall.SysProcAttr{}
outpip, err := cmd.StdoutPipe()
defer outpip.Close()
if err != nil {
return 0, "", err
}
err = cmd.Start()
if err != nil {
return 0, "", err
}
out, err := ioutil.ReadAll(outpip)
if err != nil {
return 0, "", err
}
// 监听进程wait,回收子进程
errCmdCh := make(chan error, 1)
go func() {
go func() {
errCmdCh <- cmd.Wait()
}()
for {
select {
case <-ctx.Done():
log.Println("ctx.done")
pid := cmd.Process.Pid
if err := syscall.Kill(-1*pid, syscall.SIGKILL); err != nil {
return
}
case err := <-errCmdCh:
log.Printf("errCmdCh error %+v \n", err)
return
default:
log.Println(cmd.Process.Pid)
time.Sleep(2 * time.Second)
}
}
}()
return cmd.Process.Pid, string(out), nil
}