package utils
|
|
import (
|
"bufio"
|
"bytes"
|
"errors"
|
"fmt"
|
"io"
|
"os"
|
"os/exec"
|
"time"
|
)
|
|
|
|
func ShellExecute(dir, exe string, args ...string) (string, error) {
|
cmd := exec.Command(exe, args...)
|
stdout, err := cmd.StdoutPipe();
|
if nil != err {
|
msg := fmt.Sprintf("ShellExecute cmd.StdoutPipe err:%v", err)
|
return "", errors.New(msg)
|
}
|
|
cmd.Stderr = os.Stderr
|
if "" != dir {
|
cmd.Dir = dir
|
}
|
|
err = cmd.Start()
|
if nil != err {
|
msg := fmt.Sprintf("ShellExecute cmd.Start err:%v", err)
|
return "", errors.New(msg)
|
}
|
|
var buffer bytes.Buffer
|
reader := bufio.NewReader(stdout)
|
for {
|
line, err2 := reader.ReadString('\n')
|
if io.EOF == err2 {
|
break
|
}
|
|
if nil != err2 {
|
msg := fmt.Sprintf("ShellExecute reader.ReadString err:%v", err2)
|
return "", errors.New(msg)
|
}
|
|
buffer.WriteString(line)
|
}
|
|
err = cmd.Wait()
|
if nil != err {
|
msg := fmt.Sprintf("ShellExecute cmd.Wait err:%v", err)
|
return "", errors.New(msg)
|
}
|
|
return buffer.String(), nil
|
}
|
|
type TerminateFunc func(string) string
|
|
func ShellExecuteEx(d time.Duration, t TerminateFunc, dir, exe string, args ...string) (string, error) {
|
cmd := exec.Command(exe, args...)
|
stdout, err := cmd.StdoutPipe();
|
if nil != err {
|
msg := fmt.Sprintf("ShellExecuteEx cmd.StdoutPipe err:%v", err)
|
return "", errors.New(msg)
|
}
|
|
cmd.Stderr = os.Stderr
|
if "" != dir {
|
cmd.Dir = dir
|
}
|
|
err = cmd.Start()
|
if nil != err {
|
msg := fmt.Sprintf("ShellExecuteEx cmd.Start err:%v", err)
|
return "", errors.New(msg)
|
}
|
|
ch := make(chan string)
|
go func(out io.ReadCloser, command *exec.Cmd) {
|
reader := bufio.NewReader(out)
|
for {
|
line, err2 := reader.ReadString('\n')
|
if io.EOF == err2 {
|
ch <- ""
|
break
|
}
|
|
if nil != err2 {
|
break
|
}
|
|
address := t(line)
|
if len(address) > 0 {
|
err := cmd.Process.Signal(os.Kill)
|
if nil != err {
|
fmt.Println("failed to send signal to child process", err)
|
}
|
ch <- address
|
break
|
}
|
}
|
}(stdout, cmd)
|
|
var address string
|
select {
|
case address = <-ch:
|
err = nil
|
break
|
case <-time.After(d):
|
_ = cmd.Process.Signal(os.Kill)
|
err = errors.New("Timeout error")
|
break
|
}
|
|
_ = cmd.Wait()
|
|
return address, err
|
}
|