package syscmd import ( "context" "errors" "fmt" "os/exec" "strings" "time" ) func RunCommand(name string, args ...string) (string, string, int, error) { return RunCommandTimeout(60*time.Second, name, args...) } func CheckPolicyRoute(iface, table string) (bool, error) { stdout, _, exitCode, err := RunCommand("ip", "route", "show", "table", table) if exitCode != 0 { if err == nil { err = fmt.Errorf("ip route show exited with %d", exitCode) } return false, err } want := fmt.Sprintf("default dev %s", iface) for _, line := range strings.Split(stdout, "\n") { line = strings.TrimSpace(line) if strings.HasPrefix(line, want) { return true, nil } } return false, nil } func RunCommandTimeout(timeout time.Duration, name string, args ...string) (string, string, int, error) { ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() cmd := exec.CommandContext(ctx, name, args...) out, err := cmd.CombinedOutput() stdout := string(out) stderr := stdout exitCode := 0 if err != nil { if ee, ok := err.(*exec.ExitError); ok { exitCode = ee.ExitCode() } else if errors.Is(err, context.DeadlineExceeded) { exitCode = -1 err = fmt.Errorf("command timeout: %w", err) } else { exitCode = -1 } } return stdout, stderr, exitCode, err }