Mohan pd.
Mohan pd. Author of The Coders Blog. Also a professional fullstack javascript developer working with various tech company and client around world.

Guide to expert, an awesome tool to automatically interact with applications that run in terminal

Sep 14, 2019 · 2 minutes Tool to automatically interact with applications that run in terminal
Guide to expert, an awesome tool to automatically interact with applications that run in terminal

Expect is an awesome tool to automatically interact with applications that run in terminal. Expect script allows us to start an application, then to monitor the stdout and to send messages to the stdin of that application when it detects a certain stdout pattern occurs.

Basic concept

Core functionality of Expect consists of: spawn, expect, and send.

  1. spawn : start the process that we want to monitor/control.
  2. expect : wait and only do the next action when other detect a certain pattern in the monitored stdout or timeout is triggered.
  3. send : send text to the stdin of the monitored application.

Other build-in variables and functions:

  • timeout : setting timeout for expect. (-1) means disabling timeout.
  • puts : write text to the interactive screen.
  • wait : wait until the monitored process stops.
  • sleep : sleep the expect script for a certain amount of time.
  • $argv : array of input parameters.
  • eof : the pattern that occurs when a spawn process is closed.
  • lindex : access array element.
  • interact: give user the interaction control.

Expect also provides the concept of global and local variables and functions:

  • The following pseudo-code defines function runcmd with three parameters: X , Y , Z.
  • Keyword global is used to access VAR from inside runcmd.
  • $X refers to variable X.
  • Line with # at the beginning indicates comments.
  • arg1 and arg2 capture input parameters.
set arg1 [lindex $argv 0]
set arg2 [lindex $argv 1]

set VAR "..."

# define function runcmd
proc runcmd{ X , Y , Z } {

    global VAR
    ...
    puts "X=$X"
}
# call function runcmd with X=A,Y=B,Z=C
runcmd A,B,C

Examples

The following function tries to access to a ssh server that requires to enter password and run a script in a certain directory. Script, directory, and server are input parameters of that function. In the main script, that function is called to stop tomcat service inside /opt/tomcat.

SET SSHPWD "xxxxxx"
#--------------------------------------------------------------------
# run cmd in directory of remote server 
#--------------------------------------------------------------------
proc runcmd { script , dir , server  } {

    global SSHPWD

    puts "------------------------------------------------------------"
    puts " run - $script - in - $dir - of - $server -"
    puts "------------------------------------------------------------"

    # never timeout
    set timeout -1 

    # login remote server
    spawn ssh $server
    expect "password:"
    send "$SSHPWD\r"

    # change to root
    expect   "\[[email protected]"  
    send "sudo -s\r"
    expect "[email protected]"
    
    # run cmd  
    send "cd $dir\r"
    send "pwd\r"
    send "\r"
    send "$script \r"
    send "\r"

    # logout    
    send "exit\r"
    send "exit\r"

    # connection is closed
    expect "closed\."
    
    puts "------------------------------------------------------------"
    puts " finish - $script -"
    puts "------------------------------------------------------------"

    sleep 10

}

runcmd "service tomcat7 stop" , "/opt/tomcat/" ,  "server"