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