Wednesday, January 10, 2018

Expect scripting best practices that I learned so far

I use expect scripting for logging into remote machine and do some stuff and get back result as success or failure.

Here are my learning's..
1. Always setup keys at local and remote machines for logging in.
2. Setup your own prompt text at remote shell (> or # or $)
3. Use wait method to get exit value

1. REGEX matching:
If the remote machine's prompt is color coded with "$" in the prompt string, then for effective regex pattern match use follwing,

set prompt ".*(>|%|#|\\$).*"

expect -re $prompt

2. To know exit status of last command/script, add the following at the end of expect script,

lassign [wait -nowait] pid spawnid os_error_flag value

if {$os_error_flag == 0} {
    puts "exit status: $value"
} else {
    puts "errno: $value"
}

exit $value

3. Syntax issues:
While using "if" statements curly braces has to be in same line,

if {condition} {
   statement
}

While using expect_out, "no space" in between arguments(comma and string),

$expect_out(0,string)

4. Here document
If you ever has to use nested spawn (login to a shell again login to another shell), think of using here document 

set command "/opt/bin/another_shell << EOF\n"
append command "execute_command\n"
append command "exit\n"
append command "EOF"

send "$command\n" 

5. Solving issue of expect skipping conditional "send" statement

So, I had a part of script like,

set prompt ".*(>|%|#|\\$).*"

expect -re $prompt

if {[info exists args(-a)]} {
send "$args(-c) $args(-a)\n"
} else {
send "$args(-c)\n"
}
expect -re $prompt

send "echo \"returncode :$?\"\n"

exit 0


In the above snippet, "send" statements inside "if .. else" did not execute always. it gets skipped so many times.

Fix1: Adding delay (sleep 1) above last expect statement.
This worked well. Anyway I wanted a more elegant solution.

Fix2: using "$?"

if {[info exists args(-a)]} {
send "$args(-c) $args(-a);echo $?\n"
} else {
send "$args(-c);echo $?\n"
}


expect -re "0\r\n$prompt"

exit 0

Here the issue is, expect need to look for two lines 
0
PROMPT#

So, I added "\r\n" after "0" then the prompt statement.

Python3 generator with recursion

Requirement: Generate sequential MAC addresses without any duplicates Input: integer Output: MAC Address Problem: Python2 does not support y...