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 }