package cmpSnipper import ( "os/exec" "context" "time" "strings" "syscall" ) func (app *App) PingSnip(parm any) (any, error) { // log.Println("PingSnip") path, err := exec.LookPath("ping") app.Log("Prog:", path) if err != nil { return map[string]interface{}{ "retval" : 127, "error" : "No prog", }, nil } ctx, cancel := context.WithTimeout(context.Background(), 10 * time.Second) defer cancel() cmd := exec.CommandContext(ctx, "ping", "-c", "4", "8.8.8.8") cmd.Stdin = strings.NewReader("") var stdout strings.Builder cmd.Stdout = &stdout var stderr strings.Builder cmd.Stderr = &stderr var exitCode int; err = cmd.Run() if err != nil { // try to get the exit code if exitError, ok := err.(*exec.ExitError); ok { ws := exitError.Sys().(syscall.WaitStatus) exitCode = ws.ExitStatus() } else { // This will happen (in OSX) if `name` is not available in $PATH, // in this situation, exit code could not be get, and stderr will be // empty string very likely, so we use the default fail code, and format err // to string and set to stderr app.Log("Could not get exit code for failed program") exitCode = 255 } } else { // success, exitCode should be 0 if go is ok ws := cmd.ProcessState.Sys().(syscall.WaitStatus) exitCode = ws.ExitStatus() } return map[string]interface{}{ "retval" : exitCode, "error" : err, "stdout" : stdout.String(), "stderr" : stderr.String(), }, nil }