-
-
Save tawateer/3519de1cb748c83f8dee5f711a1204f9 to your computer and use it in GitHub Desktop.
Golang exec.Command Timeout Wrapper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"fmt" | |
"os/exec" | |
"time" | |
) | |
func run(timeout int, command string, args ...string) string { | |
// instantiate new command | |
cmd := exec.Command(command, args...) | |
// get pipe to standard output | |
stdout, err := cmd.StdoutPipe() | |
if err != nil { | |
return "cmd.StdoutPipe() error: " + err.Error() | |
} | |
// start process via command | |
if err := cmd.Start(); err != nil { | |
return "cmd.Start() error: " + err.Error() | |
} | |
// setup a buffer to capture standard output | |
var buf bytes.Buffer | |
// create a channel to capture any errors from wait | |
done := make(chan error) | |
go func() { | |
if _, err := buf.ReadFrom(stdout); err != nil { | |
panic("buf.Read(stdout) error: " + err.Error()) | |
} | |
done <- cmd.Wait() | |
}() | |
// block on select, and switch based on actions received | |
select { | |
case <-time.After(time.Duration(timeout) * time.Second): | |
if err := cmd.Process.Kill(); err != nil { | |
return "failed to kill: " + err.Error() | |
} | |
return "timeout reached, process killed" | |
case err := <-done: | |
if err != nil { | |
close(done) | |
return "process done, with error: " + err.Error() | |
} | |
return "process completed: " + buf.String() | |
} | |
return "" | |
} | |
func main() { | |
s := run(5, "ping", "-c25", "8.8.8.8") | |
fmt.Printf("output: %s\n", s) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment