-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvty_runcmd.exp
executable file
·345 lines (293 loc) · 10.2 KB
/
vty_runcmd.exp
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
#!/usr/bin/expect --
##########################################################################
# vty_runcmd.exp
#
# This is an expect script that will connect to a device using ssh or
# telnet, then run the specified command. The output will either be
# written to an output file or printed to stdout.
#
# Created by Tim Evens ([email protected]), 5/2009
# Corrected by Sergio Zavala (sergio.zavala at sidetec.com.mx), 12/2010
#
# Copyright Tim Evens, 2009
#
# HISTORY:
# Tim Evens 5/21/09 Initial program created
# Sergio Zavala 12/26/10 Connection return code corrected
# Tim Evens 1/05/10 Connection validated
##########################################################################
#++++++++++++++++++++++++++
# Global vars
#++++++++++++++++++++++++++
set timeout 30
# below matches prompts such as "router#", "router>", "router$"
set prompt "\>\ *$|#\ *$|\\$\ *$"
#-----------------------------------------------
# Connect(method, prompt, host, user, password)
# This function will connect to a host using telnet or ssh.
#
# RETURNS:
# zero if successful
# 1 = timeout or invalid hostname or method
# 2 = invalid login
# 3 = timeout waiting for login
# 4 = connection failed to host during expect wait
# 9 = unknown error
#-----------------------------------------------
proc Connect {method host usr pw} {
set rval 0
set usr_chk 0
set pw_chk 0
set max_checks 4
global spawn_id
global timeout
global prompt
puts "Connecting using $method to $host as user $usr"
# see if we are using ssh
if { [string compare $method "ssh"] == 0 } {
set host "$usr@$host"
}
# Run command and get connected
set id [spawn $method $host]
if { $id <= 0 } {
puts "ERROR: Failed to connect to host\n"
set rval 1
} else {
puts "Using Process ID: $id"
}
# Start the expect/send process to login
expect {
# Below handles the username prompt
-nocase -re "name:|^login:" {
send "$usr\r"
incr usr_chk;
# continue with expect loop as long as we haven't hit this too many times
if { $usr_chk < $max_checks } {
exp_continue
} else {
set rval 2
puts "ERROR: Login retry failed. Invalid login username"
}
# Below handles the password prompt
} -nocase -re "word:" {
send "$pw\r"
incr pw_chk;
# continue with expect loop as long as we haven't hit this too many times
if { $pw_chk < $max_checks } {
exp_continue
} else {
set rval 2
puts "ERROR: Login retry failed. Invalid login password"
}
# Below handles the yes/no prompt when SSH first connects to a host
} -nocase -re "\(yes/no\)" {
send "yes\r"
exp_continue
# Below handles the normal prompt to detect when logged in
} -nocase -re "$prompt" {
puts "\nSUCCESS: Logged in and ready to send commands\n"
# Below is for expect timeout waiting for a
} timeout {
puts "ERROR: Connection timeout waiting for login prompt"
set rval 3
# Below is for when the connect is closed before finishing
} eof {
puts "ERROR: Connection to host failed: $expect_out(buffer)"
set rval 4
}
}
# return with error code
return $rval
}
# End of Connect ()
#-----------------------------------------------
# Usage()
# This function will print the usage
#-----------------------------------------------
proc Usage {} {
puts "Usage: vty_runcmd.exp <options>"
puts "\n"
puts "REQUIRED OPTIONS:"
puts " -h <hostname|ip> = hostname or ip address"
puts " -u <username> = username to login with"
puts " -p <password> = password for login"
puts "\n"
puts "Other OPTIONS:"
puts " -e <enable password> = Enable password"
puts " -t <seconds> = timeout in seconds"
puts " -m <ssh|telnet> = use either ssh or telnet, default telnet"
puts " -f <filename> = command file, defaults to STDIN"
puts "\n"
}
# End of Check_ARGS()
#-----------------------------------------------
# main()
#
# RETURNS:
# 0 if successful
# 1 if invalid arg passed
# 2 not enough args (required args not met)
#-----------------------------------------------
set rval 0
set hostname ""
set username ""
set password ""
set enable_pw ""
set cmdfile ""
set method "telnet"
# Loop through the command line args
for {set n 0} {$n < $argc} {incr n} {
set arg [lindex $argv $n]
# Check the args
if { [string compare $arg "-u"] == 0} {
if { $n < $n+1 } {
incr n
set username [lindex $argv $n]
} else {
set rval 1
puts "ERROR: Missing ARG for $arg\n"
}
} elseif { [string compare $arg "-p"] == 0} {
if { $n < $n+1 } {
incr n
set password [lindex $argv $n]
} else {
set rval 1
puts "ERROR: Missing ARG for $arg\n"
}
} elseif { [string compare $arg "-h"] == 0} {
if { $n < $n+1 } {
incr n
set hostname [lindex $argv $n]
} else {
set rval 1
puts "ERROR: Missing ARG for $arg\n"
}
} elseif { [string compare $arg "-m"] == 0} {
if { $n < $n+1 } {
incr n
set method [lindex $argv $n]
} else {
set rval 1
puts "ERROR: Missing ARG for $arg\n"
}
} elseif { [string compare $arg "-t"] == 0} {
if { $n < $n+1 } {
incr n
set timeout [lindex $argv $n]
} else {
set rval 1
puts "ERROR: Missing ARG for $arg\n"
}
} elseif { [string compare $arg "-f"] == 0} {
if { $n < $n+1 } {
incr n
set cmdfile [lindex $argv $n]
} else {
set rval 1
puts "ERROR: Missing ARG for $arg\n"
}
} elseif { [string compare $arg "-e"] == 0} {
if { $n < $n+1 } {
incr n
set enable_pw [lindex $argv $n]
} else {
set rval 1
puts "ERROR: Missing ARG for $arg\n"
}
}
}
# End of arg check
# make sure we found the amount of args expected
if { [llength $hostname] > 0 && [llength $method] > 0 &&
[llength $username] > 0 && [llength $password] > 0 } {
# Print out the args found
puts "hostname = $hostname, user = $username, pw = $password, method = $method"
} else {
set rval 2
puts "ERROR: Missing required args, must have -h, -u, -p\n"
Usage
}
# ------------------
# Now that we have the correct ARGS and we know what to do, lets proceed to
# connect, run the commands, then exit.
# ------------------
# make sure we have not encountered any errors
if { $rval <= 0 } {
if { [llength $cmdfile] <= 0 } {
puts "Enter the send text (type 'end' on last line to finish):"
expect_user -nocase -re "(.*)\nend\n"
set send_text $expect_out(1,string)
} else {
puts "Using $cmdfile for send text"
# set cmdfile_fd [open $cmdfile r]
if { [catch {set cmdfile_fd [open $cmdfile r]} err_msg] } {
puts stderr "Could not open $cmdfile for reading\n$err_msg"
exit 1
}
# read in the file info - warning there is a limit on the size
set send_text [read $cmdfile_fd 10000]
# close open file
close $cmdfile_fd
}
# connect and check return status before proceeding
if { [Connect "$method" "$hostname" "$username" "$password"] > 0 } {
# stop here, no need to print an error since Connect func does that
exit 1
}
# If we have an enable password, lets try to send it
if { [llength $enable_pw] > 0} {
puts "***Using enable mode"
send "enable\r"
expect {
-timeout 3
# Below handles the password prompt
-nocase -re "word:" {
send "$enable_pw\r"
exp_continue
# Below handles the normal prompt to detect when logged in
} -re "#\ *$" {
puts "--SUCCESS on enable mode--"
# Below is for expect timeout waiting for a
} timeout {
puts "ERROR: Enable password timeout"
set rval 3
# Below is for when the connect is closed before finishing
} eof {
puts "ERROR: Connection to host failed: $expect_out(buffer)"
set rval 4
}
}
}
# Loop through the send_text and send one line at a time
foreach line [split $send_text \n] {
# Make sure to exclude empty lines
if { [llength $line] > 0 } {
send "$line\r"
# Start the expect/send process to login
expect {
# Below handles the yes/no prompts
-nocase -re "\(yes/no\)" {
send "yes\r"
exp_continue
# Below handles the y/n prompts
} -nocase -re "\(yes/no\)" {
send "yes\r"
exp_continue
# Below handles the y/n prompts
} -nocase -re "--more--" {
send " "
exp_continue
# Below handles the normal prompt to detect when logged in
} -nocase -re "$prompt" {
puts "\n--SUCCESS for normal login prompt--\n"
}
}
}
}
# Now that we are done, send an exit
puts "*** Finished with script"
send "exit\r"
sleep 1
}
## END OF SCRIPT #############################################################