作者: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>
WEB化批量执行命令&文件上传