Shell Programming-Expect Free of Interaction

Keywords: Operation & Maintenance ssh ftp Linux shell

Expect overview

Expect is a tool based on tcl. Expect is a tool for automatic control and testing. It mainly solves the problem of non-interaction in shell script. It's helpful for large-scale Linux operations and maintenance
In the development of Linux operations and peacekeeping, we often need remote login server to operate. The login process is an interactive process, which may require input of yes/no, password and other information. To simulate this input, you can use Expect scripts.

Basic command

send: Sends a string to a process to simulate user input

  • This command can't automatically return and change lanes. Generally, r (return) is added.

expect

  • An internal command of expect that determines whether the last output contains the specified string or not and returns immediately if it does, otherwise it waits for a timeout to return.
  • Only the output of processes initiated by span can be captured

spawn: Start the process and track subsequent interaction information

Interaction: Stay interact ive when execution is complete and give control to the console

Timeout: Specifies a timeout time and continues to execute subsequent instructions when it expires

  • The unit is: seconds.
  • Timeout-1 is never timeout
  • By default, timeout is 10 seconds

exp_continue

  • Allow expect to continue executing instructions downward

send_user

  • Echo command, equivalent to echo

argv parameter array

  • Expect scripts can accept parameters passed from bash, which can be obtained using [lindex $argv n], n starting from 0, representing the first, second, and third parameters, respectively.

Expect scripts must end with an interact or expect eof, which is usually enough to perform automation tasks

  • Expect eof is waiting for the end sign. A command initiated by span produces an eof tag at the end, and expect eof is waiting for that tag.

Expect syntax

Single Branch Grammar

expect "password:" {send "mypassword\r";}

Multi-branch schema grammar

send command does not have the function of carriage return and lane change. Generally, r or n should be added.

expect "aaa" {send "AAA\r"}
expect "aaa" {send "AAA\r"}
expect "aaa" {send "AAA\r"}

As long as any of the aaa or bbb or ccc matches, exit the expect statement after executing the corresponding send statement

expect {
"aaa" {send "AAA\r"}
"bbb" {send "BBB\r"}
"ccc" {send "CCC\r"}
}

exp_continue means to continue matching later, and if aaa is matched, to continue matching bbb downward after the send statement is executed

expect {
"aaa" {send "AAA\r";exp_continue}
"bbb" {send "BBB\r";exp_continue}
"ccc" {send "CCC\r"}
}

- re parameter represents matching regular expression

Expect execution

Direct execution

SSH login
First landing
Normal login
Connection rejected, ssh not open, port number incorrect, or firewall restrictions
No connection address

#!/usr/bin/expect//Expect binary file path
#Timeout time
set timeout 20                  //20 seconds waiting time
log_file test.log                //log file
log_user 1                       //Log user
#Parameter passing in
set hostname [lindex $argv 0]        //Adding parameter 0, statistic variable and loading position 1 parameter
set password [lindex $argv 1]        //Append parameter 1, statistic variable and load position 2 parameter
#Tracking command
spawn ssh root@$hostname          //Tracking command
#Capturing information and matching non-interactive execution
expect {                                             //Capture prompt information
        "Connection refused" exit         //Discontinue after capturing rejected connection information
        "service not konwn" exit          //Capture the service to open information and exit
        "(yes/no)"                                // Capture yes or no parameters
        {send "yes\r";exp_continue}    //Enter yes and continue execution                
        "*password"                             // Capture parameters    
        {send "$password\r"}              //Enter password parameters              
}
#Delivery of control to the console
interact                                          //Control Transfer Console Man-made Input
[root@localhost ~]# ./expect.sh 192.168.109.132 baby520./
spawn ssh root@192.168.109.132
root@192.168.109.132's password: 
Last login: Thu Oct 10 16:52:48 2019 from 192.168.109.10
[root@localhost ~]#

Expect execution

Embedded execution

#!/bin/bash 
user=$1
password=$2
#Non-interactive commands outside expect
useradd $user
#Start interaction
expect <<-EOF                        //Expect start flag, standard input, equivalent to stdin
spawn passwd $user
expect "New*"
send "$password\r"
expect "again*"
send "$password\r"
expect eof;
EOF                                        //Expect closing statement, no blanks around EOF
[root@localhost ~]# ./expect.sh 192.168.109.132 baby520./
spawn ssh root@192.168.109.132
root@192.168.109.132's password: 
Last login: Thu Oct 10 17:38:16 2019 from 192.168.109.133
[root@localhost ~]# exit
//Logout
Connection to 192.168.109.132 closed.

Case 1

Create custom users, password customization

#!/bin/bash
username=$1
password=$2
useradd $username

/usr/bin/expect <<-EOF
spawn passwd $username
expect {
        "New*"
        {send "$password\r";exp_continue}
        "again*"
        {send "$password\r"}
}
EOF
[root@localhost ~]# ./tom.sh test2 123123
spawn passwd test2
//Change the password of user test2.
//New password:
//Invalid password: password less than 8 characters
//Re-enter the new password:
passwd: All authentication tokens have been successfully updated.

Case 2

Using expect to complete FTP login process

#!/usr/bin/expect -f
set timeout 20
spawn ftp 192.168.109.133
expect "Name*"
send "ftp\r"
expect "Password:*"
send "\r"
expect "ftp>*"
interact
expect eof

Thank you for reading!!!

Posted by Redneckheaven on Thu, 10 Oct 2019 06:18:15 -0700