ssh2shell 1.9.8 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- package/lib/ssh2shell.js +163 -129
- package/package.json +57 -57
- package/src/ssh2shell.coffee +151 -128
- package/test/Multiple primary hosts.js +4 -10
- package/test/devtest.js +5 -3
- package/test/issue69.js +24 -24
- package/test/keyboard-interactivetest.js +3 -20
- package/test/lots of commands.js +87 -0
- package/test/notificationstest.js +13 -10
- package/test/sshUserCommandsPosition.js +26 -0
- package/test/sudo no pass test.js +40 -0
- package/test/timeouttest.js +19 -63
- package/test/tunneltest.js +2 -2
- package/test/tunneltestSshUserCommands.js +71 -0
package/src/ssh2shell.coffee
CHANGED
|
@@ -9,7 +9,8 @@ Stream = require('stream');
|
|
|
9
9
|
class SSH2Shell extends Stream
|
|
10
10
|
sshObj: {}
|
|
11
11
|
command: ""
|
|
12
|
-
|
|
12
|
+
_hosts: []
|
|
13
|
+
_sshToNextHost: false
|
|
13
14
|
_primaryhostSessionText: ""
|
|
14
15
|
_allSessions: ""
|
|
15
16
|
_connections: []
|
|
@@ -36,7 +37,7 @@ class SSH2Shell extends Stream
|
|
|
36
37
|
@.emit 'commandProcessing' , @command, @_buffer, @sshObj, @_stream
|
|
37
38
|
clearTimeout @idleTimer if @idleTimer
|
|
38
39
|
@idleTimer = setTimeout( =>
|
|
39
|
-
@.emit 'commandTimeout', @.command, @._buffer, @._stream, @.
|
|
40
|
+
@.emit 'commandTimeout', @.command, @._buffer, @._stream, @.connection
|
|
40
41
|
, @idleTime)
|
|
41
42
|
else if @command.length < 1 and not @standardPrompt.test(@_buffer)
|
|
42
43
|
@.emit 'commandProcessing' , @command, @_buffer, @sshObj, @_stream
|
|
@@ -50,21 +51,19 @@ class SSH2Shell extends Stream
|
|
|
50
51
|
|
|
51
52
|
#remove test coloring from responses like [32m[31m
|
|
52
53
|
unless @.sshObj.disableColorFilter
|
|
53
|
-
@emit 'msg', "#{@sshObj.server.host}: text formatting filter: "+@sshObj.textColorFilter+", filtered: "+@textColorFilter.test(@_buffer) if @sshObj.verbose and @sshObj.debug
|
|
54
54
|
@_buffer = @_buffer.replace(@textColorFilter, "")
|
|
55
55
|
|
|
56
56
|
#remove non-standard ascii from terminal responses
|
|
57
57
|
unless @.sshObj.disableASCIIFilter
|
|
58
|
-
@emit 'msg', "#{@sshObj.server.host}: Non-standard ASCII filtered: "+@asciiFilter.test(@_buffer) if @sshObj.verbose and @sshObj.debug
|
|
59
58
|
@_buffer = @_buffer.replace(@asciiFilter, "")
|
|
60
59
|
|
|
61
60
|
switch (true)
|
|
62
61
|
#check if sudo password is needed
|
|
63
62
|
when @command.length > 0 and @command.indexOf("sudo ") isnt -1
|
|
64
|
-
@emit 'msg', "#{@sshObj.server.host}: Sudo command data" if @sshObj.debug
|
|
63
|
+
@emit 'msg', "#{@sshObj.server.host}: Sudo command data" if @sshObj.debug
|
|
65
64
|
@_processPasswordPrompt()
|
|
66
65
|
#check if ssh authentication needs to be handled
|
|
67
|
-
when @command.length > 0 and @command.indexOf("ssh ")
|
|
66
|
+
when @sshObj.sshToNextHost and @command.length > 0 and @command.indexOf("ssh ") is 0
|
|
68
67
|
@emit 'msg', "#{@sshObj.server.host}: SSH command data" if @sshObj.debug
|
|
69
68
|
@_processSSHPrompt()
|
|
70
69
|
#check for standard prompt from a command
|
|
@@ -80,7 +79,7 @@ class SSH2Shell extends Stream
|
|
|
80
79
|
else
|
|
81
80
|
@emit 'msg', "Data processing: data received timeout" if @sshObj.debug
|
|
82
81
|
@idleTimer = setTimeout( =>
|
|
83
|
-
@.emit 'commandTimeout', @.command, @._buffer, @._stream, @.
|
|
82
|
+
@.emit 'commandTimeout', @.command, @._buffer, @._stream, @.connection
|
|
84
83
|
, @idleTime)
|
|
85
84
|
, @dataIdleTime)
|
|
86
85
|
|
|
@@ -88,45 +87,52 @@ class SSH2Shell extends Stream
|
|
|
88
87
|
return @_buffer.replace(@command.substr(0, @_buffer.length), "")
|
|
89
88
|
|
|
90
89
|
_processPasswordPrompt: =>
|
|
91
|
-
#First test for password prompt
|
|
90
|
+
#First test for password prompt
|
|
92
91
|
response = @_sanitizeResponse().trim()
|
|
93
92
|
passwordPrompt = @passwordPrompt.test(response)
|
|
94
93
|
standardPrompt = @standardPrompt.test(response)
|
|
95
|
-
@.emit 'msg', "#{@sshObj.server.host}: Password
|
|
96
|
-
@.emit 'msg', "#{@sshObj.server.host}: Password prompt: Password
|
|
97
|
-
@.emit 'msg', "#{@sshObj.server.host}:
|
|
98
|
-
@.emit 'msg', "#{@sshObj.server.host}: Sudo
|
|
99
|
-
|
|
100
|
-
#
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
@
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
@.emit 'msg', "#{@sshObj.server.host}:
|
|
109
|
-
@.emit 'msg', "#{@sshObj.server.host}:
|
|
110
|
-
@.emit 'msg', "#{@sshObj.server.host}: Sent password: #{@sshObj.server.password}" if @sshObj.verbose
|
|
94
|
+
@.emit 'msg', "#{@sshObj.server.host}: Sudo Password prompt detected: #{passwordPrompt}" if @sshObj.debug
|
|
95
|
+
@.emit 'msg', "#{@sshObj.server.host}: Sudo Password prompt: Password sent: #{@sshObj.pwSent}" if @sshObj.debug
|
|
96
|
+
@.emit 'msg', "#{@sshObj.server.host}: Sudo Password: #{@sshObj.server.password}" if @sshObj.debug
|
|
97
|
+
@.emit 'msg', "#{@sshObj.server.host}: Sudo Response: #{response}" if @sshObj.verbose
|
|
98
|
+
|
|
99
|
+
#Prompt detection
|
|
100
|
+
#no password
|
|
101
|
+
switch (true)
|
|
102
|
+
when passwordPrompt and not @sshObj.server.password
|
|
103
|
+
@.emit 'msg', "#{@sshObj.server.host}: Sudo password prompt no password set" if @sshObj.debug
|
|
104
|
+
@_resetFromSudoError()
|
|
105
|
+
when passwordPrompt and not @sshObj.pwSent
|
|
106
|
+
@.emit 'msg', "#{@sshObj.server.host}: Sudo password prompt: Buffer: #{response}" if @sshObj.verbose
|
|
107
|
+
@.emit 'msg', "#{@sshObj.server.host}: Sudo password prompt: Send password " if @sshObj.debug
|
|
108
|
+
@.emit 'msg', "#{@sshObj.server.host}: Sudo sent password: #{@sshObj.server.password}" if @sshObj.verbose
|
|
111
109
|
#send password
|
|
112
110
|
@sshObj.pwSent = true
|
|
113
111
|
@_runCommand("#{@sshObj.server.password}")
|
|
114
|
-
|
|
115
|
-
@.emit 'msg', "#{@sshObj.server.host}: Password prompt: not detected" if @sshObj.debug
|
|
116
|
-
@.emit 'msg', "#{@sshObj.server.host}: Password prompt #{@sshObj.passwordPrompt}" if @sshObj.verbose
|
|
117
|
-
@_runExit()
|
|
118
|
-
#password sent so either check for failure or run next command
|
|
119
|
-
else if passwordPrompt
|
|
112
|
+
when passwordPrompt and @sshObj.pwSent
|
|
120
113
|
@.emit 'msg', "#{@sshObj.server.host}: Sudo password faied: response: #{response}" if @sshObj.verbose
|
|
121
|
-
@.emit 'error', "#{@sshObj.server.host}: Sudo password was incorrect for #{@sshObj.server.userName}
|
|
122
|
-
@.emit 'msg', "#{@sshObj.server.host}:
|
|
114
|
+
@.emit 'error', "#{@sshObj.server.host}: Sudo password was incorrect for #{@sshObj.server.userName}, Sudo authentication" if @sshObj.debug
|
|
115
|
+
@.emit 'msg', "#{@sshObj.server.host}: Sudo failed password prompt: Password: [#{@sshObj.server.password}]" if @sshObj.debug
|
|
116
|
+
@sshObj.pwSent = false
|
|
123
117
|
#add buffer to sessionText so the sudo response can be seen
|
|
124
|
-
@
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
@
|
|
128
|
-
@
|
|
129
|
-
|
|
118
|
+
@_resetFromSudoError()
|
|
119
|
+
when standardPrompt
|
|
120
|
+
@.emit 'msg', "#{@sshObj.server.host}: Sudo password accepted" if @sshObj.debug
|
|
121
|
+
@sshObj.pwSent = false
|
|
122
|
+
@.emit 'msg', "#{@sshObj.server.host}: Sudo Standard Response: #{response}" if @sshObj.verbose
|
|
123
|
+
@_commandComplete()
|
|
124
|
+
else
|
|
125
|
+
@idleTimer = setTimeout( =>
|
|
126
|
+
@.emit 'commandTimeout', @.command, response, @._stream, @._connection
|
|
127
|
+
, @idleTime)
|
|
128
|
+
|
|
129
|
+
_resetFromSudoError: =>
|
|
130
|
+
@sshObj.pwSent = false
|
|
131
|
+
@sshObj.sessionText += "#{@_buffer}"
|
|
132
|
+
@_buffer = ""
|
|
133
|
+
@command = ""
|
|
134
|
+
#cancal command on host
|
|
135
|
+
@_stream.write '\x03'
|
|
130
136
|
|
|
131
137
|
_processSSHPrompt: =>
|
|
132
138
|
#not authenticated yet so detect prompts
|
|
@@ -156,25 +162,30 @@ class SSH2Shell extends Stream
|
|
|
156
162
|
@_runCommand("#{@sshObj.server.passPhrase}")
|
|
157
163
|
#normal prompt so continue with next command
|
|
158
164
|
else if standardPrompt
|
|
159
|
-
@.emit 'msg', "#{@sshObj.server.host}: SSH
|
|
165
|
+
@.emit 'msg', "#{@sshObj.server.host}: SSH standard prompt: connection failed" if @sshObj.debug
|
|
160
166
|
@.emit 'msg', "#{@sshObj.server.host}: SSH connection failed"
|
|
161
167
|
@.emit 'msg', "#{@sshObj.server.host}: SSH failed response: #{response}"
|
|
162
168
|
@sshObj.sessionText += "#{@sshObj.server.host}: SSH failed: response: #{response}"
|
|
163
169
|
@_runExit()
|
|
164
170
|
else
|
|
165
|
-
@.emit 'msg', "#{@sshObj.server.host}: SSH
|
|
166
|
-
@.emit 'msg', "#{@sshObj.server.host}:
|
|
167
|
-
@.emit 'msg', "#{@sshObj.server.host}:
|
|
168
|
-
@.emit 'msg', "#{@sshObj.server.host}:
|
|
171
|
+
@.emit 'msg', "#{@sshObj.server.host}: SSH no prompt was not detected"
|
|
172
|
+
@.emit 'msg', "#{@sshObj.server.host}: SSH response: #{response}" if @sshObj.verbose
|
|
173
|
+
@.emit 'msg', "#{@sshObj.server.host}: SSH password prompt: #{@sshObj.passwordPrompt}" if @sshObj.verbose and not @sshObj.server.hasOwnProperty("password")
|
|
174
|
+
@.emit 'msg', "#{@sshObj.server.host}: SSH passphrase prompt: #{@sshObj.passphrasePrompt}" if @sshObj.verbose and @sshObj.server.hasOwnProperty("passPhrase")
|
|
175
|
+
@.emit 'msg', "#{@sshObj.server.host}: SSH standard prompt: #{@sshObj.standardPrompt}" if @sshObj.verbose
|
|
169
176
|
@_runExit()
|
|
170
177
|
else
|
|
171
178
|
@.emit 'msg', "#{@sshObj.server.host}: SSH post authentication prompt detection" if @sshObj.debug
|
|
172
|
-
|
|
179
|
+
#@sshObj.sshToNextHost = false
|
|
180
|
+
|
|
173
181
|
if standardPrompt
|
|
174
|
-
@.emit 'msg', "#{@sshObj.server.host}: SSH complete: normal prompt" if @sshObj.debug
|
|
182
|
+
@.emit 'msg', "#{@sshObj.server.host}: SSH complete: normal prompt" if @sshObj.debug
|
|
183
|
+
@sshObj.sessionText += "\n #{response}" if @sshObj.showBanner
|
|
175
184
|
@sshObj.exitCommands.push "exit"
|
|
176
185
|
@.emit 'msg', "#{@sshObj.connectedMessage}"
|
|
177
186
|
@.emit 'msg', "#{@sshObj.readyMessage}"
|
|
187
|
+
@.emit 'msg', "#{@sshObj.server.host}: SSH complete: next command" if @sshObj.debug
|
|
188
|
+
@sshObj.sshToNextHost = false
|
|
178
189
|
@_nextCommand()
|
|
179
190
|
#Password or passphase detected a second time after authentication indicating failure.
|
|
180
191
|
else if (passwordPrompt or passphrasePrompt)
|
|
@@ -183,14 +194,14 @@ class SSH2Shell extends Stream
|
|
|
183
194
|
@.emit 'msg', "#{@sshObj.server.host}: SSH: failed response: #{response}" if @sshObj.verbose
|
|
184
195
|
@sshObj.sshAuth = false
|
|
185
196
|
using = switch
|
|
186
|
-
when passwordPrompt then "password: #{@sshObj.server.password}"
|
|
187
|
-
when passphrasePrompt then "passphrase: #{@sshObj.server.passPhrase}"
|
|
197
|
+
when passwordPrompt then "SSH password: #{@sshObj.server.password}"
|
|
198
|
+
when passphrasePrompt then "SSH passphrase: #{@sshObj.server.passPhrase}"
|
|
188
199
|
@.emit 'error', "#{@sshObj.server.host}: SSH authentication failed for #{@sshObj.server.userName}@#{@sshObj.server.host}", "Nested host authentication"
|
|
189
200
|
@.emit 'msg', "#{@sshObj.server.host}: SSH auth failed: Using " + using if @sshObj.debug
|
|
190
201
|
|
|
191
202
|
#no connection so drop back to first host settings if there was one
|
|
192
203
|
#@sshObj.sessionText += "#{@_buffer}"
|
|
193
|
-
@.emit 'msg', "#{@sshObj.server.host}: SSH
|
|
204
|
+
@.emit 'msg', "#{@sshObj.server.host}: SSH response: #{response}" if @sshObj.verbose
|
|
194
205
|
if @_connections.length > 0
|
|
195
206
|
return @_previousHost()
|
|
196
207
|
|
|
@@ -218,18 +229,13 @@ class SSH2Shell extends Stream
|
|
|
218
229
|
@_checkCommand()
|
|
219
230
|
|
|
220
231
|
_commandComplete: =>
|
|
221
|
-
response = @_buffer.trim()
|
|
232
|
+
response = @_buffer.trim()
|
|
222
233
|
#check sudo su has been authenticated and add an extra exit command
|
|
223
|
-
|
|
224
|
-
if @command isnt "" and @command isnt "exit" and @command.indexOf("ssh ") is -1
|
|
234
|
+
if @command isnt "" and @command isnt "exit" and @sshObj.sshToNextHost isnt true
|
|
225
235
|
@.emit 'msg', "#{@sshObj.server.host}: Command complete:\nCommand:\n #{@command}\nResponse: #{response}" if @sshObj.verbose
|
|
226
236
|
@sshObj.sessionText += response
|
|
227
237
|
@.emit 'msg', "#{@sshObj.server.host}: Raising commandComplete event" if @sshObj.debug
|
|
228
238
|
@.emit 'commandComplete', @command, @_buffer, @sshObj
|
|
229
|
-
|
|
230
|
-
#if @command.indexOf("exit") != -1
|
|
231
|
-
# @_runExit()
|
|
232
|
-
#else
|
|
233
239
|
@_nextCommand()
|
|
234
240
|
|
|
235
241
|
_nextCommand: =>
|
|
@@ -263,10 +269,12 @@ class SSH2Shell extends Stream
|
|
|
263
269
|
@.emit 'msg', "#{@sshObj.server.host}: Load previous host config" if @sshObj.debug
|
|
264
270
|
@.emit 'end', "#{@sshObj.server.host}: \n#{@sshObj.sessionText}", @sshObj
|
|
265
271
|
@.emit 'msg', "#{@sshObj.server.host}: Previous hosts: #{@_connections.length}" if @sshObj.debug
|
|
272
|
+
|
|
266
273
|
if @_connections.length > 0
|
|
267
274
|
@sshObj = @_connections.pop()
|
|
268
275
|
@.emit 'msg', "#{@sshObj.server.host}: Reload previous host" if @sshObj.debug
|
|
269
|
-
|
|
276
|
+
#@_loadDefaults(@_runExit)
|
|
277
|
+
@_runExit()
|
|
270
278
|
else
|
|
271
279
|
@_runExit()
|
|
272
280
|
|
|
@@ -275,31 +283,36 @@ class SSH2Shell extends Stream
|
|
|
275
283
|
nextHost = @sshObj.hosts.shift()
|
|
276
284
|
@.emit 'msg', "#{@sshObj.server.host}: SSH to #{nextHost.server.host}" if @sshObj.debug
|
|
277
285
|
@.emit 'msg', "#{@sshObj.server.host}: Clearing previous event handlers" if @sshObj.debug
|
|
278
|
-
|
|
286
|
+
@.emit 'msg', "#{@sshObj.server.host}: Remove previous event handlers" if @sshObj.debug
|
|
287
|
+
@_removeEvents()
|
|
288
|
+
|
|
279
289
|
@_connections.push(@sshObj)
|
|
280
290
|
|
|
281
|
-
@sshObj = nextHost
|
|
291
|
+
@sshObj = nextHost
|
|
292
|
+
|
|
282
293
|
@_initiate(@_sshConnect)
|
|
283
294
|
|
|
284
295
|
|
|
285
|
-
_nextPrimaryHost: (
|
|
296
|
+
_nextPrimaryHost: ( connect )=>
|
|
286
297
|
|
|
287
|
-
if
|
|
298
|
+
if @_hosts.length > 0
|
|
288
299
|
if @sshObj.server
|
|
289
300
|
@.emit 'msg', "#{@sshObj.server.host}: Current primary host" if @sshObj.debug
|
|
290
|
-
|
|
291
|
-
|
|
301
|
+
@.emit 'msg', "#{@sshObj.server.host}: Remove previous event handlers" if @sshObj.debug
|
|
302
|
+
@_removeEvents()
|
|
303
|
+
@sshObj = @_hosts.shift()
|
|
292
304
|
@_primaryhostSessionText = "#{@sshObj.server.host}: "
|
|
293
305
|
|
|
294
306
|
@.emit 'msg', "#{@sshObj.server.host}: Next primary host" if @sshObj.debug
|
|
295
|
-
|
|
296
|
-
@_initiate(
|
|
307
|
+
|
|
308
|
+
@_initiate(connect)
|
|
297
309
|
else
|
|
298
310
|
@.emit 'msg', "#{@sshObj.server.host}: No more primary hosts" if @sshObj.debug
|
|
299
311
|
@_runExit
|
|
300
312
|
|
|
301
313
|
|
|
302
314
|
_sshConnect: =>
|
|
315
|
+
|
|
303
316
|
#add ssh commandline options from host.server.ssh
|
|
304
317
|
sshFlags = "-x"
|
|
305
318
|
sshOptions = ""
|
|
@@ -321,6 +334,7 @@ class SSH2Shell extends Stream
|
|
|
321
334
|
sshOptions += ' -o "StrictHostKeyChecking=no"'
|
|
322
335
|
sshOptions += " -p #{@sshObj.server.port}"
|
|
323
336
|
@sshObj.sshAuth = false
|
|
337
|
+
@sshObj.sshToNextHost = true
|
|
324
338
|
@command = "ssh #{sshFlags} #{sshOptions} #{@sshObj.server.userName}@#{@sshObj.server.host}"
|
|
325
339
|
@.emit 'msg', "#{@sshObj.server.host}: SSH command: connect" if @sshObj.debug
|
|
326
340
|
@_runCommand(@command)
|
|
@@ -331,7 +345,8 @@ class SSH2Shell extends Stream
|
|
|
331
345
|
if @sshObj.exitCommands and @sshObj.exitCommands.length > 0
|
|
332
346
|
@.emit 'msg', "#{@sshObj.server.host}: Queued exit commands: #{@sshObj.exitCommands.length}" if @sshObj.debug
|
|
333
347
|
@command = @sshObj.exitCommands.pop()
|
|
334
|
-
if @_connections and @_connections.length > 0
|
|
348
|
+
if @_connections and @_connections.length > 0
|
|
349
|
+
@.emit 'msg', "#{@sshObj.server.host}: Primary host: #{@_connections[0].server.host}" if @sshObj.verbose
|
|
335
350
|
@_connections[0].sessionText += "\n#{@sshObj.server.host}: #{@sshObj.sessionText}"
|
|
336
351
|
@_runCommand(@command)
|
|
337
352
|
#more hosts to connect to so process the next one
|
|
@@ -343,9 +358,7 @@ class SSH2Shell extends Stream
|
|
|
343
358
|
@.emit 'msg', "#{@sshObj.server.host}: load previous host" if @sshObj.debug
|
|
344
359
|
@.emit 'msg', "#{@sshObj.server.host}: #{@sshObj.closedMessage}"
|
|
345
360
|
@_previousHost()
|
|
346
|
-
|
|
347
|
-
#@connection.end()
|
|
348
|
-
else if @command == "exit"
|
|
361
|
+
else if @command is "exit"
|
|
349
362
|
@.emit 'msg', "#{@sshObj.server.host}: Manual exit command" if @sshObj.debug
|
|
350
363
|
@_runCommand("exit")
|
|
351
364
|
#Nothing more to do so end the stream with last exit
|
|
@@ -357,81 +370,92 @@ class SSH2Shell extends Stream
|
|
|
357
370
|
@_stream.close() #"exit#{@sshObj.enter}"
|
|
358
371
|
|
|
359
372
|
_removeEvents: =>
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
373
|
+
###
|
|
374
|
+
if @sshObj.debug
|
|
375
|
+
@.emit 'msg', "#{@sshObj.server.host}: Event handler count:"
|
|
376
|
+
@.emit 'msg', "keyboard-interactive: " + (@.listenerCount 'keyboard-interactive')
|
|
377
|
+
@.emit 'msg', "error: " + (@.listenerCount "error")
|
|
378
|
+
@.emit 'msg', "data: " + (@.listenerCount "data")
|
|
379
|
+
@.emit 'msg', "stderrData: " + (@.listenerCount "stderrData")
|
|
380
|
+
@.emit 'msg', "end: " + (@.listenerCount 'end')
|
|
381
|
+
@.emit 'msg', "commandProcessing: " + (@.listenerCount 'commandProcessing')
|
|
382
|
+
@.emit 'msg', "commandComplete: " + (@.listenerCount 'commandComplete')
|
|
383
|
+
@.emit 'msg', "commandTimeout: " + (@.listenerCount 'commandTimeout')
|
|
384
|
+
@.emit 'msg', "msg: " + (@.listenerCount 'msg')
|
|
385
|
+
###
|
|
386
|
+
@.removeListener "data", @sshObj.onData if typeof @sshObj.onData == 'function'
|
|
363
387
|
@.removeAllListeners "error"
|
|
364
|
-
@.removeListener "data", @sshObj.onData if typeof @sshObj.onData == 'function'
|
|
365
388
|
@.removeListener "stderrData", @sshObj.onStderrData if typeof @sshObj.onStderrData == 'function'
|
|
366
389
|
@.removeAllListeners 'end'
|
|
390
|
+
@.removeAllListeners 'keyboard-interactive'
|
|
367
391
|
@.removeAllListeners 'commandProcessing'
|
|
368
392
|
@.removeAllListeners 'commandComplete'
|
|
369
393
|
@.removeAllListeners 'commandTimeout'
|
|
370
394
|
@.removeAllListeners 'msg'
|
|
371
|
-
|
|
395
|
+
|
|
372
396
|
clearTimeout @idleTimer if @idleTimer
|
|
373
397
|
clearTimeout @dataReceivedTimer if @dataReceivedTimer
|
|
374
398
|
|
|
375
|
-
|
|
376
399
|
constructor: (hosts) ->
|
|
377
|
-
|
|
378
|
-
|
|
400
|
+
super hosts
|
|
401
|
+
if typeIsArray(hosts) and hosts.length > 0
|
|
402
|
+
@_hosts = hosts
|
|
379
403
|
else
|
|
380
|
-
@
|
|
381
|
-
@ssh2Client = require('ssh2').Client
|
|
404
|
+
@_hosts = [hosts]
|
|
405
|
+
@ssh2Client = require('ssh2').Client
|
|
406
|
+
|
|
382
407
|
@.on "newPrimmaryHost", @_nextPrimaryHost
|
|
383
|
-
|
|
384
|
-
|
|
408
|
+
|
|
409
|
+
@.on "data", (data) =>
|
|
385
410
|
@_onData( data )
|
|
411
|
+
|
|
386
412
|
@.on "stderrData", (data) =>
|
|
387
|
-
console.error data
|
|
388
|
-
|
|
389
|
-
@_allSessions = ""
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
_initiate: (callback)=>
|
|
393
|
-
@_removeEvents()
|
|
394
|
-
|
|
395
|
-
if typeof @sshObj.msg == 'function'
|
|
396
|
-
@.on "msg", @sshObj.msg.send
|
|
397
|
-
else
|
|
398
|
-
@.on "msg", ( message ) =>
|
|
399
|
-
console.log message
|
|
400
|
-
|
|
401
|
-
@_loadDefaults()
|
|
402
|
-
|
|
403
|
-
@.emit 'msg', "#{@sshObj.server.host}: initiate" if @sshObj.debug
|
|
404
|
-
|
|
405
|
-
#event handlers
|
|
406
|
-
@.on "keyboard-interactive", ( name, instructions, instructionsLang, prompts, finish ) =>
|
|
407
|
-
@.emit 'msg', "#{@sshObj.server.host}: Class.keyboard-interactive" if @sshObj.debug
|
|
408
|
-
if @sshObj.verbose
|
|
409
|
-
@.emit 'msg', "name: " + name
|
|
410
|
-
@.emit 'msg', "instructions: " + instructions
|
|
411
|
-
str = JSON.stringify(prompts, null, 4)
|
|
412
|
-
@.emit 'msg', "Prompts object: " + str
|
|
413
|
-
|
|
413
|
+
console.error data
|
|
414
|
+
|
|
414
415
|
@.on "error", (err, type, close = false, callback) =>
|
|
415
|
-
@.emit 'msg', "#{
|
|
416
|
+
@.emit 'msg', "Class.error: #{err}, #{type}" if @sshObj.debug
|
|
416
417
|
if ( err instanceof Error )
|
|
417
418
|
@.emit 'msg', "Error: " + err.message + ", Level: " + err.level
|
|
418
419
|
else
|
|
419
420
|
@.emit 'msg', "#{type} error: " + err
|
|
420
|
-
callback(err, type) if typeof callback == 'function'
|
|
421
|
-
@connection.end() if close
|
|
422
|
-
|
|
423
|
-
@.on "end", ( sessionText, sshObj ) =>
|
|
424
|
-
@.emit 'msg', "#{@sshObj.server.host}: Class.end" if @sshObj.debug
|
|
425
421
|
|
|
426
|
-
|
|
427
|
-
|
|
422
|
+
@_stream.close() if close
|
|
423
|
+
|
|
424
|
+
if @_hosts[0].server.tryKeyboard
|
|
425
|
+
@.on "keyboard-interactive", ( name, instructions, instructionsLang, prompts, finish ) =>
|
|
426
|
+
@.emit 'msg', "#{@sshObj.server.host}: Class.keyboard-interactive" if @sshObj.debug
|
|
427
|
+
if @sshObj.verbose
|
|
428
|
+
@.emit 'msg', "name: " + name
|
|
429
|
+
@.emit 'msg', "instructions: " + instructions
|
|
430
|
+
str = JSON.stringify(prompts, null, 4)
|
|
431
|
+
@.emit 'msg', "Prompts object: " + str
|
|
432
|
+
|
|
433
|
+
@_allSessions = ""
|
|
428
434
|
|
|
429
|
-
_loadDefaults: (callback) =>
|
|
430
435
|
|
|
431
|
-
|
|
436
|
+
_initiate: (action)=>
|
|
437
|
+
@.emit 'msg', "#{@sshObj.server.host}: initiate" if @sshObj.debug
|
|
438
|
+
|
|
439
|
+
@_loadDefaults()
|
|
440
|
+
#event handlers
|
|
441
|
+
|
|
442
|
+
if typeof action == 'function'
|
|
443
|
+
action()
|
|
444
|
+
|
|
445
|
+
_loadDefaults: () =>
|
|
446
|
+
|
|
447
|
+
if @sshObj.msg and @sshObj.msg.send and typeof @sshObj.msg.send == 'function'
|
|
448
|
+
@.on "msg", @sshObj.msg.send
|
|
449
|
+
else if @sshObj.msg and typeof @sshObj.msg == 'function'
|
|
450
|
+
@.on "msg", @sshObj.msg
|
|
451
|
+
else
|
|
452
|
+
@.on "msg", ( message ) =>
|
|
453
|
+
console.log message
|
|
454
|
+
|
|
432
455
|
@.emit 'msg', "#{@sshObj.server.host}: Load Defaults" if @sshObj.debug
|
|
433
456
|
@command = ""
|
|
434
457
|
@_buffer = ""
|
|
458
|
+
@sshObj.sshToNextHost = false
|
|
435
459
|
@sshObj.connectedMessage = "Connected" unless @sshObj.connectedMessage
|
|
436
460
|
@sshObj.readyMessage = "Ready" unless @sshObj.readyMessage
|
|
437
461
|
@sshObj.closedMessage = "Closed" unless @sshObj.closedMessage
|
|
@@ -466,7 +490,7 @@ class SSH2Shell extends Stream
|
|
|
466
490
|
@passwordPrompt = new RegExp(@sshObj.passPromptText+".*" + @sshObj.passwordPrompt + "\\s?$","i") unless @passwordPrompt
|
|
467
491
|
@passphrasePrompt = new RegExp(@sshObj.passPromptText+".*" + @sshObj.passphrasePrompt + "\\s?$","i") unless @passphrasePrompt
|
|
468
492
|
@standardPrompt = new RegExp("[" + @sshObj.standardPrompt + "]\\s?$") unless @standardPrompt
|
|
469
|
-
|
|
493
|
+
|
|
470
494
|
|
|
471
495
|
@sshObj.onCommandProcessing = @sshObj.onCommandProcessing ? ( command, response, sshObj, stream ) =>
|
|
472
496
|
|
|
@@ -477,10 +501,9 @@ class SSH2Shell extends Stream
|
|
|
477
501
|
response = response.replace(@command, "")
|
|
478
502
|
@.emit 'msg', "#{@sshObj.server.host}: Class.commandTimeout" if @sshObj.debug
|
|
479
503
|
@.emit 'msg', "#{@sshObj.server.host}: Timeout command: #{command} response: #{response}" if @sshObj.verbose
|
|
480
|
-
|
|
504
|
+
|
|
481
505
|
@.emit "error", "#{@sshObj.server.host}: Command timed out after #{@.idleTime/1000} seconds", "Timeout", true, (err, type)=>
|
|
482
|
-
|
|
483
|
-
|
|
506
|
+
@sshObj.sessionText += @_buffer
|
|
484
507
|
|
|
485
508
|
@.on "keyboard-interactive", @sshObj.onKeyboardInteractive if typeof @sshObj.onKeyboardInteractive == 'function'
|
|
486
509
|
@.on "error", @sshObj.onError if typeof @sshObj.onError == 'function'
|
|
@@ -494,8 +517,7 @@ class SSH2Shell extends Stream
|
|
|
494
517
|
@.emit 'msg', "#{@sshObj.server.host}: Host loaded" if @sshObj.verbose
|
|
495
518
|
@.emit 'msg', @sshObj if @sshObj.verbose
|
|
496
519
|
|
|
497
|
-
|
|
498
|
-
callback()
|
|
520
|
+
|
|
499
521
|
|
|
500
522
|
connect: (callback)=>
|
|
501
523
|
@_callback = callback if typeof callback == 'function'
|
|
@@ -547,10 +569,8 @@ class SSH2Shell extends Stream
|
|
|
547
569
|
|
|
548
570
|
@_primaryhostSessionText += @sshObj.sessionText+"\n"
|
|
549
571
|
@_allSessions += @_primaryhostSessionText
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
@.emit 'end', @_allSessions, @sshObj
|
|
553
|
-
|
|
572
|
+
if @_hosts.length == 0
|
|
573
|
+
@.emit 'end', @_allSessions, @sshObj
|
|
554
574
|
@_removeEvents()
|
|
555
575
|
|
|
556
576
|
|
|
@@ -565,11 +585,14 @@ class SSH2Shell extends Stream
|
|
|
565
585
|
|
|
566
586
|
@connection.on "close", (had_error) =>
|
|
567
587
|
@.emit 'msg', "#{@sshObj.server.host}: Connection.close" if @sshObj.debug
|
|
588
|
+
clearTimeout @idleTimer if @idleTimer
|
|
589
|
+
clearTimeout @dataReceivedTimer if @dataReceivedTimer
|
|
568
590
|
if had_error
|
|
569
591
|
@.emit "error", had_error, "Connection close"
|
|
570
592
|
else
|
|
571
593
|
@.emit 'msg', @sshObj.closedMessage
|
|
572
|
-
|
|
594
|
+
|
|
595
|
+
if @_hosts.length == 0
|
|
573
596
|
if typeof @_callback == 'function'
|
|
574
597
|
@_callback @_allSessions
|
|
575
598
|
else
|
|
@@ -19,15 +19,13 @@ var conParamsHost1 = {
|
|
|
19
19
|
userName: process.env.SERVER3_USER_NAME,
|
|
20
20
|
password: process.env.SERVER3_PASSWORD
|
|
21
21
|
},
|
|
22
|
-
debug =
|
|
22
|
+
debug = true,
|
|
23
23
|
verbose = false
|
|
24
24
|
|
|
25
25
|
//Host objects:
|
|
26
26
|
var host1 = {
|
|
27
27
|
server: conParamsHost1,
|
|
28
|
-
commands: [
|
|
29
|
-
"echo Host_1"
|
|
30
|
-
],
|
|
28
|
+
commands: ["echo Host_1"],
|
|
31
29
|
connectedMessage: "Connected to host1",
|
|
32
30
|
debug: debug,
|
|
33
31
|
verbose: verbose
|
|
@@ -35,18 +33,14 @@ var host1 = {
|
|
|
35
33
|
|
|
36
34
|
host2 = {
|
|
37
35
|
server: conParamsHost2,
|
|
38
|
-
commands: [
|
|
39
|
-
"echo Host_2"
|
|
40
|
-
],
|
|
36
|
+
commands: ["echo Host_2"],
|
|
41
37
|
debug: debug,
|
|
42
38
|
verbose: verbose
|
|
43
39
|
},
|
|
44
40
|
|
|
45
41
|
host3 = {
|
|
46
42
|
server: conParamsHost3,
|
|
47
|
-
commands: [
|
|
48
|
-
"echo Host_3"
|
|
49
|
-
],
|
|
43
|
+
commands: ["echo Host_3"],
|
|
50
44
|
debug: debug,
|
|
51
45
|
verbose: verbose
|
|
52
46
|
}
|
package/test/devtest.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
var dotenv = require('dotenv').config()
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var host = {
|
|
4
4
|
server: {
|
|
5
5
|
host: process.env.HOST,
|
|
6
6
|
port: process.env.PORT,
|
|
@@ -42,8 +42,10 @@ var sshObj = {
|
|
|
42
42
|
var SSH2Shell = require ('../lib/ssh2shell');
|
|
43
43
|
|
|
44
44
|
//run the commands in the shell session
|
|
45
|
-
var SSH = new SSH2Shell(
|
|
45
|
+
var SSH = new SSH2Shell(host);
|
|
46
|
+
|
|
46
47
|
SSH.on('end', function( sessionText, sshObj ){
|
|
47
|
-
this.emit('msg', sessionText);
|
|
48
|
+
this.emit('msg', "Session Text " + sessionText);
|
|
48
49
|
})
|
|
50
|
+
|
|
49
51
|
SSH.connect();
|
package/test/issue69.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
var dotenv = require('dotenv').config(),
|
|
2
|
-
debug =
|
|
3
|
-
verbose =
|
|
2
|
+
debug = true,
|
|
3
|
+
verbose = true
|
|
4
4
|
|
|
5
5
|
var host1 = {
|
|
6
|
-
server: {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
server: {
|
|
7
|
+
host: process.env.HOST,
|
|
8
|
+
port: process.env.PORT,
|
|
9
|
+
userName: process.env.USER_NAME,
|
|
10
|
+
password: process.env.PASSWORD
|
|
11
|
+
},
|
|
12
12
|
connectedMessage:'connected to host1',
|
|
13
13
|
debug: debug,
|
|
14
14
|
verbose: verbose
|
|
@@ -16,26 +16,26 @@ server: {
|
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
var host2 = {
|
|
19
|
-
server: {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
server: {
|
|
20
|
+
host: process.env.SERVER2_HOST,
|
|
21
|
+
port: process.env.PORT,
|
|
22
|
+
userName: process.env.SERVER2_USER_NAME,
|
|
23
|
+
password: process.env.SERVER2_PASSWORD
|
|
24
|
+
|
|
25
|
+
},
|
|
26
26
|
connectedMessage: 'connected to host2',
|
|
27
27
|
debug: debug,
|
|
28
28
|
verbose: verbose
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
var host3 = {
|
|
32
|
-
server: {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
server: {
|
|
33
|
+
host: process.env.SERVER3_HOST,
|
|
34
|
+
port: process.env.PORT,
|
|
35
|
+
userName: process.env.SERVER3_USER_NAME,
|
|
36
|
+
password: process.env.SERVER3_PASSWORD
|
|
37
|
+
|
|
38
|
+
},
|
|
39
39
|
commands: ['echo server3'],
|
|
40
40
|
connectedMessage:'connected to host3',
|
|
41
41
|
debug: debug,
|
|
@@ -47,11 +47,11 @@ host1.hosts = [host2];
|
|
|
47
47
|
|
|
48
48
|
var SSH2Shell = require ('../lib/ssh2shell'),
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
SSH = new SSH2Shell(host1);
|
|
51
51
|
|
|
52
52
|
var callback = function( sessionText ){
|
|
53
53
|
console.log ( "-----Callback session text:\n" + sessionText);
|
|
54
54
|
console.log ( "-----Callback end" );
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
SSH.connect(callback);
|