github.com/annwntech/go-micro/v2@v2.9.5/runtime/local/process/os/os.go (about)

     1  // +build !windows
     2  
     3  // Package os runs processes locally
     4  package os
     5  
     6  import (
     7  	"fmt"
     8  	"os"
     9  	"os/exec"
    10  	"strconv"
    11  	"syscall"
    12  
    13  	"github.com/annwntech/go-micro/v2/runtime/local/process"
    14  )
    15  
    16  func (p *Process) Exec(exe *process.Executable) error {
    17  	cmd := exec.Command(exe.Package.Path)
    18  	cmd.Dir = exe.Dir
    19  	return cmd.Run()
    20  }
    21  
    22  func (p *Process) Fork(exe *process.Executable) (*process.PID, error) {
    23  
    24  	// create command
    25  	cmd := exec.Command(exe.Package.Path, exe.Args...)
    26  
    27  	cmd.Dir = exe.Dir
    28  	// set env vars
    29  	cmd.Env = append(cmd.Env, os.Environ()...)
    30  	cmd.Env = append(cmd.Env, exe.Env...)
    31  
    32  	// create process group
    33  	cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
    34  
    35  	in, err := cmd.StdinPipe()
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	out, err := cmd.StdoutPipe()
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	er, err := cmd.StderrPipe()
    44  	if err != nil {
    45  		return nil, err
    46  	}
    47  	// start the process
    48  	if err := cmd.Start(); err != nil {
    49  		return nil, err
    50  	}
    51  
    52  	return &process.PID{
    53  		ID:     fmt.Sprintf("%d", cmd.Process.Pid),
    54  		Input:  in,
    55  		Output: out,
    56  		Error:  er,
    57  	}, nil
    58  }
    59  
    60  func (p *Process) Kill(pid *process.PID) error {
    61  	id, err := strconv.Atoi(pid.ID)
    62  	if err != nil {
    63  		return err
    64  	}
    65  	if _, err := os.FindProcess(id); err != nil {
    66  		return err
    67  	}
    68  
    69  	// now kill it
    70  	// using -ve PID kills the process group which we created in Fork()
    71  	return syscall.Kill(-id, syscall.SIGTERM)
    72  }
    73  
    74  func (p *Process) Wait(pid *process.PID) error {
    75  	id, err := strconv.Atoi(pid.ID)
    76  	if err != nil {
    77  		return err
    78  	}
    79  
    80  	pr, err := os.FindProcess(id)
    81  	if err != nil {
    82  		return err
    83  	}
    84  
    85  	ps, err := pr.Wait()
    86  	if err != nil {
    87  		return err
    88  	}
    89  
    90  	if ps.Success() {
    91  		return nil
    92  	}
    93  
    94  	return fmt.Errorf(ps.String())
    95  }