Security News
Maven Central Adds Sigstore Signature Validation
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.
github.com/go-cmd/cmd
This package is a small but very useful wrapper around os/exec.Cmd that makes it safe and simple to run external commands in highly concurrent, asynchronous, real-time applications. It works on Linux, macOS, and Windows. Here's the basic usage:
import (
"fmt"
"time"
"github.com/go-cmd/cmd"
)
func main() {
// Start a long-running process, capture stdout and stderr
findCmd := cmd.NewCmd("find", "/", "--name", "needle")
statusChan := findCmd.Start() // non-blocking
ticker := time.NewTicker(2 * time.Second)
// Print last line of stdout every 2s
go func() {
for range ticker.C {
status := findCmd.Status()
n := len(status.Stdout)
fmt.Println(status.Stdout[n-1])
}
}()
// Stop command after 1 hour
go func() {
<-time.After(1 * time.Hour)
findCmd.Stop()
}()
// Check if command is done
select {
case finalStatus := <-statusChan:
// done
default:
// no, still running
}
// Block waiting for command to exit, be stopped, or be killed
finalStatus := <-statusChan
}
That's it, only three methods: Start
, Stop
, and Status
. When possible, it's better to use go-cmd/Cmd
than os/exec.Cmd
because go-cmd/Cmd
provides:
As the example above shows, starting a command immediately returns a channel to which the final status is sent when the command exits for any reason. So by default commands run asynchronously, but running synchronously is possible and easy, too:
// Run foo and block waiting for it to exit
c := cmd.NewCmd("foo")
s := <-c.Start()
To achieve similar with os/exec.Cmd
requires everything this package already does.
It's common to want to read stdout or stderr while the command is running. The common approach is to call StdoutPipe and read from the provided io.ReadCloser
. This works but it's wrong because it causes a race condition (that go test -race
detects) and the docs say it's wrong:
It is thus incorrect to call Wait before all reads from the pipe have completed. For the same reason, it is incorrect to call Run when using StdoutPipe.
The proper solution is to set the io.Writer
of Stdout
. To be thread-safe and non-racey, this requires further work to write while possibly N-many goroutines read. go-cmd/Cmd
has done this work.
Similar to real-time stdout and stderr, it's nice to see, for example, elapsed runtime. This package allows that: Status
can be called any time by any goroutine, and it returns this struct:
type Status struct {
Cmd string
PID int
Complete bool
Exit int
Error error
Runtime float64 // seconds
Stdout []string
Stderr []string
}
Speaking of that struct above, Go built-in Cmd
does not put all the return information in one place, which is fine because Go is awesome! But to save some time, go-cmd/Cmd
uses the Status
struct above to convey all information about the command. Even when the command finishes, calling Status
returns the final status, the same final status sent to the status channel returned by the call to Start
.
os/exec/Cmd.Wait can block even after the command is killed. That can be surprising and cause problems. But go-cmd/Cmd.Stop
reliably terminates the command, no surprises. The issue has to do with process group IDs. It's common to kill the command PID, but usually one needs to kill its process group ID instead. go-cmd/Cmd.Stop
implements the necessary low-level magic to make this happen.
In addition to 100% test coverage and no race conditions, this package is actively used in production environments.
Brian Ip wrote the original code to get the exit status. Strangely, Go doesn't just provide this, it requires magic like exiterr.Sys().(syscall.WaitStatus)
and more.
MIT © go-Cmd.
FAQs
Unknown package
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.
Security News
CISOs are racing to adopt AI for cybersecurity, but hurdles in budgets and governance may leave some falling behind in the fight against cyber threats.
Research
Security News
Socket researchers uncovered a backdoored typosquat of BoltDB in the Go ecosystem, exploiting Go Module Proxy caching to persist undetected for years.