Skip to content

How to Learn The Basics of Expect Script?

learn expect script

In the previous article, we have explained the basics of bash scripts that can make the work of a sysadmin more efficient. However, I see a shortcoming in the bash script. I find it difficult to automate using the bash script for interactive applications such as telnet, FTP, SSH, and others. After searching the internet, I found a solution to my problem which is to use the Expect script.

 

Problem

How to learn the basics of expect script?

 

Solution

Expect script is a programming language created by Don Libes in 1990 and is a derivative of the Tcl/Tk language. This programming language is used to automate interaction services such as telnet, ssh, FTP, etc. where the bash language is not capable or difficult to do so. To install the Expect script, use the following commands:

RedHat Distribution (CentOS, AlmaLinux, RockyLinux)

yum install -y expect

 

Ubuntu/Debian

apt-get install -y expect

 

OpenSUSE

zypper install -y expect

 

Just like a bash script, expect also uses a shebang written at the very top of a script and written as follows:

#!/usr/bin/expect

 

We recommend it to write #!/usr/bin/env expect to make it more portable and can be used across different UNIXs. For file extensions used for expect scripts, expect uses the .exp extension. In the table below, there are some commands in the expect script that are often used:

Commands in Expect

Command Short Explanation
spawn Creates a new process by running a given program. This is usually given at the start of the script to begin the process. Examples given earlier were "spawn ssh [email protected] or spawn ftp host". You are starting up (connecting to) the process you want to interact with.
expect The expect command will wait until one of the patterns given matches the output of a spawned process, a specified time period has passed, or an end-of-file is seen.
send Sends string to the current process. Usually this is a command followed by a return character (\r) like send "yourpassword\r". You use the expect command to match the output and decide what to send the current process.
interact This will give control of the current process over to the user for interaction. Great if the script can get a person to a certain point and then they have to take over. When you get to the point you want to interact with just put in the word "interact".
send_user Output that gets sent to stdout. This is used for sending message to the screen as the script runs. It is great for user feedback, banners, and for generating error messages.
log_user By default all process output shows up on stdout (your screen). To stop this you can set log_user to 0 "log_user 0" at the top of your script. To turn things back on just set it back to "log_user 1" or remove the line.
exp_internal This is essentially the Expect debug log mode. Turn this on by setting this to 1 like "exp_internal 1". It will show you everything expect sees and how it is trying to match it. This is invaluable for when you think your script should be working, but it is not.
set Set is just how to set variables in Tcl and thus Expect. Things like setting the global timeout value from 10 seconds to 20 with "set timeout 20". Another would be grabbing a username from the command line of the expect script and setting it to a variable "set username [lindex $argv 0]".
close Closes the connection to the current process.

 

Below is the Expect script format that is commonly used:

#!/usr/bin/expect
spawn service [email protected]_server
expect "last character of the command"
send "your command\r"

 

Usually, I use this Expect script to access a Linux server and retrieve or run commands on another Linux server. There is a very helpful tip for using the Expect script. We need to know what the last character appears after we press the enter key. For example, I want to access a server with IP 192.168.56.217 with SSH protocol with root password qwerty, then we type ssh [email protected] and press the enter key then if we see there will display password: after we press enter key as in the image below:

Using SSH

So, based on the above image, we can create a simple expect script. For the spawn write, we can write spawn ssh [email protected] For the expect part, we can write Password: or we can write briefly as *: (remember, after the colon, there must be a space). And for the send part, we can write the password. So, the Expect script will be:

#!/usr/bin/expect -f

spawn ssh [email protected]
expect "*: "
send "qwerty\r"
expect "# "
interact

 

The -f flag in the shebang prefaces a file from which to read commands from. Don’t forget to make the file executable. After that, try running the file and it should look like the image below:

Create an Expect script for the first time

The following are examples of the use of Expect scripts:

1. FTP using Expect script

If we want to use the expect script to send a file (test.sh) using the FTP service to the IP 192.168.56.227 then we can use the example expect script below:

#!/usr/bin/expect -f
spawn ftp 192.168.56.227
set timeout 7
expect "): "
send "sysadmin\r"
expect "Password:"
send "qwerty\r"
expect "ftp> "
send "put test.sh\r"
expect "ftp> "
send "by\r"

 

Run the file and it should be like in the image below:

Using the Expect script for ftp

 

2. Telnet using Expect script

We can use expect script to telnet to server with IP 192.168.56.220 and here is the script:

#!/usr/bin/expect -f
spawn telnet 192.168.56.220
expect "login"
send "qwerty\r"
expect "Password:"
send "qwerty\r"
expect "$ "
send "free -m\r"
expect "$ "
send "exit\r"

 

Run the file and it should be like in the image below:

Using the Expect script for telnet

 

3. SSH using Expect script

Like in the above example, we can use Expect script for SSH. For example my server has IP 192.168.56.227 and I create Expect script to run the command free -m in the server. So here is the script:

#!/usr/bin/expect -f

spawn ssh [email protected]
set timeout 5
expect "Password: "
send "qwerty\r"
expect "*# "
send "free -m\r"
expect "*# "
send "exit\r"

 

Run the file and it should be like in the image below:

Using expect script for SSH

I recommend using the expect script for SSH to the server that is accessed using SSH and we should not use the expect script to access the server that was first accessed using SSH because it will usually look like the image below because it will be difficult for us to create the script:

Access to the server for the first time using SSH

 

Expect can also use arguments. So if we want to use arguments in the expect script, then here is an example expect script that uses arguments:

#!/usr/bin/env expect

if {[llength $argv] != 2} {
      puts "Script for Telnet"
      puts "Usage: $argv0 username password\n"
            exit 1
}

set USER_NAME [lindex $argv 0]
set PASS [lindex $argv 1]
spawn ssh [email protected]
expect "Password: "
send "$USER_NAME\r"
expect "Password:"
send "$PASS\r"
expect "*# "
send "free -m\r"
expect "*# "
send "exit\r"

 

Run the file and it should be like in the image below:

Expect with argument

Expect can send escape characters using ASCII characters in the Oct section, as shown in the table below:

ASCII table

For example, if we want to create an expect script that can send CTRL-D after sending commands to see free memory on a remote server, here is an example expect script:

#!/usr/bin/expect -f

spawn ssh [email protected]
set timeout 5
expect "Password: "
send "qwerty\r"
expect "*# "
send "free -m\r"
expect "]# "
send "\004\r"

 

Run the file and it should be like in the image below:

Using escape character in Expect

 

Note

If anyone asks why should use the expect script only to run commands on another Linux server while we can use the command:

ssh [email protected] 'free -m'

 

then I can only answer that expect can not only run commands on other Linux servers but there are other functions that we can use one of which is to send ASCII characters on other servers and there are many other uses in expect that we can explore.

 

References

Print Friendly, PDF & Email
Tags:

Leave a Reply

Your email address will not be published. Required fields are marked *