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.
EXAMPLES
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 "myserver.com"
spawn ssh "$user\@server"
The above would spawn the ssh process and submit the user and server, so essentially like entering ssh [email protected]
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.spawn(command, args=[], timeout=30, maxread=2000,searchwindowsize=None, logfile=None, cwd=None, env=None, ignore_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 Linuxaria.com 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 192.168.10.73 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 stdout: 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 [email protected]') fout=file('mylog.txt','w') child.logfile=fout #child.logfile=sys.stdout child.expect("password:") child.sendline("my_password") child.expect('$') child.sendline('ls /home') child.expect('$') child.sendline('date') child.expect('$')
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.EOF, pexpect.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 do_some_other_thing() 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 [email protected]') 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:
before: [email protected]'s after: password:
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
Example:
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 (hostname, username, password) #create a ssh session s.sendline ('uptime') # send command uptime to execute on target machine. s.prompt() print s.before s.sendline ('ls -l') s.prompt() print s.before s.sendline ('df') s.prompt() print s.before s.logout() except pxssh.ExceptionPxssh, e: print "pxssh failed on login." print str(e)
Automated FTP operation
In this example, we will log on the ftp server 192.168.10.119, and download a file called syslog.2
from __future__ import unicode_literals #Use unicode coding import pexpect import sys child=pexpect.spawnu('ftp 192.168.10.119') child.expect('(?i)name .*: ') #(?i) means case insensitive child.sendline('frank') child.expect('(?i)password') 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> ') sys.stdout.write(child.before) sys.stdout.write(child.after) sys.stdout.flush() child.interact() child.sendline('bye') child.close()
Reference
https://gist.github.com/Fluidbyte/6294378