github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/command/local_command.go (about) 1 package command 2 3 import ( 4 "io" 5 "os" 6 "os/exec" 7 "strings" 8 "sync" 9 10 "github.com/mongodb/grip" 11 "github.com/pkg/errors" 12 ) 13 14 type LocalCommand struct { 15 CmdString string 16 WorkingDirectory string 17 Shell string 18 Environment []string 19 ScriptMode bool 20 Stdout io.Writer 21 Stderr io.Writer 22 Cmd *exec.Cmd 23 mutex sync.RWMutex 24 } 25 26 func (lc *LocalCommand) Run() error { 27 err := lc.Start() 28 if err != nil { 29 return err 30 } 31 32 lc.mutex.RLock() 33 defer lc.mutex.RUnlock() 34 35 return lc.Cmd.Wait() 36 } 37 38 func (lc *LocalCommand) GetPid() int { 39 lc.mutex.RLock() 40 defer lc.mutex.RUnlock() 41 42 if lc.Cmd == nil { 43 return -1 44 } 45 46 return lc.Cmd.Process.Pid 47 } 48 49 func (lc *LocalCommand) Start() error { 50 lc.mutex.Lock() 51 defer lc.mutex.Unlock() 52 53 if lc.Shell == "" { 54 lc.Shell = "sh" 55 } 56 57 var cmd *exec.Cmd 58 if lc.ScriptMode { 59 cmd = exec.Command(lc.Shell) 60 cmd.Stdin = strings.NewReader(lc.CmdString) 61 } else { 62 cmd = exec.Command(lc.Shell, "-c", lc.CmdString) 63 } 64 65 // create the command, set the options 66 if lc.WorkingDirectory != "" { 67 cmd.Dir = lc.WorkingDirectory 68 } 69 cmd.Env = lc.Environment 70 if cmd.Env == nil { 71 cmd.Env = os.Environ() 72 } 73 cmd.Stdout = lc.Stdout 74 cmd.Stderr = lc.Stderr 75 76 // cache the command running 77 lc.Cmd = cmd 78 79 // start the command 80 return cmd.Start() 81 } 82 83 func (lc *LocalCommand) Stop() error { 84 lc.mutex.Lock() 85 defer lc.mutex.Unlock() 86 87 if lc.Cmd != nil && lc.Cmd.Process != nil { 88 return lc.Cmd.Process.Kill() 89 } 90 grip.Warning("Trying to stop command but Cmd / Process was nil") 91 return nil 92 } 93 94 func (lc *LocalCommand) PrepToRun(expansions *Expansions) error { 95 lc.mutex.Lock() 96 defer lc.mutex.Unlock() 97 98 var err error 99 100 lc.CmdString, err = expansions.ExpandString(lc.CmdString) 101 if err != nil { 102 return errors.WithStack(err) 103 } 104 105 lc.WorkingDirectory, err = expansions.ExpandString(lc.WorkingDirectory) 106 return errors.WithStack(err) 107 } 108 109 type LocalCommandGroup struct { 110 Commands []*LocalCommand 111 Expansions *Expansions 112 } 113 114 func (lc *LocalCommandGroup) PrepToRun() error { 115 for _, cmd := range lc.Commands { 116 if err := cmd.PrepToRun(lc.Expansions); err != nil { 117 return err 118 } 119 } 120 return nil 121 }