yanghui
2021-06-28 b568d251606f82968b8103c485a0d70027c1d57e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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
}