2017-05-05 05:44:44 +00:00
|
|
|
|
// +build !windows
|
|
|
|
|
|
|
|
|
|
package utils
|
|
|
|
|
|
|
|
|
|
import (
|
2017-09-16 09:58:33 +00:00
|
|
|
|
"errors"
|
|
|
|
|
"golang.org/x/net/context"
|
|
|
|
|
"os/exec"
|
|
|
|
|
"syscall"
|
2017-05-05 05:44:44 +00:00
|
|
|
|
)
|
|
|
|
|
|
2017-05-26 13:59:01 +00:00
|
|
|
|
type Result struct {
|
2017-09-16 09:58:33 +00:00
|
|
|
|
output string
|
|
|
|
|
err error
|
2017-05-26 13:59:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-05-05 05:44:44 +00:00
|
|
|
|
// 执行shell命令,可设置执行超时时间
|
2017-09-16 09:58:33 +00:00
|
|
|
|
func ExecShell(ctx context.Context, command string) (string, error) {
|
|
|
|
|
cmd := exec.Command("/bin/bash", "-c", command)
|
|
|
|
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
|
|
|
|
Setpgid: true,
|
|
|
|
|
}
|
2018-01-27 10:08:46 +00:00
|
|
|
|
resultChan := make(chan Result)
|
2017-09-16 09:58:33 +00:00
|
|
|
|
go func() {
|
|
|
|
|
output, err := cmd.CombinedOutput()
|
|
|
|
|
resultChan <- Result{string(output), err}
|
|
|
|
|
}()
|
|
|
|
|
select {
|
|
|
|
|
case <-ctx.Done():
|
|
|
|
|
if cmd.Process.Pid > 0 {
|
|
|
|
|
syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
|
|
|
|
|
}
|
|
|
|
|
return "", errors.New("timeout killed")
|
|
|
|
|
case result := <-resultChan:
|
|
|
|
|
return result.output, result.err
|
|
|
|
|
}
|
|
|
|
|
}
|