@@ -63,6 +63,7 @@ func multiplexAction(context *cli.Context) error {
63
63
}
64
64
65
65
concurrent := context .GlobalInt ("concurrency" )
66
+ lines := context .GlobalInt ("lines" )
66
67
67
68
// Parse OpenSSH client config file at ~/.ssh/config:
68
69
user , err := user .Current ()
@@ -115,7 +116,7 @@ func multiplexAction(context *cli.Context) error {
115
116
host : host ,
116
117
config : sections [host ],
117
118
signal : signal ,
118
- //lines : make([]string, 1) ,
119
+ state : pending ,
119
120
})
120
121
}
121
122
@@ -127,15 +128,7 @@ func multiplexAction(context *cli.Context) error {
127
128
for range signal {
128
129
w .Flush ()
129
130
for _ , i := range jobs {
130
- var data string
131
- status := green
132
- if i .err != nil {
133
- status = red
134
- data = i .err .Error ()
135
- } else {
136
- data = i .read (5 )
137
- }
138
- fmt .Fprintf (w , lineformat , status , underline , i .host , reset , data )
131
+ fmt .Fprintf (w , lineformat , formatHostLine (i ), i .read (lines ))
139
132
}
140
133
w .Flush ()
141
134
}
@@ -155,21 +148,61 @@ func multiplexAction(context *cli.Context) error {
155
148
return nil
156
149
}
157
150
151
+ func getState (i int ) string {
152
+ switch i {
153
+ case pending :
154
+ return "PENDING"
155
+ case running :
156
+ return "RUNNING"
157
+ case finished :
158
+ return "FINISHED"
159
+ default :
160
+ return "UNKNOWN"
161
+ }
162
+ }
163
+
164
+ func formatHostLine (j * job ) string {
165
+ var (
166
+ status = green
167
+ statemsg = ""
168
+ )
169
+ if j .err != nil {
170
+ status = red
171
+ statemsg = fmt .Sprintf (": ERROR %s" , j .err )
172
+ } else {
173
+ statemsg = fmt .Sprintf (": %s" , getState (j .state ))
174
+ }
175
+ return fmt .Sprintf ("%s%s%s%s%s" ,
176
+ status ,
177
+ underline ,
178
+ j .host ,
179
+ statemsg ,
180
+ reset ,
181
+ )
182
+ }
183
+
158
184
const (
159
185
escape = "\x1b "
160
186
reset = escape + "[0m"
161
187
red = escape + "[31m" // nolint: deadcode, varcheck, unused
162
188
green = escape + "[32m"
163
189
underline = escape + "[4m"
164
190
)
165
- const lineformat = "%s%s%s%s\n %s\n "
191
+ const lineformat = "%s\n %s\n "
192
+
193
+ const (
194
+ pending = iota + 1
195
+ running
196
+ finished
197
+ )
166
198
167
199
type job struct {
168
200
host string
169
201
config SSHClientOptions
170
202
signal chan struct {}
171
203
lines []string
172
204
err error
205
+ state int
173
206
}
174
207
175
208
func (i * job ) read (count int ) string {
@@ -184,13 +217,19 @@ func executeCommand(wg *sync.WaitGroup, jobs chan *job, c command, user string,
184
217
defer wg .Done ()
185
218
186
219
for job := range jobs {
220
+ job .state = running
221
+ job .signal <- struct {}{}
222
+
187
223
var err error
188
224
if job .host , err = cleanHost (job .host ); err != nil {
189
225
job .err = err
226
+ continue
190
227
}
191
228
if err = runSSH (job , c , user , agt , methods , cliOptions , quiet ); err != nil {
192
229
job .err = err
193
230
}
231
+ job .state = finished
232
+ job .signal <- struct {}{}
194
233
}
195
234
}
196
235
@@ -321,6 +360,11 @@ func main() {
321
360
Usage : "set the concurrent worker limit" ,
322
361
Value : 10 ,
323
362
},
363
+ cli.IntFlag {
364
+ Name : "lines,l" ,
365
+ Usage : "number of lines to display on screen at once" ,
366
+ Value : 5 ,
367
+ },
324
368
}
325
369
app .Action = multiplexAction
326
370
if err := app .Run (os .Args ); err != nil {
0 commit comments