The Go exec package makes it pretty easy to run an OS command and read the output; and there are a few examples of how to pipe the output of one command into another (e.g. lsof | wc -l):
lsof := exec.Command("lsof")
wc := exec.Command("wc", "-l")
outPipe, err := lsof.StdoutPipe()
if err != nil {
return nil, err
}
lsof.Start()
wc.Stdin = outPipe
out, err := wc.Output()
if err != nil {
return nil, err
}
return out, nil
There’s a problem with this code though, the pipe will never be closed; if the caller is a long-lived process then it will leak file descriptors.
You don’t normally have to worry about this, as calling Run or Output (instead of Start) will take care of it; but we can’t use those as they’ll close the pipe too early.
The problem is easily solved, either by closing the pipe yourself:
outPipe, err := lsof.StdoutPipe() defer outPipe.Close()
or by calling Wait after the output from the second command has been received:
out, err := wc.Output()
if err != nil {
return nil, err
}
err = lsof.Wait()
if err != nil {
return nil, err
}
return out, nil