这里以 tornado 框架为例,由于文件大小不确定,也许会非常大,所以使用异步回调的方式。上代码:
import re
import tornado
import sys
import subprocess
reload(sys)
sys.setdefaultencoding('utf8')
CURRENT_DUMP = {}
class FileHandler():
executor = ThreadPoolExecutor(20)
@tornado.web.asynchronous
@tornado.gen.engine
def get(self, param): #接收get请求
callback = self.get_argument("callback", "callback")
# 拉取文件
if (param == 'filepull'):
file_id = self.get_argument("file_id ", "")
# 校验用户操作文件的权限
# ...
# 把此次同步记录到log里
log_id = self.addLog(user_id, file_id, 'pull', '未开始', '')
if log_id == 0:
self.write('%s({"status":"创建日志失败"})' % callback)
else:
tornado.ioloop.IOLoop.instance().add_callback(self.filepull_impl, log_id)
self.write('%s({"status":"已加入到队列,请稍后查看日志","log_id":%d})' % (callback,task_id))
def addLog(self, ...):
# 日志存入sql数据库,并返回log_id
return log_id
# 开始拉取文件,并记录日志
def filepull_impl(self, log_id):
try:
# update 日志的状态为:执行中 ...
cmd = ' -avzp /test [email protected]::home/ ' # rsync命令
# -avzP --delete --password-file=/zyy/rsync-pc.passwd /zyy/test/* rsync://[email protected]:39001/zyytest
status, result = self.rsync_exec(cmd)
if status:
# 修改日志状态为:'拉取成功',执行结果:'执行成功,总文件大小:%s' % result
else:
# 修改日志状态为:'拉取失败',执行结果:'同步未完成:%s' % result
CURRENT_DUMP.pop(log_id)
except Exception, e:
# 修改日志状态为:'拉取失败',执行结果:'rsync error:%s' % e
# 拉取文件的具体实现
def rsync_exec(self, cmd):
cmd = "/usr/bin/rsync %s " % (cmd) #补充完整的rsync命令
#Popen 是 subprocess的核心,子进程的创建和管理都靠它处理。
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
# 等待自动结束
log_info=[]
# 检查进程是否终止,如果终止返回 returncode,否则返回 None。
while p.poll() == None:
log=p.stdout.readline().strip()
if log!="":
logging.info(log)
log_info.append(log)
CURRENT_DUMP[log_id].append(log)
# 等待子进程终止
p.wait()
log_info.extend(p.stdout.readlines()) #有时程序退出了,但是管道还有数据
str='\n'.join(log_info)
#执行完子进程状态,通常返回状态为0则表明它已经运行完毕,若值为负值 "-N",表明子进程被终。
if (p.returncode == 0):
# searchObj = re.search(r'total\s+size\s+is\s+(\d+)\s+speedup', str, re.M | re.I)
searchObj = re.search(r'total\s+size\s+is\s+([\d\,]+)\s+speedup', str, re.M | re.I)
if searchObj:
ll=searchObj.group(1).replace(',','')
try:
ll=int(ll)/1024
return True,'%dKb'%ll
except Exception,e:
return True,ll
return False,str
return False,str
参数的参考链接: