Expect scripting language is used to feed input automatically to an interactive program. It is easy to learn compared to other scripting languages. Using expect script sysadmins and developers can automate redundant tasks easily. It works by expecting specific strings, and sending or responding strings accordingly.
Following three expect commands are used when automating any interactive processes.
- send – to send the strings to the process
- expect – wait for the specific string from the process
- spawn – to start the command
Make sure to install expect packages on your system, as it does not get installed by default. Once installed, you’ll see the expect interpreter as “/usr/bin/expect”. Generally, expect script files has .exp as extensions.
1. Expect “Hello World” Example
The following expect script is expecting the specific string “hello”. When it finds it (after user enters it), “world” string will be send as response.
#!/usr/bin/expect expect "hello" send "world"
2. Timeout On Expect String
By default, the expect timeout is 10 seconds. If you don’t enter anything for the expect command, it times out in 20 seconds. You can also change the timeout as shown below.
#!/usr/bin/expect set timeout 10 expect "hello" send "world"
3. Automate User Processes With Expect
With the help of expect, you can automate the user processes and get the expected output. For example, you might use this to simplify the project testing process by writing scripts for the test cases.
The below example does the addition program automation.
#!/usr/bin/expect set timeout 20 spawn "./addition.pl" expect "Enter the number1 :" { send "12\r" } expect "Enter the number2 :" { send "23\r" } interact
Execute this as shown below.
$ ./user_proc.exp spawn ./addition.pl Enter the number1 : 12 Enter the number2 : 23 Result : 35
In case, if you have written the code without interact command, then the script would exit immediately after sending the string “23\r”. Interact command does the control, hands over the job to the addition process, and produces the expected result.
4. Match and No Match Contents in $expect_out Variables
On the successful matching of string expect returns, but before that it stores the matched string in $expect_out(0,string). The string that are received prior plus the matched string are stored in $expect_out(buffer). The below example shows you the value of these two variable on match.
#!/usr/bin/expect set timeout 20 spawn "./hello.pl" expect "hello" send "no match : <$expect_out(buffer)> \n" send "match : <$expect_out(0,string)>\n" interact
The hello.pl program just prints only two lines as shown below.
#!/usr/bin/perl print "Perl program\n"; print "hello world\n";
Execute it as shown below.
$ ./match.exp spawn ./hello.pl Perl program hello world no match : <Perl program hello> match : <hello>
5. Automate SU login into Other User Accounts
Expect allows you to pass the password for the Linux login account from the program, instead of entering the password on the terminal. In the below program, su login is automated to login into desired accounts.
#!/usr/bin/expect set timeout 20 set user [lindex $argv 0] set password [lindex $argv 1] spawn su $user expect "Password:" send "$password\r"; interact
Execute the above expect program as shown below.
bala@localhost $ ./su.exp guest guest spawn su guest Password: guest@localhost $
After running the above script, it logged into the guest user account from bala user account.
6. SSH Login into Another Machine
The example expect program shown below automates the ssh login from one machine to another machine.
#!/usr/bin/expect set timeout 20 set ip [lindex $argv 0] set user [lindex $argv 1] set password [lindex $argv 2] spawn ssh "$user\@$ip" expect "Password:" send "$password\r"; interact
Execute the above expect program as shown below.
guest@host1 $ ./ssh.exp 192.168.1.2 root password spawn ssh root@192.168.1.2 Password: Last login: Sat Oct 9 04:11:35 2010 from host1.geetkstuff.com root@host2 #
Comments on this entry are closed.
You could also add one previous step to the SSH login for automated scripts: Test if remote key is already imported:
set timeout 5
expect “yes/no)?”
send “yes\r”
regards!
Sure wish I could still print these. Some good stuff that I often don’t have time to play with until later and then for get. When I printed them I could catch up on train or at home.
Thanks tho! Keep up the good work.
G
Something to keep in mind with these expect scripts using passwords is that anything typed on the command line goes into your history. So you could end up saving your password into your history file. Then others with root access can see these passwords. Hopefully if they have root access though they should be someone thats trusted. Still I don’t want ANYONE knowing my passwords 😉
@Scott, good point.. but there is a way around the History file. I don’t remember which option it is, but one of the HIST options will let you specify a space (literally hitting the space bar once) before the command and it won’t put it in the History file. I did this at a company where they had an appliance and refused to have the three of us all use the root account. So I got tired of them watching what I was doing.. I need to go back and look that one up.
@Brian, Interestingly enough I went to research this space method you mentioned and lo and behold, I was google routed right back to this website 🙂
http://www.thegeekstuff.com/2008/08/15-examples-to-master-linux-command-line-history/
Item #10
@Brian/@Scott
The HIST options is: “unset HISTFILE”
We can set it as an alias in .bashrc file
alias xx=’unset HISTFILE’
hello sir,
how can i install the expect packages? where i can get it?
The match.exp example didn’t work out on my computer.
The output is:
spawn ./hello.pl
Perl program
hello world
I guess it’s because the hello.pl is over too soon to give match.exp enough time to send…
After add a line of “;” to the hello.pl I can see the output exactly the same as yours.
the line added is <> sign…. it’s omitted….
How to send an exact string onto remote machine which contains metacharacters like $ where it is not set in the local script?
send “RELEASE=ls -l|grep -i $RELEASE_DATE”
Where in $RELEASE_DATE is not set in the script
For those who have trouble with the match.exp exemple like I did. Replace send “no match : \n” by puts stderr “no match : \n”.
It works for me.
Apparently this page doesn’t support message including any strings that can be interpreted as HTML !! so my previous message is 100% unundestandable.
Let me try it that way:
replace : send “no match : \ \n”
by : puts stderr “no match : \ \n”
Hope this time it will work
in the 4th example. i think u should use send_user command instead of just send. the perl program ends after printing stuff and you are sending some input to the process even after ending. i’m having some problems on aix, then figured out that send_user outputs to the user and not the process which spawned it.
Hi
I need to send a string with ” part of the srting. Problem send “test “dos” ” says its invalid. Could you help me
For script
#!/usr/bin/expect
expect “hello”
send “world”
I’m getting error
couldn’t read file “hello”: no such file or directory
expect.sh: line 3: send: command not found
Please help me to handle Warning Message
Password:
Warning: your password will expire in 4 days
my script automatically comes out after warning message encounters
send “show running-config\r”
expect -ex ” –More– ” {send ” “}
interact
I have this code which scrolls after expecting a ” –More– ” while running the show command. I want to put the expect code in a while loop so that it would loop whenever it finds ” –More– ”
I wrote it this way
while {1} {
expect -ex ” –More– ” {send ” “}
if {expect “#”} break else continue
}
Another way I used a sample from another website:
set running 1
while {$running > 0} {
expect {
-exact ” –More– ” {send — ” “}
“#” {set running 0}
}
I am not able to make this work. Is there a way you could help me in this.
Its simple and very good! 🙂 I learnt expect scripting basics from these examples.
Thanks
Hi Sir,
I want to execute the “sas.servers status” in directory /u01/app/sas/configuration/Lev1 by using su sas.
#!/usr/bin/expect
set timeout 20
set user [lindex $argv 0]
set password [lindex $argv 1]
spawn su $user
expect “Password:”
send “$password\r”;
send “cd /u01/app/sas/configuration/Lev1\r”;
spawn “./sas.servers status”
interact
——
Its not working could you please help.
Thanks,
Ravikumar Saikam.
Hi Ravi,
Try your command like this,
spawn su $user
expect “Password:”
send “$password\r”
expect “# ” # Expected prompt
send “/u01/app/sas/configuration/Lev1/sas.servers status”
interact
-Sunil
hi,
I want to take the username and password in the variable and use it for doing scp/ssh.Can you help me on the same?
for the ssh login….the script below do not timeout…..how to exit when password is wrong? and something like (wrong password)
#!/usr/bin/expect
set timeout 20
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
spawn ssh “$user\@$ip”
expect “Password:”
send “$password\r”;
interact
if you don’t want ot worry about:
expect “yes/no)?”
Just use:
spawn ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $user@$host
and you will not see that message anymore.
Hi,
I am trying to replace an ip in a file. That ‘sed’ command i am sending but throwing error.
#!/usr/bin/expect
spawn ssh -p 20222 root@10.43.38.242
expect “\*root@10.43.38.242’s password:”
send “root\r”
expect “#”
send “sed -i “s/.*host match.*/\10\.43\.38\.180\/g” config_bk.xml\r”
expect eof
error- extra characters after close-quote
while executing
“send “sed -i “s/.*host match.*/\10\.43\.38\.180\/g” config_bk.xml\r”
Could anyone please help me on this?
Thanks. This helps me a lot!
Hi,
For “5. Automate SU login into Other User Accounts”
We could see that the user password typed and can be seen. What if I want to type the unseen password for privacy, like “read -s password” command.
Thank you.
why aix is not allowing us to use metacharacters as password?
For those interested in obtaining the ‘expect’ package or information related thereto, here.
In the event that html may not be accepted within comments, you’ll find the expect home page at: expect.sourceforge.net
Hi,
How can we expand aliases inside expect script ?
Ex: I have defined below alias in my .bashrc file.
alias some_host=”ssh root@x.x.x.x”
How can i use “some_host” inside expect script ?
It is good stuff for beginner!
I am using your expect script to login the server and passing shutdown command. I have a separate file with list of 100 IPs and need your help to figure it out. How can I make the script to get each IP and login and pass the command to the servers.
#!/usr/bin/expect
set timeout 20
set user [lindex $argv 0]
set host [lindex $argv 1]
set password [lindex $argv 2]
spawn su $user
expect “Password:”
send “$password\r”;
expect “# ” # Expected prompt
send “sudo shutdown -h now”
expect “$password\r”;
interact
This saved my day! Thanks
simple explanation for the beginner
Hi,
I need to run a script to execute a scrpt on remote server. there are list of servers. I tried many ways but all are throwing error.
Can you please help me resolve this issue.
Thanks
Hi, Done a script and I run, it runs with another user gives me spawn / bin / bash error, and if I open a session with the same user but from another pc I get the same error
I got an error at the 2nd exemple:
couldn’t execute “./addition.pl”: no such file or directory
while executing
We are having issue while developing the program who can pass enter to start and enter to stop (in loop).
In developed logic, we are able to start the script and read first enter key(\n) after that it requires to sleep for 1 min and then pass enter to stop the process. But currently it is only passing first enter to start internal process in the script.
===============================
===========================
Expect guru, Please help here
Hi,
I am trying to login into a system where a utility(iris.cli.exe) requires to login. I want to spawn iris_cli.exe -server=ip -username=username -password=password to login into the system. What should be command I use to login via script.