github.com/zhongdalu/gf@v1.0.0/g/os/gproc/gproc_proccess.go (about)

     1  // Copyright 2018 gf Author(https://github.com/zhongdalu/gf). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/zhongdalu/gf.
     6  
     7  package gproc
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  	"os"
    13  	"os/exec"
    14  	"strings"
    15  )
    16  
    17  // 子进程
    18  type Process struct {
    19  	exec.Cmd
    20  	Manager *Manager // 所属进程管理器
    21  	PPid    int      // 自定义关联的父进程ID
    22  }
    23  
    24  // 创建一个进程(不执行)
    25  func NewProcess(path string, args []string, environment ...[]string) *Process {
    26  	var env []string
    27  	if len(environment) > 0 {
    28  		env = make([]string, 0)
    29  		for _, v := range environment[0] {
    30  			env = append(env, v)
    31  		}
    32  	} else {
    33  		env = os.Environ()
    34  	}
    35  	env = append(env, fmt.Sprintf("%s=%s", gPROC_TEMP_DIR_ENV_KEY, os.TempDir()))
    36  	p := &Process{
    37  		Manager: nil,
    38  		PPid:    os.Getpid(),
    39  		Cmd: exec.Cmd{
    40  			Args:       []string{path},
    41  			Path:       path,
    42  			Stdin:      os.Stdin,
    43  			Stdout:     os.Stdout,
    44  			Stderr:     os.Stderr,
    45  			Env:        env,
    46  			ExtraFiles: make([]*os.File, 0),
    47  		},
    48  	}
    49  	// 当前工作目录
    50  	if d, err := os.Getwd(); err == nil {
    51  		p.Dir = d
    52  	}
    53  	if len(args) > 0 {
    54  		start := 0
    55  		if strings.EqualFold(path, args[0]) {
    56  			start = 1
    57  		}
    58  		p.Args = append(p.Args, args[start:]...)
    59  	}
    60  	return p
    61  }
    62  
    63  // 开始执行(非阻塞)
    64  func (p *Process) Start() (int, error) {
    65  	if p.Process != nil {
    66  		return p.Pid(), nil
    67  	}
    68  	p.Env = append(p.Env, fmt.Sprintf("%s=%d", gPROC_ENV_KEY_PPID_KEY, p.PPid))
    69  	if err := p.Cmd.Start(); err == nil {
    70  		if p.Manager != nil {
    71  			p.Manager.processes.Set(p.Process.Pid, p)
    72  		}
    73  		return p.Process.Pid, nil
    74  	} else {
    75  		return 0, err
    76  	}
    77  }
    78  
    79  // 运行进程(阻塞等待执行完毕)
    80  func (p *Process) Run() error {
    81  	if _, err := p.Start(); err == nil {
    82  		return p.Wait()
    83  	} else {
    84  		return err
    85  	}
    86  }
    87  
    88  // PID
    89  func (p *Process) Pid() int {
    90  	if p.Process != nil {
    91  		return p.Process.Pid
    92  	}
    93  	return 0
    94  }
    95  
    96  // 向进程发送消息
    97  func (p *Process) Send(data []byte) error {
    98  	if p.Process != nil {
    99  		return Send(p.Process.Pid, data)
   100  	}
   101  	return errors.New("invalid process")
   102  }
   103  
   104  // Release releases any resources associated with the Process p,
   105  // rendering it unusable in the future.
   106  // Release only needs to be called if Wait is not.
   107  func (p *Process) Release() error {
   108  	return p.Process.Release()
   109  }
   110  
   111  // Kill causes the Process to exit immediately.
   112  func (p *Process) Kill() error {
   113  	if err := p.Process.Kill(); err == nil {
   114  		if p.Manager != nil {
   115  			p.Manager.processes.Remove(p.Pid())
   116  		}
   117  		return nil
   118  	} else {
   119  		return err
   120  	}
   121  }
   122  
   123  // Signal sends a signal to the Process.
   124  // Sending Interrupt on Windows is not implemented.
   125  func (p *Process) Signal(sig os.Signal) error {
   126  	return p.Process.Signal(sig)
   127  }