Expect script to collect logs in expert mode

I am trying to collect logs from a system in expert mode. Where I login to system and then change mode to expert mode and issue command to collect the log. I have a script which works but It waits for 30 mins even though log collection is complete before that. I have two issues with existing script.

  1. Since log collection takes really long time (sometimes about 30 minutes). Expect script does not wait for the prompt and exits at timeout value. So I don't get complete O/P. Hence, I added timeout value of 1800 secs. But this one forces script to wait for 30 mins. I would like to exit as soon as I am back on prompt. I tried using expect exact but need some help on this.

  2. How can I capture the current prompt itself as a variable and ask Expect to wait until it gets the prompt. or Make a prompt based on Username variable and hostname lie - USERNAME@SYSNAME##.

Here is my current code.

#!/usr/bin/expect -f
set timeout 5
set hostname [lindex $argv 0]
set username "admin"
set password "password"
set prompt "(>|#|\\\$) $"


spawn ssh $username@$hostname
expect {
    ".*key fingerprint" {send "yes\r"; exp_continue}
    "assword:" {send "$password\r"}
}

expect -re {\$prompt}

send "show product id\r"

expect -re "\nProduct ID: (.*)$prompt"
set PRDID $expect_out(1,string)

#send "hostname\r"
#expect -re "\n (.*)$prompt"
#set HNAME $expect_out(1,string)



expect -re $prompt
send "expert mode\r"
expect -re "assword:" {send "$PRDID\r"}
#send "$PRDID\r"
expect -re $prompt
#set output $expect_out(buffer);

send "show detailed logs\r"
set timeout 1800  ### To wait for 30 mins
## expect -re $prompt
expect -exact "(.*)## $"   ### I tried using expect exact. But it seems something wrong here.
###  expect -exact "\nSA@$HNAME##$"
send -- "\r"
send "exit\r"
#puts [open w] $expect_out(buffer);
expect eof
[root@se scripts]#

If it waits for the full 30 minutes, it means that expect does not see the string you are waiting for.

You are writing

expect -exact "(.*)## $"

which means that you are waiting for the string "(.*)## $" to appear somewhere. I don't think this is what you want to achieve.

You can use exact, if you know the exact sequence of characters. In your case, it seems to me more natural do do an anchored regular expression matching, to cope for variations in, say, whitespace, for example

exact -re {^.+@.+ *## *[$] *$}

Please see it only as a suggestion to start with. I don't know what's in your output in general, and you have to judge by yourself, how to write the regexp so that you don't accidentally catch a line in your logs which looks the same.

1 Like

This is what I am using now and it doesn't timeout now and I get complete logs in O/P.

        sleep 1
    expect {
        timeout {send "\r"; exp_continue}
        "SA@*## "
    }

Well, that it doesn't timeout, I can understand: You are executing exp_continue in the case of timeout, which means that you cancel the timeout and continue waiting.

Now to the case why it doesn't match. You are using a globbing match here, so the pattern should match whenever a line contains the string "PA@" and later in the same line "## ". My guess is that for whatever reason, such a line is not delivered.

After fixing the timeout issue, have a look at the $expect_out(buffer) whether you can find there the line you are looking for.

Appreciate your help rovf