// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved. // // This Source Code Form is subject to the terms of the MIT License. // If a copy of the MIT was not distributed with this file, // You can obtain one at https://gitee.com/johng/gf. package gproc import ( "os" "fmt" "os/exec" "errors" "strings" ) // 子进程 type Process struct { exec.Cmd Manager *Manager // 所属进程管理器 PPid int // 自定义关联的父进程ID } // 创建一个进程(不执行) func NewProcess(path string, args []string, environment...[]string) *Process { var env []string if len(environment) > 0 { env = make([]string, 0) for _, v := range environment[0] { env = append(env, v) } } else { env = os.Environ() } env= append(env, fmt.Sprintf("%s=%s", gPROC_TEMP_DIR_ENV_KEY, os.TempDir())) p := &Process { Manager : nil, PPid : os.Getpid(), Cmd : exec.Cmd { Args : []string{path}, Path : path, Stdin : os.Stdin, Stdout : os.Stdout, Stderr : os.Stderr, Env : env, ExtraFiles : make([]*os.File, 0), }, } // 当前工作目录 if d, err := os.Getwd(); err == nil { p.Dir = d } if len(args) > 0 { start := 0 if strings.EqualFold(path, args[0]) { start = 1 } p.Args = append(p.Args, args[start : ]...) } return p } // 开始执行(非阻塞) func (p *Process) Start() (int, error) { if p.Process != nil { return p.Pid(), nil } p.Env = append(p.Env, fmt.Sprintf("%s=%d", gPROC_ENV_KEY_PPID_KEY, p.PPid)) if err := p.Cmd.Start(); err == nil { if p.Manager != nil { p.Manager.processes.Set(p.Process.Pid, p) } return p.Process.Pid, nil } else { return 0, err } } // 运行进程(阻塞等待执行完毕) func (p *Process) Run() error { if _, err := p.Start(); err == nil { return p.Wait() } else { return err } } // PID func (p *Process) Pid() int { if p.Process != nil { return p.Process.Pid } return 0 } // 向进程发送消息 func (p *Process) Send(data []byte) error { if p.Process != nil { return Send(p.Process.Pid, data) } return errors.New("invalid process") } // Release releases any resources associated with the Process p, // rendering it unusable in the future. // Release only needs to be called if Wait is not. func (p *Process) Release() error { return p.Process.Release() } // Kill causes the Process to exit immediately. func (p *Process) Kill() error { if err := p.Process.Kill(); err == nil { if p.Manager != nil { p.Manager.processes.Remove(p.Pid()) } return nil } else { return err } } // Signal sends a signal to the Process. // Sending Interrupt on Windows is not implemented. func (p *Process) Signal(sig os.Signal) error { return p.Process.Signal(sig) }