Cisco Support Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Announcements

Welcome to Cisco Support Community. We would love to have your feedback.

For an introduction to the new site, click here. And see here for current known issues.

New Member

Expect scripting issue

Hi All

I am in the process of creating an expect script to capture the output of show commands from various devices and output them as <name of the device>.<command>.txt

However, I am having the following issues:

  1. The "show commands" on the script are not always parsed correctly on the routers (for example the "show ip route" might be parsed as "how ip route" and therefore generate an error)
  2. The output file has the correct format but there is no output within the file

Could you please review and assist in the issues above?

#!/usr/bin/expect 
# Here, we specify all our commands in a list, that we will issue one
# by one at a later time.
set commands {
"show ip route"
"show ip int brief"
"show arp"
}
# Set the date.
set date [timestamp -format %C%y%m%d]
# This variable is for a file called *.txt that has the IP
# of all of the routers you are collecting information from.
set device_list [read [open "routers.txt"]]
# Specify password, as well as what we expect the routers'
# prompt to be.
set pass "*********"
set prompt "#"
# This command tells expect not to echo the output to the console.
exp_log_user 0
# We loop through each device in our list, one by one...
foreach device $device_list {
# Set each device's log file to be the name of the device...
set file_name "$device.txt"

# we initiate the SSH connection
spawn ssh $device -l *********


#If we see a message asking about the device's host key, accept it.
expect -re "Password:" {
exp_send "$pass\r"
}

#exp_send "terminal length 0\n"
foreach cmd $commands {
exp_send "terminal length 0\n"
expect -re $prompt {
exp_log_file -a $file_name.$cmd
exp_send "$cmd\r"
#exp_sleep 2
exp_log_file
}


}
#expect -re $prompt {
#send "term len 0\r"
#}


expect -re $prompt {
exp_send "logout\r"
}


# Turn off logging.
exp_log_file
}
close

Thanks

Pantelis      

2 ACCEPTED SOLUTIONS

Accepted Solutions
Cisco Employee

Re: Expect scripting issue

Maybe it's a latency issue.  Try adding:

expect -re $prompt

Right before term len 0 is sent.

New Member

Expect scripting issue

Hi,

I tried your code and it appears like the host #1 is used to connect to the host #2. BUT it only appears like it because:

#

In reality the connection to host #2 does not originate from the host #1 but from the host you are running the script from.

To clarify, IOS doesn't have a command named "spawn"... so the command would simply fail if you were trying to connect to the host #2 from host #1 using that command.

The code you supplied works for me, all I did was to change the username and password, the code successfully creates files for both the devices I had in the txt-file for the supplied show-commands.

If your experiences differ from mine, I'd next check that you are running the latest versions of expect etc.

22 REPLIES
Cisco Employee

Expect scripting issue

By the time you start logging, you've already seen the output you want.  What about:

send "term len 0\r"

expect -re $prompt

foreach cmd $commands {

    exp_log_file -a $file_name.$cmd

    send "$cmd\r"

    expect -re $prompt

    exp_log_file

}

New Member

Re: Expect scripting issue

Thanks Joseph

It is now logging per file. However it seems that the name of the file and the actual output are not the same. For example, the output ".show in int brief"  ill display the "show ip route" instead

show arp file has the "show ip int brief" output

show ip int brief has the "show ip route" output

show ip route has a "term len 0" entry

Also again once of the commands was not properly parsed to the router

how ip int brief

               ^

% Invalid input detected at '^' marker.

Cisco Employee

Re: Expect scripting issue

Try this instead:

match_max [expr 32 * 1024]

foreach cmd $commands {

    send "$cmd\r"

    expect -re $prompt

    set output $expect_out(buffer)

    set fd [open $filename.$cmd w]

    puts $fd $output

    close $fd

}

New Member

Re: Expect scripting issue

exactly the same result

Cisco Employee

Expect scripting issue

I am testing it locally, and it works fine for me.  Maybe there's an issue with your prompt pattern.  Try changing your prompt to:

set prompt {([#>]) ?$}

New Member

Re: Expect scripting issue

Did that but still no luck. The device I am quering is a Cisco CISCO2911/K9 with Version 15.1(3)T. No high cpu on the device either

The latest script with the amendement is:

#!/usr/bin/expect

# Here, we specify all our commands in a list, that we will issue one

# by one at a later time.

set commands {

"show ip route"

"show ip int brief"

"show arp"

}

# Set the date.

set date [timestamp -format %C%y%m%d]

# This variable is for a file called routers.txt that has the hostname/IP

# of all of the routers you are collecting information from.tepad

set device_list [read [open "routers.txt"]]

# Specify password, as well as what we expect the routers'

# prompt to be.

set pass "******"

#set prompt "#"

set prompt {([#>]) ?$}

# This command tells expect not to echo the output to the console.

exp_log_user 0

# We loop through each device in our list, one by one...

foreach device $device_list {

# Set each device's log file to be the name of the device...

set file_name "$device"

# we initiate the SSH connection

spawn ssh $device -l *****

#If we see a message asking about the device's host key, accept it.

expect -re "Password:" {

exp_send "$pass\r"

}

# We log our output from each router to its specified file.

#exp_log_file -a $file_name.$date

# Loop through each command that we specified earlier.

send "term len 0\r"

expect -re $prompt

#foreach cmd $commands {

#   exp_log_file -a $file_name.$date.$cmd.txt

#   send "$cmd\r"

#   expect -re $prompt

#   exp_sleep 2

#   exp_log_file

#}

match_max [expr 32 * 1024]

foreach cmd $commands {

    send "$cmd\r"

    expect -re $prompt

    set output $expect_out(buffer)

    set fd [open $file_name.$cmd w]

    puts $fd $output

    close $fd

}

expect -re $prompt {

exp_send "logout\r"

}

# Turn off logging.

exp_log_file

}


one of the output file is:

show arp

how ip int brief

               ^

% Invalid input detected at '^' marker.

#


Cisco Employee

Expect scripting issue

Here's what I'm using.  I have log_user on just to make sure things are going okay.

#!/usr/bin/expect

# Here, we specify all our commands in a list, that we will issue one

# by one at a later time.

set commands [list "show ip route" "show ip int brief" "show arp"]

# Set the date.

set date [timestamp -format %C%y%m%d]

# This variable is for a file called routers.txt that has the hostname/IP

# of all of the routers you are collecting information from.tepad

set device_list [read [open "routers.txt"]]

# Specify the username and password, as well as what we expect the routers'

# prompt to be.

set pass "******"

#set prompt "#"

set prompt {([#>]) ?$}

# This command tells expect not to echo the output to the console.

log_user 1

# We loop through each device in our list, one by one...

foreach device $device_list {

# Set each device's log file to be the name of the device...

    set file_name $device

# we initiate the SSH connection

    eval spawn ssh $device -l *****

    match_max [expr 32 * 1024]

#If we see a message asking about the device's host key, accept it.

    interact -o -nobuffer -re "assword: $" return

    send "$pass\r"

# We log our output from each router to its specified file.

#exp_log_file -a $file_name.$date

# Loop through each command that we specified earlier.

    send "term len 0\r"

    expect -re $prompt

    foreach cmd $commands {

        send "$cmd\r"

        expect -re $prompt

        set output $expect_out(buffer)

        set fd [open $file_name.$cmd w]

        puts $fd $output

        close $fd

    }

    expect -re $prompt

    send "exit\r"

}

New Member

Re: Expect scripting issue

I am afraid this didn't work for me as well. The output from the putty session to the server is:

[root@*****tmp]# expect test.tcl

spawn ssh -l ****

Password:


hostname#show ip route

Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP

       D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area

       N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2

       E1 - OSPF external type 1, E2 - OSPF external type 2

       i - IS-IS, su - IS-IS summary, L1 - IS-IS level-1, L2 - IS-IS level-2

       ia - IS-IS inter area, * - candidate default, U - per-user static route

       o - ODR, P - periodic downloaded static route, H - NHRP, l - LISP

       + - replicated route, % - next hop override

hostname#how ip int brief

               ^

% Invalid input detected at '^' marker.

hostname#show arp

Protocol  Address          Age (min)  Hardware Addr   Type   Interface

As a result the output is not saved correctly to the files as mentioned above. for example the "hostname.show ip route" give the "exec motd". Strange that it works fine for you

Cisco Employee

Re: Expect scripting issue

Maybe it's a latency issue.  Try adding:

expect -re $prompt

Right before term len 0 is sent.

New Member

Re: Expect scripting issue

Hi Joseph

Thank you very much. This did the trick. At the moment if I add two or more devices under the router.txt the script uses the previous device to hop to the next. For example if my list has the following devices: 1.1.1.1 and 2.2.2.2 it will try to ssh to 2.2.2.2 from 1.1.1.1 as per below:

1.1.1.1#spawn ssh 2.2.2.2 -l

Is this possible to change this in order to ssh from the server I am running the program from everytime rather that the previous device?

Thanks

Pantelis

Cisco Employee

Expect scripting issue

The spawn looks like it is running from the device, but it is running from the expect host.  The log_user output is deceiving because the spawn is not fully closed.  In your main foreach loop, add the following at the end:

close

New Member

Expect scripting issue

Hi Joseph

There is already a "close" file within the foreeach loop.Code below:

  foreach cmd $commands {

        send "$cmd\r"

        expect -re $prompt

        set output $expect_out(buffer)

        set fd [open $file_name.$cmd w]

        puts $fd $output

        close $fd

    }

I've tried to add "close" as per below but I am getting errors

foreach cmd $commands {

send "$cmd\r"

expect -re $prompt

#remove zeros from the cmd filename

regsub -all {[ \r\t\n]+} $cmd "" correct_cmd

set output $expect_out(buffer)

set fd [open $file_name-$date-$correct_cmd.txt w]

puts $fd $output

close $fd

}

close

1.1.1.1#send: spawn id exp7 not open

    while executing

"send "$cmd\r""

    ("foreach" body line 2)

    invoked from within

"foreach cmd $commands {

        send "$cmd\r"

        expect -re $prompt

        #remove zeros from the cmd filename

        regsub -all {[ \r\t\n]+} ..."

    ("foreach" body line 20)

    invoked from within

"foreach device $device_list {

# Set each device's log file to be the name of the device...

    set file_name $device

# we initiate the SSH connection

..."

    (file "store_show_commands_switches.tcl" line 21)

Cisco Employee

Expect scripting issue

It looks like you've put the close in the wrong place.  Post your current script.

New Member

Expect scripting issue

Hi Joseph

Late code is:

#!/usr/bin/expect

# Here, we specify all our commands in a list, that we will issue one

# by one at a later time.

set commands [list "sh ip route summary" "show interfaces" "show arp" "sh ip ospf neighbor" "sh ip eigrp neighbor" "sh cdp neighbors"]

# Set the date.

set date [timestamp -format %C%y%m%d]

# This variable is for a file called switches.txt that has the hostname/IP

# of all of the routers you are collecting information from.tepad

set device_list [read [open "switches.txt"]]

# Specify password, as well as what we expect the switch

# prompt to be.

set pass "********"

#set prompt "#"

set prompt {([#>]) ?$}

# This command tells expect not to echo the output to the console.

#exp_log_user 0

#log_user 1

# We loop through each device in our list, one by one...

foreach device $device_list {

# Set each device's log file to be the name of the device...

set file_name $device

# we initiate the SSH connection

eval spawn ssh $device -l ******

match_max [expr 32 * 1024]

#If we see a message asking about the device's host key, accept it.

interact -o -nobuffer -re "assword: $" return

send "$pass\r"

# We log our output from each router to its specified file.

#exp_log_file -a $file_name.$date

# Loop through each command that we specified earlier.

expect -re $prompt

send "term len 0\r"

expect -re $prompt

foreach cmd $commands {

send "$cmd\r"

expect -re $prompt

#remove zeros from the cmd filename

regsub -all {[ \r\t\n]+} $cmd "" correct_cmd

set output $expect_out(buffer)

set fd [open $file_name-$date-$correct_cmd.txt w]

puts $fd $output

close $fd

}

expect -re $prompt

send "exit\r"

}

Thanks

Cisco Employee

Expect scripting issue

This is what I meant by adding the close:

#!/usr/bin/expect

# Here, we specify all our commands in a list, that we will issue one

# by one at a later time.

set commands [list "sh ip route summary" "show interfaces" "show arp" "sh ip ospf neighbor" "sh ip eigrp neighbor" "sh cdp neighbors"]

# Set the date.

set date [timestamp -format %C%y%m%d]

# This variable is for a file called switches.txt that has the hostname/IP

# of all of the routers you are collecting information from.tepad

set device_list [read [open "switches.txt"]]

# Specify password, as well as what we expect the switch

# prompt to be.

set pass "********"

#set prompt "#"

set prompt {([#>]) ?$}

# This command tells expect not to echo the output to the console.

#exp_log_user 0

#log_user 1

# We loop through each device in our list, one by one...

foreach device $device_list {

# Set each device's log file to be the name of the device...

set file_name $device

# we initiate the SSH connection

eval spawn ssh $device -l ******

match_max [expr 32 * 1024]

#If we see a message asking about the device's host key, accept it.

interact -o -nobuffer -re "assword: $" return

send "$pass\r"

# We log our output from each router to its specified file.

#exp_log_file -a $file_name.$date

# Loop through each command that we specified earlier.

expect -re $prompt

send "term len 0\r"

expect -re $prompt

foreach cmd $commands {

send "$cmd\r"

expect -re $prompt

#remove zeros from the cmd filename

regsub -all {[ \r\t\n]+} $cmd "" correct_cmd

set output $expect_out(buffer)

set fd [open $file_name-$date-$correct_cmd.txt w]

puts $fd $output

close $fd

}

expect -re $prompt

send "exit\r"

close

}

New Member

Expect scripting issue

same issue Joseph. The host is been used as a hop to ssh to the next one

#spawn ssh 10.x.xx.xx -l *****

New Member

Expect scripting issue

Hi, instead of close, do:

exp_close -i $spawn_id

exp_wait

New Member

Expect scripting issue

same issue

code has been amended to :

expect -re $prompt

send "exit\r"

exp_close -i $spawn_id

foreach cmd $commands {

send "$cmd\r"

expect -re $prompt

#remove zeros from the cmd filename

regsub -all {[ \r\t\n]+} $cmd "" correct_cmd

set output $expect_out(buffer)

set fd [open $file_name-$date-$correct_cmd.txt w]

puts $fd $output

close $fd

}

expect -re $prompt

send "exit\r"

exp_close -i $spawn_id

exp_wait

}

New Member

Expect scripting issue

Could you post the full version of the current code you have (without any sensivite information of course..)?

New Member

Expect scripting issue

Hi Toni

#!/usr/bin/expect

# Here, we specify all our commands in a list, that we will issue one

# by one at a later time.

set commands [list "sh ip route summary" "show interfaces" "show arp" "sh ip ospf neighbor" "sh ip eigrp neighbor" "sh cdp neighbors"]

# Set the date.

set date [timestamp -format %C%y%m%d]

# This variable is for a file called switches.txt that has the hostname/IP

# of all of the switches you are collecting information from.tepad

set device_list [read [open "switches.txt"]]

# Specify the username and password, as well as what we expect the routers'

# prompt to be.

set pass "*******"

#set prompt "#"

set prompt {([#>]) ?$}

# This command tells expect not to echo the output to the console.

#exp_log_user 0

#log_user 1

# We loop through each device in our list, one by one...

foreach device $device_list {

# Set each device's log file to be the name of the device...

set file_name $device

# we initiate the SSH connection

eval spawn ssh $device -l *****

match_max [expr 32 * 1024]

#If we see a message asking about the device's host key, accept it.

interact -o -nobuffer -re "assword: $" return

send "$pass\r"

# We log our output from each router to its specified file.

#exp_log_file -a $file_name.$date

# Loop through each command that we specified earlier.

expect -re $prompt

send "term len 0\r"

expect -re $prompt

foreach cmd $commands {

send "$cmd\r"

expect -re $prompt

#remove zeros from the cmd filename

regsub -all {[ \r\t\n]+} $cmd "" correct_cmd

set output $expect_out(buffer)

set fd [open $file_name-$date-$correct_cmd.txt w]

puts $fd $output

close $fd

}

expect -re $prompt

send "exit\r"

exp_close -i $spawn_id

exp_wait

}

Thanks

Pantelis

New Member

Expect scripting issue

Hi,

I tried your code and it appears like the host #1 is used to connect to the host #2. BUT it only appears like it because:

#

In reality the connection to host #2 does not originate from the host #1 but from the host you are running the script from.

To clarify, IOS doesn't have a command named "spawn"... so the command would simply fail if you were trying to connect to the host #2 from host #1 using that command.

The code you supplied works for me, all I did was to change the username and password, the code successfully creates files for both the devices I had in the txt-file for the supplied show-commands.

If your experiences differ from mine, I'd next check that you are running the latest versions of expect etc.

New Member

Expect scripting issue

Hi Toni

My only concern was the fact that I could see # when running the command. However, it does make sense as the IOS doesn't know what "spawn" is.

Thanks

2241
Views
0
Helpful
22
Replies
CreatePlease login to create content