First create a command to use for testing. This command will include flags to tell it to fail, what failure message to print, and what the exit code should be. ###### job-process.go ```go package main import ( "flag" "fmt" "os" ) func main() { echo := "job started" successMsg := "job succeeded" failMsg := "job failed" exitCode := 1 fail := false flag.StringVar(&echo, "echo", echo, "initial message") flag.StringVar(&successMsg, "success-msg", successMsg, "success message") flag.StringVar(&failMsg, "fail-msg", failMsg, "failure message") flag.IntVar(&exitCode, "exitcode", exitCode, "failure exit code (default=1)") flag.BoolVar(&fail, "fail", fail, "make process fail") flag.Parse() if echo != "" { fmt.Println(echo) } if fail { fmt.Println(failMsg) os.Exit(exitCode) } fmt.Println(successMsg) } ``` Build the command ``` go build job-process.go ``` Test it ``` $ ./job-process -h Usage of ./job-process: -echo string initial message (default "job started") -exitcode int failure exit code (default=1) (default 1) -fail make process fail -fail-msg string failure message (default "job failed") -success-msg string success message (default "job succeeded") $ ./job-process job started job succeeded $ ./job-process --echo "hello world" hello world job succeeded $ ./job-process --fail job started job failed $ echo $? 1 $ ./job-process --fail --fail-msg="ruh roh" --exitcode=2 job started ruh roh $ echo $? 2 ``` Now build a command to spawn `job-process`. ```go package main import ( "fmt" "os/exec" ) func run(msg string, succeed bool) { // This demo requires `./job-process` to exist in the cwd. // If not, go build it: `go build job-process.go` job := "./job-process" var cmd *exec.Cmd if succeed { cmd = exec.Command(job) } else { cmd = exec.Command(job, "--fail", "--fail-msg='RUHROH: catastrophic mission failure'", "--exitcode=2") } fmt.Printf("*** Spawning job: %s (should succeed: %t)\n", msg, succeed) out, err := cmd.CombinedOutput() // Whether successful or not, print all the output fmt.Printf("%s\n", out) // If not successful, also print the error code if err != nil { fmt.Println(err) } } func main() { run("good job", true) run("bad job", false) } ``` As the output demonstrates, the command successfully spawns the job twice (once to succeed, once to fail) and has access to the job's stdout, stderr, and exit code. ``` *** Spawning job: good job (should succeed: true) job started job succeeded *** Spawning job: bad job (should succeed: false) job started 'RUHROH: catastrophic mission failure' exit status 2 ``` --- Next: [[12. Where to Go Next]]