本脚本用于游戏服务器端的自动更新,主要流程就是把更新包和脚本的配置文件放在一个中心端center,分支机房client去中心端center下载更新包,并验证MD5,分支机房的游戏服务器根据自身需求通过rsync下载相应的更新包,游戏服务器通过解压、拷贝、验证部分重要文件的MD5来确保更新正确完成,目前此脚本已经用于更新本公司多款游戏,兼容windows、linux系统(根据自身需要更改相关路径),可以用页面去调用,已经写了post页面返回值。
#!/usr/bin/env Python # -*- coding: utf-8 -*- #Used update game path to server import os,re,sys,urllib,urllib2,hashlib,time,shutil,platform def post(status, type, info, err_info=""): post_url = args["post_url"] aid = args["aid"] data = {"aid": aid, "status": status, "type": type, "info": info} if err_info: data = {"aid": aid, "status": status, "type": type, "info": info, "err_info": err_info} print data f = urllib2.urlopen(url=post_url, data=urllib.urlencode(data)) def md5sum(file_name): if os.path.isfile(file_name): f = open(file_name,'rb') py_ver = sys.version[:3] if py_ver == "2.4": import md5 as hashlib else: import hashlib md5 = hashlib.md5(f.read()).hexdigest() f.close() return md5 else: return 0 def config(args,files): try: game = args["main_prefix"] url = "http://208.asktao.com/autoupdate/%s/config.ini" % game get = urllib.urlopen(url) aa = get.readlines() w = {} for i in aa: a = i.strip().split()[0] if "[" in a: x = a.strip("[]") w[x] = {} continue w[x][i.strip().split()[1].strip()] = i.strip().split()[0].strip() for key in w: if key == files: return w[key] except Exception,e: return 0 class down_start(): def work(self,args): aa = config(args,"path_md5") game = args["main_prefix"] if aa == 0: post(2,"read update config","Not find %s config file" % game) sys.exit() local = '/data/autoupdate/' url = "http://208.asktao.com/autoupdate/%s/" % game for f in aa: md5_r = f.strip().split()[0] pkg_name = f.strip().split()[1] get = urllib.urlopen(os.path.join(url,pkg_name)) status = get.getcode() if status == 200:#验证MD5,MD5错误的话重新下载一次,再次错误就提示失败,退出程序 urllib.urlretrieve(os.path.join(url,pkg_name),os.path.join(local,pkg_name),) md5_l = md5sum(os.path.join(local,pkg_name)) if md5_l == md5_r: post(1,"down",pkg_name) else: urllib.urlretrieve(os.path.join(url,pkg_name),os.path.join(local,pkg_name),) md5_l = md5sum(os.path.join(local,pkg_name)) if md5_l == md5_r: post(1,"down",pkg_name) else: post(2,"down",pkg_name,"Download %s,MD5 not right" % pkg_name) sys.exit() else: post(2,"down",pkg_name,"Not find %s path file" % pkg_name) # 检查rsync服务是否启动 while True: pid = os.popen("ps auxww | grep 'rsync --daemon' | grep -v grep").read() if not pid: getso("/usr/bin/rsync --daemon") continue break #全部完成,更新中心状态 post(1,"down","down_done") class sync_start(): def rsync(self,update_pkg,args): node_ip = args["node_ip"] game = args["main_prefix"] os_type = platform.system() if os_type == "Windows": local = "C:\\update\\" elif os_type == "Linux": local = "/home/update/tmp/" if not os.path.isdir(local): os.mkdir(local) for f in os.listdir(local): if os.path.isfile(f): os.remove(os.path.join(local,f)) elif os.path.isdir(f): shutil.rmtree(os.path.join(local,f)) aa = config(args,"path") if aa == 0: post(2,"read update config","Not find %s config file" % game) sys.exit() for f in aa: if update_pkg in f: md5_r = aa[f] pkg_name = f if os_type == "Windows": sync = "rsync -avz %s::update/*%s* /cygdrive/c/update/" % (node_ip,update_pkg) elif os_type == "Linux": sync = "rsync -avz %s::update/*%s* /home/update/tmp/" % (node_ip,update_pkg) result = os.popen(sync).readlines() md5_l = md5sum(os.path.join(local,pkg_name)) if md5_l == md5_r: post(1,"sync",pkg_name) else: if os_type == "Windows": sync = "rsync -avz %s::update/*%s* /cygdrive/c/update/" % (node_ip,update_pkg) elif os_type == "Linux": sync = "rsync -avz %s::update/*%s* /home/update/tmp/" % (node_ip,update_pkg) result = os.popen(sync).readlines() md5_l = md5sum(os.path.join(local,pkg_name)) if md5_l == md5_r: post(1,"sync",pkg_name) else: post(2,"rsync",pkg_name,"sync Error,%s not find or file's md5 wrong" % pkg_name) sys.exit() def work(self,args): update_pkg = args["update_pkg"].split(',') for i in range(len(update_pkg)): self.rsync(update_pkg[i],args) post(1,"sync","sync_done") class update_start(): def copy(self,src, dst): if os.path.isdir(src): base = os.path.basename(src) if os.path.exists(dst): dst = os.path.join(dst, base) if not os.path.exists(dst): os.makedirs(dst) names = os.listdir(src) for name in names: srcname = os.path.join(src, name) self.copy(srcname, dst) else: shutil.copy2(src, dst) def unrar(self,src,dst,args): os_type = platform.system() try: if not os.path.exists(dst) or not os.path.exists(src): raise Exception, "%s or %s not exist!" % (src, dst) if os_type == "Windows": os.system(r'C:\Progra~1\WinRAR\rar x -o+ -inul %s %s' % (src, dst)) elif os_type == "Linux": if os.path.splitext(src)[1] == ".tgz": os.system("tar -zxf %s -C %s" % (src, dst)) elif os.path.splitext(src)[1] == ".zip": os.system("unzip -oq %s -d %s" % (src, dst)) return 0 except Exception,e: return e def work(self,args): os_type = platform.system() if os_type == "Windows": update = "C:\\update\\" elif os_type == "Linux": update = "/home/update/tmp/" server_dir = {"tmcs":"C:\\Server\\","wd":"/home/asktao/"} server = server_dir[args["main_prefix"]] update_pkg = args["update_pkg"].split(',') game = args["main_prefix"] for i in range(len(update_pkg)): #####################解压更新包 for tgz in os.listdir(update): if update_pkg[i] in tgz: src = os.path.join(update,tgz) r = self.unrar(src,update,args) if r == 0: post(1,"update","%s unzip success" % src) else: post(2,"update",src,"unzip fail:%s" % r) #####################拷贝更新文件到游戏目录 ser_list = os.listdir(server) up_list = os.listdir(update) for dir in up_list: for line in ser_list: filepath = os.path.join(update,dir+"\\") serv = os.path.join(server,line+"\\") if dir in line: self.copy(filepath,serv) post(1,"update","%s files copy success" % line) #####################验证重要文件MD5 aa = config(args,"files") if aa == 0: post(2,"read update config","Not find %s config file" % game) sys.exit() for f in aa: md5_r = aa[f] pkg_name = f if os.path.exists(pkg_name): md5_s = md5sum(pkg_name) if md5_r == md5_s: post(1,"update","%s md5 Ok,update success" % pkg_name) else: post(2,"update","%s md5 Error,update fail" % pkg_name) sys.exit() shutil.rmtree(update) os.mkdir(update) post(1,"update","All_done") if __name__ == "__main__": args = {"pack":"auto_update","func1":"down_start","url":"http://208.2222.com/manage/auto_update","post_url":"http://192.168.50.209/reg.php","update_pkg":"up,up","node_ip":"192.168.50.208","main_prefix":"tmcs","aid":"123"} #down = down_start() #down.work(args) sync = sync_start() sync.work(args) update = update_start() update.work(args) '''''config.ini内容 [files]#需要验证MD5的重要文件绝对路径和MD5 15a6605156e29f68fdfd637e73a889d4 C:\Server\Line1\SAFlashPlayer.exe 15a6605156e29f68fdfd637e73a889d4 C:\Server\Line2\SAFlashPlayer.exe [path]#更新包名字和MD5 32fcb8932799aa553db13b5b9b41e5e9 auto.rar 32fcb8932799aa553db13b5b9b41e5e9 update.rar '''游戏服务器端自动更新脚本(python)
内容版权声明:除非注明,否则皆为本站原创文章。
转载注明出处:http://www.heiqu.com/283d848b6b8efe50f203730930ab3bb4.html