我们学习了defer了实例,现在我们来写个基于paramiko的异步连接服务器的代码
#!/usr/bin/python
# -*- coding:cp936 -*-
from optparse import OptionParser
import paramiko
from twisted.internet import reactor, defer
parser = OptionParser(usage="%prog",version="version %prog 1.0.0")
parser.add_option("-f", "--files",action="store", type="string", dest="files", help="give the file's name")
(options, args) = parser.parse_args()
class UPDATE:
def __init__(self,hostname,username,password):
self.hostname = hostname
self.username = username
self.password = password
def update(self):
paramiko.util.log_to_file('/tmp/update.log')
s=paramiko.SSHClient()
s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
s.connect(hostname=self.hostname,username=self.username,password=self.password)
stdin,stdout,stderr=s.exec_command('cd /opt;tar xvf %s;' %options.files.split('/')[-1])
except Exception as e:
return '%s %s' %(self.hostname,e)
result=stdout.read()
s.close()
return '%s %s' %(self.hostname,result.strip('\n'))
def transport(self):
try:
t=paramiko.Transport((self.hostname,22))
# mykey = paramiko.RSAKey.from_private_key_file(rsakey,password='jastme') #use key
# t.connect(user,mykey)
t.connect(username=self.username,password=self.password)
sftp=paramiko.SFTPClient.from_transport(t)
sftp.put('/root/%s' %(options.files.split('/')[-1]),'/opt/%s' %(options.files.split('/')[-1]),confirm=True)
except Exception as e:
return '%s %s' %(self.hostname,e)
sftp.close()
return 'Copy files %s to %s Sucessed' %(options.files.split('/')[-1],self.hostname)
def updatedf(hostname,username,password):
d=defer.Deferred()
reactor.callLater(1,d.callback,UPDATE(hostname,username,password).update())
return d
def transportdf(hostname,username,password):
d=defer.Deferred()
reactor.callLater(1,d.callback,UPDATE(hostname,username,password).transport())
return d
def printData(x):
print x
if __name__ == '__main__':
serverlist=['192.168.16.102','192.168.16.209']
input=raw_input("1. 推送文件到服务器\n2. 更新\n3. 推送文件后更新\n")
if input == '1':
for server in serverlist:
dt=transportdf(server,'root','pass')
dt.addCallback(printData)
elif input == '2':
for server in serverlist:
du=updatedf(server,'root','pass')
du.addCallback(printData)
elif input == '3':
for server in serverlist:
dt=transportdf(server,'root','pass')
dt.addCallback(printData)
du=updatedf(server,'root','pass')
du.addCallback(printData)
reactor.callLater(1, reactor.stop)
reactor.run()
这是一个远程连接服务器,推送文件,使用命令解压包的程序(当然,我们还可以做很多扩展,可以把它写成一个自动化更新服务器的代码)。我们用callback来回调paramiko的函数。看过前面章节的朋友应该很容易读懂这个代码。
在这个代码,我们使用的try来避免抛出错误后代码异常退出的情况,利用execpt来返回错误,从而充分的利用callback来回调这些信息。