github.com/pingcap/tiup@v1.15.1/components/playground/instance/process.go (about) 1 package instance 2 3 import ( 4 "context" 5 "io" 6 "os" 7 "os/exec" 8 "sync" 9 "time" 10 11 "github.com/pingcap/errors" 12 ) 13 14 // Process represent process to be run by playground 15 type Process interface { 16 Start() error 17 Wait() error 18 Pid() int 19 Uptime() string 20 SetOutputFile(fname string) error 21 Cmd() *exec.Cmd 22 } 23 24 // process implements Process 25 type process struct { 26 cmd *exec.Cmd 27 startTime time.Time 28 29 waitOnce sync.Once 30 waitErr error 31 } 32 33 // Start the process 34 func (p *process) Start() error { 35 // fmt.Printf("Starting `%s`: %s", filepath.Base(p.cmd.Path), strings.Join(p.cmd.Args, " ")) 36 p.startTime = time.Now() 37 return p.cmd.Start() 38 } 39 40 // Wait implements Instance interface. 41 func (p *process) Wait() error { 42 p.waitOnce.Do(func() { 43 p.waitErr = p.cmd.Wait() 44 }) 45 46 return p.waitErr 47 } 48 49 // Pid implements Instance interface. 50 func (p *process) Pid() int { 51 return p.cmd.Process.Pid 52 } 53 54 // Uptime implements Instance interface. 55 func (p *process) Uptime() string { 56 s := p.cmd.ProcessState 57 58 if s != nil { 59 return s.String() 60 } 61 62 duration := time.Since(p.startTime) 63 return duration.String() 64 } 65 66 func (p *process) SetOutputFile(fname string) error { 67 f, err := os.OpenFile(fname, os.O_RDWR|os.O_CREATE, 0666) 68 if err != nil { 69 return errors.AddStack(err) 70 } 71 p.setOutput(f) 72 return nil 73 } 74 75 func (p *process) setOutput(w io.Writer) { 76 p.cmd.Stdout = w 77 p.cmd.Stderr = w 78 } 79 80 func (p *process) Cmd() *exec.Cmd { 81 return p.cmd 82 } 83 84 // PrepareCommand return command for playground 85 func PrepareCommand(ctx context.Context, binPath string, args, envs []string, workDir string) *exec.Cmd { 86 c := exec.CommandContext(ctx, binPath, args...) 87 88 c.Env = os.Environ() 89 c.Env = append(c.Env, envs...) 90 c.Dir = workDir 91 c.SysProcAttr = SysProcAttr 92 return c 93 }