diff --git a/internal/common/common.go b/internal/common/common.go index f0ea6dd..1cc26a1 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -341,3 +341,46 @@ func WaitTimeout(c *exec.Cmd, timeout time.Duration) error { return ErrTimeout } } + +// https://gist.github.com/kylelemons/1525278 +func Pipeline(cmds ...*exec.Cmd) (pipeLineOutput, collectedStandardError []byte, pipeLineError os.Error) { + // Require at least one command + if len(cmds) < 1 { + return nil, nil, nil + } + + // Collect the output from the command(s) + var output bytes.Buffer + var stderr bytes.Buffer + + last := len(cmds) - 1 + for i, cmd := range cmds[:last] { + var err os.Error + // Connect each command's stdin to the previous command's stdout + if cmds[i+1].Stdin, err = cmd.StdoutPipe(); err != nil { + return nil, nil, err + } + // Connect each command's stderr to a buffer + cmd.Stderr = &stderr + } + + // Connect the output and error for the last command + cmds[last].Stdout, cmds[last].Stderr = &output, &stderr + + // Start each command + for _, cmd := range cmds { + if err := cmd.Start(); err != nil { + return output.Bytes(), stderr.Bytes(), err + } + } + + // Wait for each command to complete + for _, cmd := range cmds { + if err := cmd.Wait(); err != nil { + return output.Bytes(), stderr.Bytes(), err + } + } + + // Return the pipeline output and the collected standard error + return output.Bytes(), stderr.Bytes(), nil +} diff --git a/process/process_darwin.go b/process/process_darwin.go index 37d878b..b061969 100644 --- a/process/process_darwin.go +++ b/process/process_darwin.go @@ -80,21 +80,25 @@ func (p *Process) Name() (string, error) { return common.IntToString(k.Proc.P_comm[:]), nil } func (p *Process) Exe() (string, error) { - bin, err := exec.LookPath("lsof") + lsof_bin, err := exec.LookPath("lsof") if err != nil { return "", err } - cmd := []string{"-p", strconv.Itoa(int(p.Pid)), "-Fn", "|", "awk", "NR==3{print}", "|", "sed", "s/n\\//\\//"} + awk_bin, _ := exec.Lookpath("awk") + sed_bin, _ := exec.LookPath("sed") - fmt.Println(strings.Join(cmd, " ")) + lsof := exec.Command(lsof_bin, "-p", strconv.Itoa(int(p.Pid)), "-Fn") + awk := exec.Command(awk_bin, "NR==3{print}") + sed := exec.Command("s/n\\//\\//") + + output, stderr, err := common.Pipeline(lsof, awk, sed) - out, err := invoke.Command(bin, cmd...) if err != nil { return "", err } - ret := strings.TrimSpace(string(out)) + ret := strings.TrimSpace(string(output)) return ret, nil }