@@ -2,7 +2,6 @@ package main
2
2
3
3
import (
4
4
"fmt"
5
- log "github.com/Sirupsen/logrus"
6
5
"github.com/codegangsta/cli"
7
6
"github.com/fatih/color"
8
7
"golang.org/x/crypto/ssh"
@@ -13,6 +12,7 @@ import (
13
12
// Use of the os/user package prevents cross-compilation
14
13
"os/user" // <- https://github.com/golang/go/issues/6376
15
14
"path/filepath"
15
+ "runtime"
16
16
"strings"
17
17
)
18
18
@@ -21,7 +21,7 @@ func main() {
21
21
app .HideVersion = true
22
22
app .Name = "mssh"
23
23
app .Usage = "Run SSH commands on multiple machines"
24
- app .Version = "0.0.2.1 "
24
+ app .Version = "0.0.3 "
25
25
app .Flags = []cli.Flag {
26
26
cli.StringFlag {
27
27
Name : "user,u" ,
@@ -47,8 +47,8 @@ func main() {
47
47
Usage : "Only show last n lines of output for each cmd" ,
48
48
},
49
49
cli.BoolTFlag {
50
- Name : "color,c " ,
51
- Usage : "Print cmd output in color (use -c =false to disable)" ,
50
+ Name : "color" ,
51
+ Usage : "Print cmd output in color (use --color =false to disable)" ,
52
52
},
53
53
}
54
54
app .Action = defaultAction
@@ -60,14 +60,14 @@ func defaultAction(c *cli.Context) {
60
60
61
61
currentUser , err := user .Current ()
62
62
if err != nil {
63
- log . Errorf ( " Could not get current user: %v" , err )
63
+ print ( fmt . Sprintf ( "[X] Could not get current user: %v" , err ), "" )
64
64
}
65
65
u := c .String ("user" )
66
66
// If no flag, get current username
67
67
if len (u ) == 0 {
68
68
u = currentUser .Username
69
69
if len (u ) == 0 {
70
- log . Errorln ( " No username specified!" )
70
+ print ( "[X] No username specified!" , " " )
71
71
}
72
72
}
73
73
@@ -81,7 +81,7 @@ func defaultAction(c *cli.Context) {
81
81
if len (key ) == 0 {
82
82
// If no key provided see if there's an ssh-agent running
83
83
if len (os .Getenv ("SSH_AUTH_SOCK" )) > 0 {
84
- log . Println ( " Attempting to use existing ssh-agent" )
84
+ print ( "[*] Attempting to use existing ssh-agent" , " " )
85
85
conn , err := net .Dial ("unix" , os .Getenv ("SSH_AUTH_SOCK" ))
86
86
if err != nil {
87
87
return
@@ -90,49 +90,56 @@ func defaultAction(c *cli.Context) {
90
90
ag := agent .NewClient (conn )
91
91
auths = []ssh.AuthMethod {ssh .PublicKeysCallback (ag .Signers )}
92
92
} else {
93
- // Otherwise use ~/.ssh/id_rsa
94
- key = filepath .FromSlash (currentUser .HomeDir + "/.ssh/id_rsa" )
95
- if ! fileExists (key ) {
96
- log .Errorln ("Must specify a key, ~/.ssh/id_rsa does not exist and no ssh-agent is available!" )
93
+ k := ""
94
+ // Otherwise use ~/.ssh/id_rsa or ~/ssh/id_rsa (for windows)
95
+ if fileExists (currentUser .HomeDir + string (filepath .Separator ) + ".ssh" + string (filepath .Separator ) + "id_rsa" ) {
96
+ k = currentUser .HomeDir + string (filepath .Separator ) + ".ssh" + string (filepath .Separator ) + "id_rsa"
97
+ } else if fileExists (currentUser .HomeDir + string (filepath .Separator ) + "ssh" + string (filepath .Separator ) + "id_rsa" ) {
98
+ k = currentUser .HomeDir + string (filepath .Separator ) + "ssh" + string (filepath .Separator ) + "id_rsa"
99
+ }
100
+ if len (k ) == 0 {
101
+ print ("[X] No key specified: " + err .Error (), "" )
97
102
cli .ShowAppHelp (c )
98
103
os .Exit (2 )
99
104
}
100
- pemBytes , err := ioutil .ReadFile (key )
105
+ pemBytes , err := ioutil .ReadFile (k )
101
106
if err != nil {
102
- log .Errorf ("%v" , err )
107
+ print ("[X] Error reading key: " + err .Error (), "" )
108
+ os .Exit (2 )
103
109
}
104
110
signer , err := ssh .ParsePrivateKey (pemBytes )
105
111
if err != nil {
106
- log .Errorf ("%v" , err )
112
+ print ("[X] Error reading key: " + err .Error (), "" )
113
+ os .Exit (2 )
107
114
}
108
115
auths = []ssh.AuthMethod {ssh .PublicKeys (signer )}
109
116
}
110
117
} else {
111
118
if ! fileExists (key ) {
112
- log . Errorln ( " Specified key does not exist!" )
119
+ print ( "[X] Specified key does not exist!" , " " )
113
120
os .Exit (1 )
114
121
}
115
122
pemBytes , err := ioutil .ReadFile (key )
116
123
if err != nil {
117
- log . Errorf ( "%v" , err )
124
+ print ( "[X] " + err . Error (), "" )
118
125
}
119
126
signer , err := ssh .ParsePrivateKey (pemBytes )
120
127
if err != nil {
121
- log . Errorf ( "%v" , err )
128
+ print ( "[X] " + err . Error (), "" )
122
129
}
123
130
auths = []ssh.AuthMethod {ssh .PublicKeys (signer )}
124
131
}
125
132
126
133
// host(s) is required
127
134
if len (hosts ) == 0 {
128
- log . Warnln ("At least one host is required" )
135
+ print ("At least one host is required" , "yellow " )
129
136
cli .ShowAppHelp (c )
130
137
os .Exit (2 )
131
138
}
132
139
133
140
// At least one command is required
134
141
if len (c .Args ().First ()) == 0 {
135
- log . Warnln ("At least one command is required" )
142
+ print ("At least one command is required" , "yellow " )
136
143
cli .ShowAppHelp (c )
137
144
os .Exit (2 )
138
145
}
@@ -152,18 +159,22 @@ func defaultAction(c *cli.Context) {
152
159
combined , err := runRemoteCmd (u , host , auth , cmd )
153
160
out := tail (string (combined ), c .Int ("lines" ))
154
161
if err != nil {
155
- pretty := prettyOutput (
156
- fmt .Sprintf ("Execution of `%s` on %s@%s failed. Error message: %v" , cmd , u , host , err ),
157
- out , true , c .Bool ("color" ))
162
+ col := ""
163
+ print (fmt .Sprintf ("[X] Execution of `%s` on %s@%s failed. Error message: %v" , cmd , u , host , err ), "" )
164
+ if c .Bool ("color" ) {
165
+ col = "red"
166
+ }
167
+ print (out , col )
158
168
if c .Bool ("fail" ) {
159
- log . Fatalln ( pretty )
169
+ os . Exit ( 1 )
160
170
}
161
- log .Errorf (pretty )
162
171
} else {
163
- pretty := prettyOutput (
164
- fmt .Sprintf ("Execution of `%s` on %s@%s succeeded:" , cmd , u , host ),
165
- out , false , c .Bool ("color" ))
166
- log .Println (pretty )
172
+ print (fmt .Sprintf ("[*] Execution of `%s` on %s@%s succeeded:" , cmd , u , host ), "" )
173
+ col := ""
174
+ if c .Bool ("color" ) {
175
+ col = "green"
176
+ }
177
+ print (out , col )
167
178
}
168
179
done <- true
169
180
}
@@ -176,21 +187,20 @@ func defaultAction(c *cli.Context) {
176
187
}
177
188
}
178
189
179
- func prettyOutput (status string , out string , isErr bool , useColor bool ) (formatted string ) {
180
-
181
- formatted = status
182
- if useColor {
183
- if isErr {
184
- formatted = fmt .Sprintf ("%s\n %s" , formatted , color .RedString ("%s" , out ))
185
- } else {
186
- formatted = fmt .Sprintf ("%s\n %s" , formatted , color .GreenString ("%s" , out ))
187
- }
190
+ func print (str string , c string ) {
191
+ if len (c ) == 0 || runtime .GOOS == "windows" {
192
+ fmt .Printf ("%s\n " , str )
188
193
return
189
194
}
190
- if isErr {
191
- formatted = fmt .Sprintf ("%s\n %s" , formatted , out )
192
- } else {
193
- formatted = fmt .Sprintf ("%s\n %s" , formatted , out )
195
+ switch c {
196
+ case "red" :
197
+ fmt .Printf ("%s\n " , color .RedString ("%s" , str ))
198
+ case "green" :
199
+ fmt .Printf ("%s\n " , color .GreenString ("%s" , str ))
200
+ case "yellow" :
201
+ fmt .Printf ("%s\n " , color .YellowString ("%s" , str ))
202
+ default :
203
+ fmt .Printf ("%s\n " , str )
194
204
}
195
205
return
196
206
}
0 commit comments