哈爾濱智能建站模板網(wǎng)站統(tǒng)計系統(tǒng)
源碼將于最后一遍文章給出下載
- 監(jiān)測數(shù)據(jù)采集物聯(lián)網(wǎng)應(yīng)用開發(fā)步驟(10)
程序自動更新開發(fā)
前面章節(jié)寫了部分功能模塊開發(fā):
- 日志或文本文件讀寫開發(fā);
- Sqlite3數(shù)據(jù)庫讀寫操作開發(fā);
- 定時器插件化開發(fā);
- 串口(COM)通訊開發(fā);
- TCP/IP Client開發(fā);
- TCP/IP Server 開發(fā);
- modbus協(xié)議開發(fā);
本章節(jié)啰嗦些,該解決方案最終業(yè)務(wù)成品有些需要部署在不同工控機(jī)或設(shè)備上,在實際應(yīng)用過程中隨時間推移有些需要升級迭代或修改bug,一旦安裝部署設(shè)備點位達(dá)到一定數(shù)量,系統(tǒng)自動更新升級就是一個必要的步驟了。筆者開發(fā)的業(yè)務(wù)應(yīng)用在相應(yīng)的設(shè)備上安裝已近千臺設(shè)備,鑒于此增加了程序自動更新功能模塊。
在com.zxy.common.Com_Para.py中添加如下內(nèi)容
#自動更新服務(wù)端文件夾地址
urlPath = ""
#程序版本號
version = ""
新建程序版本自動更新類com.zxy.autoUpdate.GetVersion.py
?
#! python3
# -*- coding: utf-8 -
'''
Created on 2017年05月10日
@author: zxyong 13738196011
'''import urllib.request,datetime
from com.zxy.adminlog.UsAdmin_Log import UsAdmin_Log
from com.zxy.common import Com_Para
from com.zxy.common.Com_Fun import Com_Fun
from com.zxy.interfaceReflect.A01_A1B2C3 import A01_A1B2C3
from com.zxy.z_debug import z_debug
from urllib.parse import urlparse#監(jiān)測數(shù)據(jù)采集物聯(lián)網(wǎng)應(yīng)用--程序版本自動更新類
class GetVersion(z_debug):def __init__(self):pass#下載文件def SaveRemoteFile(self,inputFileName,inputLocalFileName):try:temResult = urllib.request.urlretrieve(Com_Para.urlPath+"/"+inputFileName,Com_Para.ApplicationPath+Com_Para.zxyPath+inputLocalFileName)except Exception as e:if str(type(self)) == "<class 'type'>":self.debug_in(self,repr(e)+"=>"+str(e.__traceback__.tb_lineno))#打印異常信息else:self.debug_in(repr(e)+"=>"+str(e.__traceback__.tb_lineno))#打印異常信息return temResult#保存版本號文件def SaveVersionFile(self,version_no,inputLocalFileName):temStrTFileName = Com_Para.ApplicationPath+Com_Para.zxyPath+inputLocalFileNametemFile = Nonetry:?temFile = open(temStrTFileName, 'w',encoding=Com_Para.U_CODE)temFile.write(version_no)temFile.close()except Exception as e:if str(type(self)) == "<class 'type'>":self.debug_in(self,repr(e)+"=>"+str(e.__traceback__.tb_lineno))#打印異常信息else:self.debug_in(repr(e)+"=>"+str(e.__traceback__.tb_lineno))#打印異常信息finally:if temFile != None:temFile.close()#檢測最新版本def CheckVersion(self):try:print("check new version..."+Com_Fun.GetTimeDef())#讀取服務(wù)器端version.txt信息temResult = self.GetRequestWeb()if temResult == "":return 0temUL = UsAdmin_Log(Com_Para.ApplicationPath,temResult,0)#文件形式版本號管理temVersion = temUL.ReadFile(Com_Para.ApplicationPath+Com_Para.zxyPath + "version.txt")Com_Para.version = temVersion#數(shù)據(jù)庫形式版本號管理temVersion = Com_Para.versiontemAryTem = []temVersion_No = ""temLastFile = ""#判斷文件是否存在if temVersion == "" and temResult != "":print("local version none,downloading new version")temAryTem = temResult.split("\n")for temLine in temAryTem:temLine = temLine.replace("\r","").replace("\n","")temLastFile = temLineif temLine.find("version=") != -1:temVersion_No = temLineelif temLine != "":print("new version file download:"+temLine)self.SaveRemoteFile(temLine,"back/"+temLine)self.CopyFile(temLine)if temVersion_No != "":#文件形式版本管理 ? ??self.SaveVersionFile(temVersion_No,"version.txt")#數(shù)據(jù)庫形式版本文件管理#將版本號insert入庫 該處代碼省略....Com_Para.version = temVersion_No ? ?print("new version updated over:")#如果讀到reboot.txt則需要重啟設(shè)備if temLastFile.strip() == "reboot.txt":self.RebootProgram()return 0if temVersion_No != "":#文件形式版本管理 ? ??print("new version updated over:")self.SaveVersionFile(temVersion_No,"version.txt")#數(shù)據(jù)庫形式版本文件管理#將版本號insert入庫 ?該處代碼省略....Com_Para.version = temVersion_Noelif temResult != "":#數(shù)據(jù)庫形式版本號管理
# ? ? ? ? ? ? ? ? localVersion = Com_Para.version#文件形式版本號管理temAryTem = temVersion.split("\n")for temLine in temAryTem:temArySub = temLine.split("=")if len(temArySub) > 1 and temArySub[0] == "version":localVersion = temArySub[1]break?bFlag = FalsetemAryTem = temResult.split("\n")for temLine in temAryTem:temLine = temLine.replace("\r","").replace("\n","")temLastFile = temLinetemArySub = temLine.split("=")if len(temArySub) > 1 and temArySub[0] == "version":try:if localVersion.find("=") != -1:iLV = int(localVersion.split("=")[1])else:iLV = int(localVersion)if localVersion != "" and iLV >= int(temArySub[1]):bFlag = Falseelse:temVersion_No = temLinebFlag = Trueexcept:bFlag = Falsebreakelse:if bFlag:self.SaveRemoteFile(temLine,"back/"+temLine)self.CopyFile(temLine)if temVersion_No != "":#文件形式版本管理 ? ??self.SaveVersionFile(temVersion_No,"version.txt")?#數(shù)據(jù)庫形式版本文件管理 ?#將版本號insert入庫 ?該處代碼省略....Com_Para.version = temVersion_Noprint("new version updated over:"+temVersion_No)if temLastFile.strip() == "reboot.txt":self.RebootProgram()return 0if (bFlag and temVersion_No != ""):#文件形式版本管理 ? ??self.SaveVersionFile(temVersion_No,"version.txt")#數(shù)據(jù)庫形式版本文件管理 ?#將版本號insert入庫 ?該處代碼省略....Com_Para.version = temVersion_Noprint("new version updated over:")if bFlag and temLastFile.strip() == "reboot.txt":self.RebootProgram()return 0except Exception as e:if str(type(self)) == "<class 'type'>":self.debug_in(self,repr(e)+"=>"+str(e.__traceback__.tb_lineno))#打印異常信息else:self.debug_in(repr(e)+"=>"+str(e.__traceback__.tb_lineno))#打印異常信息return 1#重啟設(shè)備def RebootProgram(self): ? ? ? ?aa = A01_A1B2C3()if Com_Para.devsys.lower() == "linux":?aa.param_value2 = "reboot -f"aa.CmdExecLinux()else:aa.param_value2 = "shutdown -r"aa.CmdExecWin()#文件更新def CopyFile(self,inputWebFile):temAryTem = inputWebFile.split("\n")for temLine in temAryTem:if temLine.find("=") == -1:aa = A01_A1B2C3()temFileName = temLine[0:temLine.find(".")]temFileAtt = temLine[temLine.find("."):len(temLine)].upper()if temFileAtt.upper() == ".ZIP":aa.param_value2 = "unzip -o "+Com_Para.ApplicationPath+Com_Para.zxyPath+"back"+Com_Para.zxyPath+temLine+" -d "+Com_Para.ApplicationPath+Com_Para.zxyPath+"back"+Com_Para.zxyPath+temFileName+Com_Para.zxyPathaa.param_value3 = Com_Para.ApplicationPath+Com_Para.zxyPath+"back"+Com_Para.zxyPath+temLineaa.param_value4 = Com_Para.ApplicationPath+Com_Para.zxyPath+"back"+Com_Para.zxyPath+temFileName+Com_Para.zxyPath#利用命令進(jìn)行解壓縮#aa.CmdExecLinux()#利用python自帶解壓縮模塊aa.unzip_file() ? ? ? ? ? ? ? ? ? ??if Com_Para.devsys.lower() == "linux": ? ? ? ? ? ? ? ??aa.param_value2 = "cp -rf "+Com_Para.ApplicationPath+Com_Para.zxyPath+"back"+Com_Para.zxyPath+temFileName+Com_Para.zxyPath+"* "+Com_Para.ApplicationPath+Com_Para.zxyPathelse:aa.param_value2 = "xcopy "+Com_Para.ApplicationPath+Com_Para.zxyPath+"back"+Com_Para.zxyPath+temFileName+Com_Para.zxyPath+"*.* "+Com_Para.ApplicationPath+" /E /Y"aa.CmdExecLinux()#執(zhí)行sql語句elif temFileAtt.upper() == ".SQL":aa.RunSqlFile(Com_Para.ApplicationPath+Com_Para.zxyPath+"back"+Com_Para.zxyPath+temLine)#執(zhí)行更新數(shù)據(jù)接口elif temFileAtt.upper() == ".JSON":#JSON業(yè)務(wù)數(shù)據(jù)進(jìn)行數(shù)據(jù)庫結(jié)構(gòu)更改或升級passelse:if Com_Para.devsys.lower() == "linux": ? ? ? ? ? ? ? ??aa.param_value2 = "cp -rf "+Com_Para.ApplicationPath+Com_Para.zxyPath+"back"+Com_Para.zxyPath+temLine+" "+Com_Para.ApplicationPath+Com_Para.zxyPathelse:aa.param_value2 = "copy "+Com_Para.ApplicationPath+Com_Para.zxyPath+"back"+Com_Para.zxyPath+temLine+" "+Com_Para.ApplicationPath+Com_Para.zxyPath+" /Y"aa.CmdExecLinux()#inputFlag網(wǎng)絡(luò)鏈接是否正常def set_dSockList(self,inputFlag):urlp = urlparse(Com_Para.urlPath)if Com_Para.urlPath == "":return None ? ? ? ? ? ? ? ?key = str(urlp.netloc.replace(":","|"))?#存在if key not in list(Com_Para.dSockList.keys()):Com_Para.dSockList[key] = [0,datetime.datetime.now()]if inputFlag == False:objAry = Com_Para.dSockList[key]if objAry[0] <= 10:objAry[0] = objAry[0] + 1objAry[1] = datetime.datetime.now()Com_Para.dSockList[key] = objAryelse:Com_Para.dSockList[key] = [0,datetime.datetime.now()] ? ?#判斷上次鏈接時間頻率是否合規(guī)def judge_dSock(self):urlp = urlparse(Com_Para.urlPath)if Com_Para.urlPath == "":return False ? ? ? ? ? ? ? ?key = str(urlp.netloc.replace(":","|"))?if key not in list(Com_Para.dSockList.keys()):Com_Para.dSockList[key] = [0,datetime.datetime.now()]objAry = Com_Para.dSockList[key]starttime = datetime.datetime.now()if objAry[0] <= 3:return Trueelif objAry[0] > 4 and starttime >= objAry[1] + datetime.timedelta(hours=12):return Trueelse:return Falsedef GetRequestWeb(self):temResult = ""try:#判斷上次鏈接時間頻率是否合規(guī)if not self.judge_dSock():return ""resp = urllib.request.urlopen(Com_Para.urlPath+"/version.txt",timeout=5)temResult = resp.read().decode(Com_Para.U_CODE) ? ? ? ?except Exception as e:temLog = ""if str(type(self)) == "<class 'type'>":temLog = self.debug_info(self)+repr(e)else:temLog = self.debug_info()+repr(e)uL = UsAdmin_Log(Com_Para.ApplicationPath, temLog+"=>"+str(e.__traceback__.tb_lineno))uL.WriteLog()temResult = ""self.set_dSockList(False)return temResult
新建操作系統(tǒng)執(zhí)行指令接口類com.zxy.interfaceReflect.A01_A1B2C3.py
#! python3
# -*- coding: utf-8 -
'''
Created on 2017年05月10日
@author: zxyong 13738196011
'''import os, sys,zipfile,subprocess,tempfile
from urllib.parse import unquote
from com.zxy.common import Com_Para
from com.zxy.common.Com_Fun import Com_Fun
from com.zxy.z_debug import z_debug#監(jiān)測數(shù)據(jù)采集物聯(lián)網(wǎng)應(yīng)用--操作系統(tǒng)執(zhí)行指令接口類
class A01_A1B2C3(z_debug):strResult = ""session_id = ""param_name = ""param_value1 = None #1:同步更新設(shè)備時間param_value2 = None #當(dāng)前時間param_value3 = Noneparam_value4 = Noneparam_value5 = Noneparam_value6 = Noneparam_value7 = Noneparam_value8 = Noneparam_value9 = Noneparam_value10 = None#是否繼續(xù)執(zhí)行 1:繼續(xù)執(zhí)行 0:中斷執(zhí)行strContinue = "0"strCmdValue = ""def __init__(self):passdef init_start(self):
# /**************************************************/
# //示例: 此處寫業(yè)務(wù)邏輯,最后給 param_name,param_value1....重新賦值
# // param_name += Com_Fun.Get_New_GUID()
# // param_value1 += Com_Fun.Get_New_GUID()
# // param_value2 += Com_Fun.Get_New_GUID()
# // ......# /**************************************************/
# //示例:若業(yè)務(wù)邏輯判斷失敗,不發(fā)送數(shù)據(jù)庫接口請求并返回失敗信息#strContinue = "0" 表示攔截器判斷接口執(zhí)行結(jié)束,不需要入庫操作,直接返回信息temValue = ""self.strContinue = "0"if self.param_value1 == "100" and Com_Para.devsys == "linux":temValue = self.CmdExecLinux(self)self.strResult = "命令結(jié)果:\r\n"for temR in temValue:self.strResult = self.strResult+temR.decode(Com_Para.U_CODE)+"\r\n"#100執(zhí)行命令elif self.param_value1 == "100" and Com_Para.devsys == "windows":temValue = self.CmdExecWin(self)self.strResult = "{\""+self.param_name+"\":[{\"s_result\":\"1\",\"error_desc\":\"命令執(zhí)行成功"+temValue+"\"}]}"#利用python自帶解壓縮def unzip_file(self):temzipfile = zipfile.ZipFile(self.param_value3, 'r')temzipfile.extractall(self.param_value4) #重啟程序def RestartPro(self):python = sys.executableos.execl(python,python,* sys.argv)#執(zhí)行命令(Linux)def CmdExecLinux(self):out_temp = Nonetry: temCommand = unquote(unquote(self.param_value2,Com_Para.U_CODE))out_temp = tempfile.SpooledTemporaryFile(max_size=10*1000)fileno = out_temp.fileno()obj = subprocess.Popen(temCommand,stdout=fileno,stderr=fileno,shell=True)obj.wait() out_temp.seek(0)temResult = out_temp.readlines() except Exception as e:temResult = repr(e)finally:if out_temp is not None:out_temp.close()return temResult#執(zhí)行命令(Windows)def CmdExecWin(self):try:temCommand = unquote(unquote(self.param_value2,Com_Para.U_CODE))temResult = os.popen(temCommand).read()except Exception as e:temResult = repr(e)return temResult#更新設(shè)備時間(Windows)def ChangeDateWin(self):try:temDate = Com_Fun.GetDateInput('%Y-%m-%d', '%Y-%m-%d %H:%M:%S', unquote(unquote(self.param_value2.replace("+"," "),Com_Para.U_CODE)))temTime = Com_Fun.GetDateInput('%H:%M:%S', '%Y-%m-%d %H:%M:%S', unquote(unquote(self.param_value2.replace("+"," "),Com_Para.U_CODE)))temResult = os.system('date {} && time {}'.format(temDate,temTime))except:temResult = -1return temResult#更新設(shè)備時間(Linux)def ChangeDateLinux(self):try: #將硬件時間寫入到系統(tǒng)時間:#hwclock -s#將系統(tǒng)時間寫入到硬件時間#hwclock -wtemCommand = unquote(unquote("date -s \""+self.param_value2.replace("+"," ").split(" ")[0]+"\"",Com_Para.U_CODE))temCommand = unquote(unquote("date -s \""+self.param_value2.replace("+"," ").split(" ")[1]+"\"",Com_Para.U_CODE))out_temp = tempfile.SpooledTemporaryFile(max_size=10*1000)fileno = out_temp.fileno()obj = subprocess.Popen(temCommand,stdout=fileno,stderr=fileno,shell=True)obj.wait()temCommand = unquote(unquote("hwclock -w",Com_Para.U_CODE))obj = subprocess.Popen(temCommand,stdout=fileno,stderr=fileno,shell=True)obj.wait() out_temp.seek(0)temByt = out_temp.readlines()temResult = temByt[0].decode(Com_Para.U_CODE)if temResult == "" :temResult = "1"except Exception as e:temResult = "-1" finally:if out_temp is not None:out_temp.close()return temResult
版本更新測試案例MonitorDataCmd.py主文件中編寫:
from com.zxy.autoUpdate.GetVersion import GetVersion
在????if?__name__ == '__main__':下添加
????????#版本更新測試Com_Para.urlPath = "http://localhost:8080/testweb/updtest/"gv = GetVersion() ???gv.CheckVersion()print("=>版本更新完成")
程序文件新建back文件夾臨時存放下載更新包的zip文件;
版本更新服務(wù)端文件信息
版本更新服務(wù)端版本號信息
運行結(jié)果設(shè)備端更新之后新增文件
更新文件已下載并自動解壓縮成功。
print打印出的內(nèi)容