一、流程

  通过前端上传要发布的压缩包,逻辑端获取后将压缩包分发到远程服务器上,并执行远程服务器上使用shell编写的发布脚本,实现代码发布。

二、前端文件上传代码

    
需要上传的包
*    
    
     

三、逻辑端

1、保存文件到指定位置

import osfpath = '/usr/local/zip/'file = request.files.get('package')                         # 获取压缩包filename = secure_filename(file.filename)                   # 确保文件格式正确if '.' in filename and filename.split('.',1)[1] == 'zip':   # 确保文件是*.zip格式    where = os.path.join(fpath,filename)    file.save(where)                                        # 保存为where指定的路径

2、将文件分发到远程服务器,并执行远程命令

app.config.from_object(RemoteHost)hosts = []for i in app.config:    if re.findall('HOST.',i):                               # 正则匹配HOST.类型        hosts.append(app.config.get(i))        # hosts格式为[['192.168.1.100', 22, 'root', '123456'],['192.168.1.101', 22, 'root', '123456'],...]def trans(where,filename):    ssh = paramiko.SSHClient()                              # 初始化ssh对象    comm = '/root/test.sh '+where                           # 远程服务器上要执行的命令     for i in hosts:        # 文件传输        tus = (i[0],i[1])        t = paramiko.Transport(tus)        t.connect(username=i[2],password=i[3])        sftp = paramiko.SFTPClient.from_transport(t)        # 初始化sftp对象        sftp.put(where,'/tmp'+filename)                     # 传输到'/tmp'下        t.close()                   # 执行远程命令        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 允许连接不在know_hosts文件中的主机(可选项)        ssh.connect(i[0],i[1],i[2],i[3],timeout=10)        stdin,stdout,stderr = ssh.exec_command(comm)        # 执行远程命令        ssh.close()

四、数据端

将前端获取的一些其他数据保存到数据库

data = dict((k,v[0]) for k,v in dict(request.form).items()) # message, key, projectkey = data.pop('key')data['update_persion'] = session.get('name')                # 添加执行人data['package'] = filename                                  # 添加上传的包名conditions = [ "%s='%s'" %  (k,v) for k,v in data.items()]if key == 'abcde':                                          # 许可码正确就执行操作    try:          trans(where,filename)        db.add('code',conditions)                           # 写入数据库        return render_template('/code/code.html',result='更新成功!',role = role)    except Exception, e:        errmsg = '失败信息 error: '+str(e)        return render_template('/code/code.html',result=errmsg,role = role)else:    return render_template('/code/code.html',result='许可码无效!',role = role)

效果图

wKioL1gz72aR3fhsAABK27kRcDw286.png

更新历史


使用基于python的pysvn模块,直接通过svn更新代码

def get_login(realm,username,may_save):    return True,'test','123456',True           # svn用户名:test ,密码:123456def svncheckout(url,where):    client = pysvn.Client()    client.callback_get_login = get_login      # 登录svn    try:        client.checkout(url,where)             # 将代码checkout到本地    except Exception,e:        print 'Error: {}'.format(e)

分发到远程服务器的方法

1、通过遍历所有的文件

def dirlist(where):      filelist =  os.listdir(where)        for filename in filelist:          filepath = os.path.join(where, filename)          if os.path.isdir(filepath):              dirlist(filepath)          else:              allfile.append(filepath)      return allfile

2、直接压缩

def zip_dir(dirname,zipfilename):    filelist = []    if os.path.isfile(dirname):        filelist.append(dirname)    else :        for root, dirs, files in os.walk(dirname):            for name in files:                filelist.append(os.path.join(root, name))                    zf = zipfile.ZipFile(zipfilename, "w", zipfile.zlib.DEFLATED)    for tar in filelist:        arcname = tar[len(dirname):]        #print arcname        zf.write(tar,arcname)    zf.close()

使用zip方法传输的逻辑端处理方法

@app.route('/code/',methods=['GET','POST'])@login_request.login_requestdef code():    role = session.get('role')    if request.method=='GET':        return render_template('/code/code.html',role=role)    else:        data = dict((k,v[0]) for k,v in dict(request.form).items()) # message, key, project        print data        key = data.pop('key')        project = data['project']        data['update_persion'] = session.get('name')        conditions = [ "%s='%s'" %  (k,v) for k,v in data.items()]        if key == 'abcde' and data['project']:            try:                localtime = time.strftime('-%Y-%m-%d-%H:%M:%S')                project_name = project+localtime # 例如: 'ecg-2016-12-07-10:00:37'                zip_name = project_name+'.zip'                print zip_name                svncheckout(url[project],path+project_name) # co 到 '/data/ecg-2016-12-07-10:00:37'                os.chdir(path) # cd '/data'                zip_dir(project_name,zip_name)                for host in hosts:                    trans(zip_name,path+zip_name,host)                    exec_comm('/bin/bash /root/update.sh '+zip_name,host)                     db.add('code',conditions)                return json.dumps({'code':0,'result':'更新成功'})            except Exception, e:                errmsg = '失败信息 error: '+str(e)                return json.dumps({'code':1,'errmsg':errmsg})        elif not data['project']:            return json.dumps({'code':1,'errmsg':errmsg})        else:            errmsg = '许可码无效!'            return json.dumps({'code':1,'errmsg':errmsg})

前端效果图

免去了上传zip压缩包的步骤