2019-02-02 16:18:25 +08:00
|
|
|
// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
2018-05-08 18:41:29 +08:00
|
|
|
//
|
|
|
|
// 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,
|
2019-02-02 16:18:25 +08:00
|
|
|
// You can obtain one at https://github.com/gogf/gf.
|
2018-05-08 18:41:29 +08:00
|
|
|
|
2018-05-09 18:29:46 +08:00
|
|
|
package gproc
|
2018-05-08 18:41:29 +08:00
|
|
|
|
|
|
|
import (
|
2019-06-19 09:06:52 +08:00
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
|
|
|
"strings"
|
2018-05-08 18:41:29 +08:00
|
|
|
)
|
|
|
|
|
2018-05-09 18:29:46 +08:00
|
|
|
// 子进程
|
|
|
|
type Process struct {
|
2019-06-19 09:06:52 +08:00
|
|
|
exec.Cmd
|
|
|
|
Manager *Manager // 所属进程管理器
|
|
|
|
PPid int // 自定义关联的父进程ID
|
2018-06-29 13:03:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 创建一个进程(不执行)
|
2019-06-19 09:06:52 +08:00
|
|
|
func NewProcess(path string, args []string, environment ...[]string) *Process {
|
|
|
|
var env []string
|
|
|
|
if len(environment) > 0 {
|
2019-12-11 21:22:41 +08:00
|
|
|
env = make([]string, len(environment[0]))
|
|
|
|
copy(env, environment[0])
|
2019-06-19 09:06:52 +08:00
|
|
|
} else {
|
|
|
|
env = os.Environ()
|
|
|
|
}
|
2019-12-11 21:22:41 +08:00
|
|
|
process := &Process{
|
2019-06-19 09:06:52 +08:00
|
|
|
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),
|
|
|
|
},
|
|
|
|
}
|
2019-12-11 21:22:41 +08:00
|
|
|
process.Dir, _ = os.Getwd()
|
2019-06-19 09:06:52 +08:00
|
|
|
if len(args) > 0 {
|
2019-12-11 21:22:41 +08:00
|
|
|
// Exclude of current binary path.
|
2019-06-19 09:06:52 +08:00
|
|
|
start := 0
|
|
|
|
if strings.EqualFold(path, args[0]) {
|
|
|
|
start = 1
|
|
|
|
}
|
2019-12-11 21:22:41 +08:00
|
|
|
process.Args = append(process.Args, args[start:]...)
|
2019-06-19 09:06:52 +08:00
|
|
|
}
|
2019-12-11 21:22:41 +08:00
|
|
|
return process
|
2018-05-09 18:29:46 +08:00
|
|
|
}
|
|
|
|
|
2019-12-09 21:53:44 +08:00
|
|
|
// NewProcessCmd creates and returns a process with given command and optional environment variable array.
|
|
|
|
func NewProcessCmd(cmd string, environment ...[]string) *Process {
|
|
|
|
return NewProcess(getShell(), []string{getShellOption(), cmd}, environment...)
|
|
|
|
}
|
|
|
|
|
2018-05-13 00:17:12 +08:00
|
|
|
// 开始执行(非阻塞)
|
|
|
|
func (p *Process) Start() (int, error) {
|
2019-06-19 09:06:52 +08:00
|
|
|
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
|
|
|
|
}
|
2018-05-08 18:41:29 +08:00
|
|
|
}
|
|
|
|
|
2018-05-13 00:17:12 +08:00
|
|
|
// 运行进程(阻塞等待执行完毕)
|
|
|
|
func (p *Process) Run() error {
|
2019-06-19 09:06:52 +08:00
|
|
|
if _, err := p.Start(); err == nil {
|
|
|
|
return p.Wait()
|
|
|
|
} else {
|
|
|
|
return err
|
|
|
|
}
|
2018-05-08 18:41:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// PID
|
|
|
|
func (p *Process) Pid() int {
|
2019-06-19 09:06:52 +08:00
|
|
|
if p.Process != nil {
|
|
|
|
return p.Process.Pid
|
|
|
|
}
|
|
|
|
return 0
|
2018-05-08 18:41:29 +08:00
|
|
|
}
|
|
|
|
|
2018-05-10 16:07:14 +08:00
|
|
|
// 向进程发送消息
|
2018-05-18 15:45:08 +08:00
|
|
|
func (p *Process) Send(data []byte) error {
|
2019-06-19 09:06:52 +08:00
|
|
|
if p.Process != nil {
|
|
|
|
return Send(p.Process.Pid, data)
|
|
|
|
}
|
|
|
|
return errors.New("invalid process")
|
2018-05-10 16:07:14 +08:00
|
|
|
}
|
|
|
|
|
2018-05-08 18:41:29 +08:00
|
|
|
// 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 {
|
2019-06-19 09:06:52 +08:00
|
|
|
return p.Process.Release()
|
2018-05-08 18:41:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Kill causes the Process to exit immediately.
|
|
|
|
func (p *Process) Kill() error {
|
2019-06-19 09:06:52 +08:00
|
|
|
if err := p.Process.Kill(); err == nil {
|
|
|
|
if p.Manager != nil {
|
|
|
|
p.Manager.processes.Remove(p.Pid())
|
|
|
|
}
|
2019-12-09 21:53:44 +08:00
|
|
|
p.Process.Release()
|
|
|
|
p.Process.Wait()
|
2019-06-19 09:06:52 +08:00
|
|
|
return nil
|
|
|
|
} else {
|
|
|
|
return err
|
|
|
|
}
|
2018-05-08 18:41:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Signal sends a signal to the Process.
|
|
|
|
// Sending Interrupt on Windows is not implemented.
|
|
|
|
func (p *Process) Signal(sig os.Signal) error {
|
2019-06-19 09:06:52 +08:00
|
|
|
return p.Process.Signal(sig)
|
2018-06-01 00:11:45 +08:00
|
|
|
}
|