作者:wangxun
本文中将更进一步使用Tornado提供一个WEB界面,通过WEB界面操作即可实现批量命令执行、文件上传。
首先我们需要一个资料库来存放主机信息。本文中我们使用SQLite,我们建立一张表:myhost 表中创建四个栏位:ID、HOST、USER、PWD分别记录序号,主机名、主机登入用户名、登入密码。 SQL如下:
CREATE TABLE "myhost" ( "ID" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "HOST" TEXT(36), "USER" TEXT(36), "PWD" TEXT(36) )
Python:
# -*- coding=utf-8 -*- import sys reload(sys) sys.setdefaultencoding('utf-8') import tornado.web import tornado.httpserver import tornado.ioloop import tornado.httpclient import os.path,os,datetime import threading import sqlite3 import paramiko import urllib HTML = u"" def dbconn(sql): conn = sqlite3.connect("DB.db") conn.text_factory = str cur = conn.cursor() cur.execute(sql) conn.commit() result = cur.fetchall() cur.close() conn.close() return result class ssh(): def __init__(self,host,user,pwd,remotepath=None,localpath=None,cmd=None,TYPE=None,port=22): self.host = host #Hostname self.user = user #用户名 self.pwd = pwd #密码 self.remotepath = remotepath #远程路径,上传&下载文件时需要提供此参数 self.localpath = localpath #本地路径,上传&下载文件时需要提供此参数 self.port = port #ssh端口 self.cmd = cmd #需要在远程主机执行的命令,执行命令时需要提供此参数 self.type = TYPE #sftp操作类型,允许的值有两个:upload和download def ssh(self): #命令执行 ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(self.host,self.port,self.user,self.pwd,timeout=5) stdin, stdout, stderr = ssh.exec_command(self.cmd) return stdout.read() ssh.close() def sftp(self): #文件上传下载 t = paramiko.Transport((self.host,self.port)) t.connect(username = self.user, password = self.pwd) sftp = paramiko.SFTPClient.from_transport(t) if self.type=='upload': sftp.put(self.localpath,self.remotepath) elif self.type=='download': sftp.get(self.remotepath, self.localpath) else: raise NameError('TYPE object is invalid!') t.close() settings = { "static_path" : os.path.join(os.path.dirname(__file__), "static"), "template_path" : os.path.join(os.path.dirname(__file__), "templates"), "login_url": "/login", } class main(tornado.web.RequestHandler): def get(self): SerList = dbconn("select ID,HOST from myhost") if SerList: SerList = [(i[0],i[1]) for i in SerList] else: SerList = [] self.render("test.html",SerList = SerList) def post(self): global HTML cmd = self.get_argument('cmd',') argv = self.get_argument('argv',') TYPE = self.get_argument('TYPE',') filename = self.get_argument('localpath',') localpath = os.path.join(os.path.join(os.path.dirname(__file__),'files'),filename) remotepath = '%s/%s' % (self.get_argument('url','),filename) print remotepath,localpath HOST_LIST = dbconn("select HOST,USER,PWD from myhost WHERE int in (%s)" % argv[0:-1]) for i in HOST_LIST: t = execute(host = i[0],user = i[1],pwd = i[2],cmd = cmd,TYPE = TYPE,remotepath=remotepath,localpath=localpath) t.start() t.join() result = HTML HTML = u' self.write(result) class upload(tornado.web.RequestHandler): def post(self): upload_path=os.path.join(os.path.dirname(__file__),'files') file_metas=self.request.files['Filedata'] filename=file_metas[0]['filename'] filepath=os.path.join(upload_path,filename) with open(filepath,'wb') as up: up.write(file_metas[0]['body']) self.write('finished!') class execute(threading.Thread): #命令执行、文件上传下载任务并发执行。 def __init__(self,host,user,pwd,cmd=None,TYPE='CMD',remotepath=None,localpath=None): threading.Thread.__init__(self) self.host = host self.user = user self.pwd = pwd self.cmd = cmd self.TYPE = TYPE self.remotepath = remotepath self.localpath = localpath def run(self): global HTML try: if self.TYPE=='CMD': result = ssh(host=self.host,user=self.user,pwd=self.pwd,cmd=self.cmd).ssh() if not result:result=u' HTML = HTML + self.host + u':<br />' + result.strip() + u"<br />" elif self.TYPE=='UP': result = ssh(host=self.host,user=self.user,pwd=self.pwd,TYPE='upload',remotepath=self.remotepath,localpath=self.localpath).sftp() HTML = HTML + self.host + u' :Upload successfull!<br />' else: raise NameError('TYPE object is invalid!') except Exception as e: pass App = tornado.web.Application([ (r'/',main), (r'/upload',upload), ],**settings) if __name__ == "__main__": http_server=tornado.httpserver.HTTPServer(App) http_server.listen(80) tornado.ioloop.IOLoop.instance().start()
HTML模板(需要Jquery&jquery.uploadify)
<!DOCTYPE html> <html> <head> <link href="static/css/uploadify.css" rel="stylesheet"> <script src="http://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script> <script src="static/js/jquery.uploadify.min.js"></script> <script type="text/javascript"> (document).ready(function() {("#upload").uploadify({ 'swf': 'static/js/uploadify.swf', 'uploader': '/upload', 'cancelImg': 'static/js/uploadify-cancel.png', 'buttonText': '选择文件并上传', 'queueID': 'fileQueue', 'fileSizeLimit':'50MB', 'simUploadLimit' : '100', 'formData' : {'url':("#url").val()}, 'onUploadSuccess':function(file, data, response){ var argv='("#select2 option").each(function(){ argv += (this).val() + ','; }).post("/",{argv:argv, 'TYPE':'UP', 'url':("#url").val(), 'localpath':file.name},function(HTML){("#result").html(HTML)}) }, 'removeCompleted' : false, 'auto': true, 'multi': true }); }); </script> </head> <body> <table> <tr> <td> <select multiple style="width:100px;height:200px" id="select1" > {% for i in SerList %} <option value="{{ i[0] }}">{{ i[1] }}</option> {% end %} </select> </td> <td> <button id="add">>|</button><br /> <button id="alladd">>></button><br /> <button id="move">|<</button><br /> <button id="allmove"><<</button> </td> <td> <select multiple style="width:100px;height:200px" id="select2"> </select> </td> </tr> <table> <input type="file" id="upload" /> 文件上传至:<input type="text" id="url" value="/tmp" /> <div id="fileQueue"></div> 執行命令: <input type="text" id="cmd" /> <button id="sub">提交</button><br /> <br /> <div id="result"></div> </body> <script> ("#add").click(function(){ varoptions = ("#select1 option:selected")options.appendTo("#select2") }) ("#move").click(function(){ varoptions = ("#select2 option:selected")options.appendTo("#select1") }) ("#allmove").click(function(){ varoptions = ("#select2 option")options.appendTo("#select1") }) ("#alladd").click(function(){ varoptions = ("#select1 option")options.appendTo("#select2") }) ("#sub").click(function(){ var argv='("#select2 option").each(function(){ argv += (this).val() + ','; }).post("/",{argv:argv,cmd:("#cmd").val(),'TYPE':'CMD'},function(data){("#result").html(data)}) }) </script> </html>