1
1
package main
2
2
3
3
import (
4
+ "bytes"
4
5
"fmt"
5
6
"io"
6
7
"os"
7
8
"os/exec"
8
9
"strconv"
10
+ "sync"
9
11
10
12
flags "github.com/jessevdk/go-flags"
11
13
)
12
14
13
15
const AppName = "ntimes"
14
16
15
- type Options struct {
17
+ type options struct {
18
+ Parallels int `short:"p" long:"parallels" description:"Parallel degree of execution" default:"1"`
16
19
ShowVersion bool `short:"v" long:"version" description:"Show version"`
17
20
}
18
21
19
- var opts Options
22
+ var opts options
20
23
21
24
func main () {
22
25
parser := flags .NewParser (& opts , flags .Default ^ flags .PrintErrors )
23
26
parser .Name = AppName
24
- parser .Usage = "[OPTIONS] -- COMMAND"
27
+ parser .Usage = "N [OPTIONS] -- COMMAND"
25
28
26
29
args , err := parser .Parse ()
27
30
@@ -39,23 +42,61 @@ func main() {
39
42
cmdName := args [1 ]
40
43
cmdArgs := args [2 :]
41
44
45
+ stdoutCh := make (chan io.ReadWriter )
46
+ exitCh := make (chan bool )
47
+
42
48
if err != nil {
43
49
panic (err )
44
50
}
45
51
46
- ntimes (cnt , cmdName , cmdArgs , os .Stdin , os .Stdout , os .Stderr )
52
+ go printer (os .Stdout , stdoutCh , exitCh )
53
+
54
+ ntimes (cnt , cmdName , cmdArgs , os .Stdin , os .Stdout , os .Stderr , stdoutCh , opts .Parallels )
55
+
56
+ exitCh <- true
47
57
}
48
58
49
- func ntimes (cnt int , cmdName string , cmdArgs []string , stdin io.Reader , stdout io.Writer , stderr io.Writer ) {
59
+ func ntimes (cnt int , cmdName string , cmdArgs []string , stdin io.Reader , stdout io.Writer , stderr io.Writer , stdoutCh chan io.ReadWriter , parallels int ) {
60
+ var wg sync.WaitGroup
61
+
62
+ sema := make (chan bool , parallels )
63
+
50
64
for i := 0 ; i < cnt ; i ++ {
51
- cmd := exec .Command (cmdName , cmdArgs ... )
52
- cmd .Stdin = stdin
53
- cmd .Stdout = stdout
54
- cmd .Stderr = stderr
55
- err := cmd .Run ()
56
-
57
- if err != nil {
58
- panic (err )
65
+ wg .Add (1 )
66
+ go func () {
67
+ sema <- true
68
+
69
+ defer func () {
70
+ wg .Done ()
71
+ <- sema
72
+ }()
73
+
74
+ stdoutBuffer := new (bytes.Buffer )
75
+
76
+ cmd := exec .Command (cmdName , cmdArgs ... )
77
+ cmd .Stdin = stdin
78
+ cmd .Stdout = stdoutBuffer
79
+ cmd .Stderr = stderr
80
+ err := cmd .Run ()
81
+
82
+ if err != nil {
83
+ panic (err )
84
+ }
85
+
86
+ stdoutCh <- stdoutBuffer
87
+ }()
88
+ }
89
+
90
+ wg .Wait ()
91
+ }
92
+
93
+ func printer (stdout io.Writer , stdoutCh chan io.ReadWriter , exitCh chan bool ) {
94
+ for {
95
+ select {
96
+ case r := <- stdoutCh :
97
+ io .Copy (stdout , r )
98
+ case <- exitCh :
99
+ return
59
100
}
60
101
}
61
102
}
0 commit comments