Just wanted to give a quick +1 here, came in handy for a use-case just now!
On Sunday, July 3, 2016 at 4:00:25 PM UTC-4, soapboxcicero wrote: > > Sorry for bumping an oldish thread, but I just ran into this trying to > propagate an exit code. > > I didn't find anything searching that was sufficiently > platform-independent, but a little spelunking into the stdlib source > bore fruit, so I thought I'd share my solution. > > If you have an *exec.ExitError it embeds an *os.ProcessState. > > *os.ProcessState's Sys method returns an interface{} containing the a > platform specific type from the syscall package. > > But all the platform specific types have a method ExitStatus() int. > (Even nacl and Plan 9, which fake it). > > So, given an *exec.ExitError x, to get the exit code you just need to do: > > exitCode := x.Sys().(interface{ > ExitStatus() int > }).ExitStatus() > > I suppose it wouldn't hurt to check that type assertion and return -1 > if it fails, though I imagine if that ever happened it would be a bug > in a new port. > > > On Thu, Jun 2, 2016 at 4:14 AM, Konstantin Khomoutov > <flat...@users.sourceforge.net <javascript:>> wrote: > > On Wed, 1 Jun 2016 23:56:43 +0300 > > Janne Snabb <sn...@epipe.com <javascript:>> wrote: > > > >> You should check if the type of err is *exec.ExitError and in that > >> case consider it just as non-zero exit value from the process. > >> > >> The following snippet from > >> https://golang.org/src/os/exec/exec_test.go#L123 clarifies it: > >> > >> func TestExitStatus(t *testing.T) { > >> // Test that exit values are returned correctly > >> cmd := helperCommand(t, "exit", "42") > >> err := cmd.Run() > >> want := "exit status 42" > >> > >> if werr, ok := err.(*exec.ExitError); ok { > >> if s := werr.Error(); s != want { > >> t.Errorf("from exit 42 got exit %q, want %q", > >> s, want) } > >> } else { > >> t.Fatalf("expected *exec.ExitError from exit 42; got % > >> T: %v", err, err) } > >> } > > > > I'd warn the OP to take this snippet with a hefty grain of salt: while > > it's perfectly reasonable for the test suite of an stdlib package to > > test the output of os/exec.ExitError.Error(), 3rd-party code must not > > rely on the output of the Error() methods of error values of any type to > > be predictable and stable -- at least until there's absolutely no > > other way to get onto error's details. > > > > That is, the OP should consider writing a helper function to test the > > error returned by os/exec.Cmd.Run() et al to check whether the exit > > status is non-zero and discard the error value if so. > > > > An example: > > > > ----8<---- > > package main > > > > import ( > > "os/exec" > > "testing" > > ) > > > > func maybeIgnore(err error) error { > > if _, ok := err.(*exec.ExitError); ok { > > return nil > > } > > return err > > } > > > > func TestExitCode(t *testing.T) { > > cmd := exec.Command("/bin/sh", "-c", "exit 42") > > err := maybeIgnore(cmd.Run()) > > if err != nil { > > t.Error("Expected nil error, got: %#v", err) > > } > > cmd = exec.Command("./does not exist, really") > > err = maybeIgnore(cmd.Run()) > > if err == nil { > > t.Error("Expected non-nil error, got nil") > > } > > } > > ----8<---- > > > > (Save as "whatever_test.go" and run `go test`.) > > > > -- > > You received this message because you are subscribed to the Google > Groups "golang-nuts" group. > > To unsubscribe from this group and stop receiving emails from it, send > an email to golang-nuts...@googlegroups.com <javascript:>. > > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.