TCL basic

First we talk about some basic TCL things we need to understand for this script.

lindex : [lindex $argv 0]

lrange list first lastreturns a list composed of the first through last entries in the list. If first is less than or equal to 0, it is treated as the first list element. If last is end or a value greater than the number of elements in the list, it is treated as the end. If first is greater than last then an empty list is returned.

llength – Count the number of elements in a list

Treats list as a list and returns a decimal string giving the number of elements in it.


   The result is the number of elements:
   % llength {a b c d e}
   % 5
Use “Expect” to automate the linux operation

First we install the package:

apt-get install expect

expect Basic
Spawn & Send

You can start a process with the spawn command.

For example, ssh or scp are great examples:

set user "myuser"
set server ""

spawn ssh "$user\@server"

The above would spawn the ssh process and submit the user and server, so essentially like entering ssh in the console.

The send command allows you to send something to the console.

Pexpect module

pexpect module is used to utilize expect in python.

The class spawn is the core class, and it is defined as:

class pexpect.spawncommandargs=[]timeout=30maxread=2000searchwindowsize=Nonelogfile=Nonecwd=Noneenv=Noneignore_sighup=True
  • maxread: maximum bytes can be read from terminal
  • serachwindowsize: string location in the cache.

First example, we are going to ssh into a Linux machine, then run a command.

!/usr/bin/expect -f
#From the script is licensed under GNU GPL version 2.0 or above 
# Expect script to give username, password and IP/port 
# to connect to a remote ssh server and execute command.
# This script needs five argument :
# username = Unix username on the remote machine
# password = Password of username you have provided.
# server = IP Address or hostname of the remote server.
# port = Port of the SSH server on the remote server, usually 22
# program = Complete path to the command you want to run
#As first thing we check to have 5 arguments:
if {[llength $argv] != 5} {
# We give a message so the user know our syntax:
puts "usage: ssh.exp username password server port program"
#We exit with return code = 1
exit 1
# Now we set variables in expect, note:  [lindex $argv 0] the first parameter, and so on.
set username [lindex $argv 0]
set password [lindex $argv 1]
set server [lindex $argv 2]
set port [lindex $argv 3]
set program [lindex $argv 4]
#The value of timeout must be an integral number of seconds. Normally timeouts are nonnegative, but the special case of -1 signifies that expect #should wait forever.
set timeout 60
# Now we can connect to the remote server/port with our username and password, the command spawn is used to execute another process:
spawn ssh -p $port $username@$server $program
match_max 100000
# Now we expect to have a request for password:
expect "*?assword:*"
# And we send our password:
send -- "$password\r"
# send blank line (\r) to make sure we get back to cli
send -- "\r"
#We have gave our "program" and now we expect that the remote server close the connection:
expect eof

Save it as expect_test.exp.

./expect.exp administrator password 22 ls

This will show the user administrator’s home folder content.

note: pexpect does not work well with bash shell symbols, such as > | or wildcard mask *.  We need to use another way:

shell_cmd = 'ls -l | grep LOG > logs.txt'
child = pexpect.spawn ('/bin/bash', ['-c', shell_cmd])
child.expect (pexpect.EOF)

To get the pexpect input and output info, we can use either stand output info, or log file:

Write it to Log file:
child = pexpect.spawn'some_command'fout = file'mylog.txt''w'child.logfile = fout

child = pexpect.spawn'some_command'child.logfile = sys.stdout

We are going to show a ssh login process:

import sys
import pexpect
child = pexpect.spawn('ssh administrator@')
child.sendline('ls /home')
expect methods

expect(pattern, timeout=-1, searchwindowsize=-1)

  • pattern can be string, or a list. When the pattern is a list, the return value is the first match item’s index. eg.
    child = pexpect.spawn("echo 'foobar'")
    print child.expect(['bar', 'foo', 'foobar'])The first match is foo, so the return value is 1
  • pexpect.EOF : means there is no matching pattern
  • pexpect.TIMEOUT: means the script timout

We can make use of the return value to generate further decision:

 index = p.expect(['good''bad'pexpect.EOFpexpect.TIMEOUT])
if index == 0    do_something()
elif index == 1    do_something_else()
elif index == 2    do_some_other_thing()
elif index == 3    do_something_completely_different()

Which also equals:

try   index = p.expect['good''bad']   if index == 0       do_something()
   elif index == 1       do_something_else()
except EOF 

except TIMEOUT   do_something_completely_different() 
property Before and after

The before saves the content before the matching pattern and the after saves the content and content after pattern.e.g.

import pexpect
import sys
child = pexpect.spawn'ssh root@'fout = file'mylog.txt''w'child.logfile = fout
child.expect["password"]child.sendline"980405"print "before"+child.before
print "after"+child.after

Result will be:

class pxssh

Three common used method:

  • .login(hostname, username, password) : create ssh session
  • .sendline(command)
  • .prompt() : wait for the system prompt, usually is used to wait for the end of a command
  • .logout() : disconnect the session


import pxssh
import getpass
try    s = pxssh.pxssh() #create a pxssh object s
    hostname = raw_input'hostname'    username = raw_input'username'    password = getpass.getpass'please input password'#get the password
    s.login hostnameusernamepassword#create a ssh session
    s.sendline 'uptime'# send command uptime to execute on target machine.
    print s.before 
    s.sendline 'ls -l'    s.prompt()
    print s.before
    s.sendline 'df'    s.prompt()
    print s.before
except pxssh.ExceptionPxsshe    print "pxssh failed on login."
    print stre 
Automated FTP operation

In this example, we will log on the ftp server, and download a file called syslog.2

from __future__ import unicode_literals   #Use unicode coding
import pexpect
import sys
child.expect('(?i)name .*: ') #(?i) means case insensitive
child.sendline('password_for_frank')        #pass the password
child.expect('ftp> ')
child.sendline('bin')                      #use bin transportation mode
child.expect('ftp> ')
child.sendline('get syslog.2')             #download a file called syslog.2
child.expect('ftp> ')