Run starts the command in the background. It may error out immediately if the command fails to start (ErrFailedStarting).
(parentCtx context.Context)
| 167 | // Run starts the command in the background. |
| 168 | // It may error out immediately if the command fails to start (ErrFailedStarting). |
| 169 | func (gc *Command) Run(parentCtx context.Context) error { |
| 170 | // Lock |
| 171 | gc.mutex.Lock() |
| 172 | defer gc.mutex.Unlock() |
| 173 | |
| 174 | // Protect against dumb calls |
| 175 | if gc.result != nil { |
| 176 | return ErrExecAlreadyFinished |
| 177 | } else if gc.exec != nil { |
| 178 | return ErrExecAlreadyStarted |
| 179 | } |
| 180 | |
| 181 | var ( |
| 182 | ctx context.Context |
| 183 | ctxCancel context.CancelFunc |
| 184 | pipes *stdPipes |
| 185 | cmd *exec.Cmd |
| 186 | err error |
| 187 | ) |
| 188 | |
| 189 | // Get a timing-out context |
| 190 | if gc.Timeout == 0 { |
| 191 | gc.Timeout = defaultTimeout |
| 192 | } |
| 193 | |
| 194 | ctx, ctxCancel = context.WithTimeout(parentCtx, gc.Timeout) |
| 195 | gc.startTime = time.Now() |
| 196 | |
| 197 | // Create a contextual command, set the logger |
| 198 | cmd = gc.buildCommand(ctx) |
| 199 | // Get a debug-logger from the context |
| 200 | var ( |
| 201 | log logger.Logger |
| 202 | ok bool |
| 203 | ) |
| 204 | |
| 205 | if log, ok = parentCtx.Value(LoggerKey).(logger.Logger); !ok { |
| 206 | log = nil |
| 207 | } |
| 208 | |
| 209 | conLog := logger.NewLogger(log).Set("command", cmd.String()) |
| 210 | // FIXME: this is manual silencing of pipe logs (very noisy) |
| 211 | // It should be possible to enable this with some debug flag. |
| 212 | // Note that one probably never want this on unless they are actually debugging pipes issues... |
| 213 | emLog := logger.NewLogger(nil).Set("command", cmd.String()) |
| 214 | |
| 215 | gc.exec = &execution{ |
| 216 | context: ctx, |
| 217 | cancel: ctxCancel, |
| 218 | command: cmd, |
| 219 | log: conLog, |
| 220 | } |
| 221 | |
| 222 | // Prepare pipes |
| 223 | pipes, err = newStdPipes(ctx, emLog, gc.ptyStdout, gc.ptyStderr, gc.ptyStdin, gc.writers) |
| 224 | if err != nil { |
| 225 | ctxCancel() |
| 226 |