def StartCmdStringSckP2PLayout(dictPeerByParam, sHostName4Param, sAppId, clsSckP2PLayout): dictParam = dictPeerByParam.get(sHostName4Param, {}) if not dictParam: PrintTimeMsg('StartCmdStringSckP2PLayout.get(%s)={}' % sHostName4Param) sys.exit(-1) dictApp = dictParam.get(sAppId, {}) if not dictApp: PrintTimeMsg('StartCmdStringSckP2PLayout.get(%s)From(%s)={}' % (sAppId, str(dictParam))) sys.exit(-1) sIPPort = dictParam.get('sIPPort', '') sHubId = dictParam.get('sHubId', '') sPairId = dictParam.get('sPairId', '') sSuffix = dictApp.get('sSuffix', '') sAcctPwd = dictApp.get('sAcctPwd', '') sClientInfo = dictApp.get('sClientInfo', '') bVerbose = dictApp.get('bVerbose', 'True') == 'True' if sIPPort and sHubId and sPairId and sSuffix: cssa = clsSckP2PLayout(sHubId, sIPPort, sPairId, sSuffix, sAcctPwd, sClientInfo, bVerbose) cssa.StartMainThreadLoop() else: sErrMsg = '' if not sIPPort: sErrMsg += 'sIPPort,' if not sHubId: sErrMsg += 'sHubId,' if not sPairId: sErrMsg += 'sPairId,' if not sSuffix: sErrMsg += 'sSuffix,' sErrMsg = '(%s) is null' % sErrMsg[:-1] #剔除最后一个逗号 PrintTimeMsg('StartCmdStringSckP2PLayout.sErrMsg=%s!' % (sErrMsg)) sys.exit(-1)
def __init__(self, sHubId, sHostAndPort, sPairId, sSuffix, sAcctPwd, sClientInfo, bVerbosePrintCmdStr=True): global gDictSMTPByEMail TCmdStringSckP2PLayout.__init__(self, sHubId, sHostAndPort, sPairId, sSuffix, sAcctPwd, sClientInfo, bVerbosePrintCmdStr) iRunTimes = self.LoadAndSaveRunTimes() #sEMail = random.choice(gDictSMTPByEMail.keys()) self.sSmtpEMail = gDictSMTPByEMail.keys()[iRunTimes % len(gDictSMTPByEMail)] PrintTimeMsg('TPeerWait2SendMail.iRunTimes=%d.sSmtpEMail=(%s)!' % (iRunTimes, self.sSmtpEMail)) dictSMTP = gDictSMTPByEMail.get(self.sSmtpEMail, {}) sKey = '20160811' sPass = SimpleShiftDecode(sKey, dictSMTP.get('pass', '')) self.smtp = CSendSMTPMail(dictSMTP.get('smtp', ''), self.sSmtpEMail, sPass) self.sFNameLogMailHistory = GetThisFilePath('./', 'logMailHistory.txt') PrintTimeMsg('TPeerWait2SendMail.sFNameLogMailHistory=(%s)!' % (self.sFNameLogMailHistory)) WyfAppendToFile( self.sFNameLogMailHistory, 'TPeerWait2SendMail.%s.pid=(%d)...' % ('-' * 20, os.getpid())) self.TryToFinishSendMail()
def CheckAndRunOneCmd(self): # 检查并启动命令,适合于嵌入到主进程内运行 # 返回+1,表示 启动了新程序 # 返回-1,表示 停止了新程序 # 返回0,表示 没变化 self.ChangeWorkDir() # sCmd = self.getRedirectCmd() sCmd = self.sCmdExec if self.CheckStopFileExists(): #Need Quit iRet = 0 if self.CheckPidFileExists(): pid = self.ReadPidFromFile() if psutil.pid_exists(pid): TerminateByPid(pid) iRet = -1 else: if self.bVerbose: PrintTimeMsg("Check(%s)AlreadyQuit.pid=(%s)..." % (sCmd, pid)) else: PrintTimeMsg("checkPidFileExists.FALSE=(%s)..." % (sCmd)) return iRet else: if self.CheckPidFileExists(): pid = self.ReadPidFromFile() if psutil.pid_exists(pid): self.TouchPidFile() if self.bVerbose: PrintTimeMsg("Check(%s)StillRunning.pid=(%s)..." % (sCmd, pid)) return 0 self.__closeFd() if self.bVerbose: PrintTimeMsg("CheckAndRunOneCmd.sLogOutFile=(%s)..." % (self.sLogOutFile)) self.fdOut = open(self.sLogOutFile, 'a+') self.fdOut.write("\n[%s]%s{%s}...\n" % (GetCurrentTime(), '*' * 40, self.sProgramId)) self.fdOut.flush() if self.bErr2Out: self.fdErr = self.fdOut else: self.fdErr = open(self.sLogErrFile, 'a+') #self.Process = psutil.Popen(sCmd, stdout=self.fdOut,stderr=self.fdErr, shell=False) #True self.Process = psutil.Popen(sCmd, stdout=self.fdOut, stderr=self.fdErr, shell=self.bShellPopen) # Shell=True会新起一个cmd进程 pid = self.Process.pid # sMsg = "%s#Start(%s)=%s" % (iStartCnt,sCmd,pid) # self.recordPopenLog(sMsg) PrintTimeMsg("Popen(%s)OK.pid=%s" % (sCmd, pid)) #[20:] self.WritePidToFile(pid) return +1
def ProgramStartOne(self, sProgramId): #启动某个程序 rro = self.dictCfgCmdOne.get(sProgramId, None) if rro: rro.cco.CrtDelStopFile("DEL") bRet = rro.CheckAndRunOneCmd(False) PrintTimeMsg("ProgramStartOne(%s)=%s=" % (sProgramId, bRet)) return bRet else: PrintTimeMsg("ProgramStartOne.get(%s)=Error" % (sProgramId)) return False
def HandleNotifyMsg(self, sClientIPPort, CmdIStr): # 处理客户端通知消息,返回bDone=True表示已处理,bDone=False表示未处理 oLink = self.dictObjLinkByCIP.get(sClientIPPort, None) if oLink: oLink.iNotifyMsgNum += 1 PrintTimeMsg("HandleNotifyMsg.Fm(%s)=%s=" % (sClientIPPort, ','.join(CmdIStr))) return False else: PrintTimeMsg("HandleNotifyMsg.Fm(%s).oLink=%s=" % (sClientIPPort, str(oLink))) return True
def HandlePipePushData(self, oData, iDealCount): if self.bVerbose: PrintTimeMsg( 'TCmdStringSckP2PLayoutPipe.HandlePipePushData.%d#.oData=%s=' % (iDealCount, oData)) else: if iDealCount % self.iPrintIntervalNum == 0: PrintTimeMsg('PipePushData#%d.oData=%s=' % (iDealCount, ','.join(oData))) sRcv = '*' lsParam = [str(oData)] if type(oData) == list: sRcv = oData[0] lsParam = oData[1:] self.SendRequestP2PLayoutCmd(sRcv, lsParam, 'sLogicParamPipe')
def __init__(self, dictParam): self.dictParam = dictParam PrintTimeMsg("CWinSVProgram.dictParam=%s" % PrettyPrintStr(self.dictParam)) self.sGroupId = self.dictParam.get('groupId', '') self.sProgramId = self.dictParam.get('programId', '') self.sCmdExec = self.dictParam.get('cmdExec', '') self.sWorkDir = self.dictParam.get('workDir', '') self.sLogDir = self.dictParam.get('logDir', '') self.bErr2Out = self.dictParam.get('err2Out', True) self.bShellPopen = self.dictParam.get('shellPopen', False) PrintTimeMsg("CWinSVProgram.CWinSVProgram(%s.%s)=%s=" % (self.sGroupId, self.sProgramId, self.sCmdExec)) PrintTimeMsg("CWinSVProgram.sWorkDir=%s=" % (self.sWorkDir)) PrintTimeMsg("CWinSVProgram.sLogDir=%s=,bErr2Out=%s" % (self.sLogDir, self.bErr2Out)) # stopFile=<logDir>/<programId>.stop stop文件,若存在,则终止对应进程 # pidFile=<logDir>/<programId>.pid pid文件,用于查询该进程运行状态 # outFile=<logDir>/<programId>.out 标准输出日志文件 # errFile=<logDir>/<programId>.err 标准错误输出日志文件 # outerrFile=<logDir>/<programId>.tr 标准输出和错误输出合并日志文件 sLogProgramId = self.sLogDir + self.sProgramId if self.bErr2Out: self.sLogOutFile = sLogProgramId + ".tr" self.sLogErrFile = self.sLogOutFile else: self.sLogOutFile = sLogProgramId + ".out" self.sLogErrFile = sLogProgramId + ".err" self.sPidFile = sLogProgramId + ".pid" self.sStopFile = sLogProgramId + ".stop" try: sDir = self.sLogDir os.makedirs(sDir) except OSError as exc: # Python >2.5 (except OSError, exc: for Python <2.5) import errno if exc.errno == errno.EEXIST and os.path.isdir(sDir): pass else: raise self.fdOut = None self.fdErr = None self.Process = None #当前在运行的进程对象 self.bVerbose = False
def ReadCmdStrFromLink(self, iSecondsTimeOut): #从链接上读取CmdStr # 失败返回 ErrCode,sErrMsg # 成功返回 'OK',(dwCmdId,CmdStr) iTmSeconds = iSecondsTimeOut if self.charCS == 'S' and self.cLoginStatus == 'L': iTmSeconds = 5 #登录时,超时时间要短,避免链接攻击 sRet, listHead = self.shouldReadLenData(16, iTmSeconds) if sRet != 'OK': return sRet, 'ReadCmdStrFromLink.Head(%s)' % (listHead) # printHexString("RcvDataFromClient.head",listHead) (dwCmdId, dwDataLen) = SerialCstpHeadFmString(''.join(listHead)) if self.bVerbosePrintCmdStr: PrintTimeMsg('ReadCmdStrFromLink.dwCmdId=%d,dwDataLen=%d' % (dwCmdId, dwDataLen)) if self.charCS == 'S' and self.cLoginStatus == 'L': if not IsCmdRequest(dwCmdId): return 'Error', 'ReadCmdStrFromLink.Only receive RequestCmd in Login Stage!' sRet, listData = self.shouldReadLenData(dwDataLen, 3) if sRet != 'OK': return sRet, 'ReadCmdStrFromLink.Data(%s)' % (listData) CmdStr = SerialCmdStrFmString(''.join(listData)) if self.bVerbosePrintCmdStr: printCmdString("ReadCmdStrFromLink", CmdStr) return sRet, (dwCmdId, CmdStr)
def HexToInt8(sHex): """ 将8字节16进制串转为双字无符号整数 """ try: return int(sHex,16) except Exception, e: PrintTimeMsg('HexToInt8(%s)=Error' % sHex) raise
def SetKickOffFlagTrue(self, sClientIPPort): # 设置踢出标记 # PrintTimeMsg("SetKickOffFlagTrue(%s)..." % (sClientIPPort)) oLink = self.dictObjLinkByCIP.get(sClientIPPort, None) if oLink: oLink.bKickOff = True PrintTimeMsg("SetKickOffFlagTrue(%s)!" % (sClientIPPort))
def __init__(self, sHubId): self.sHubId = sHubId self.oBind = None # 监听等待的服务端对象 # oBind 在 HandleServerStart 中赋值: # oHub = TCmdStringHub服务框架对象标识,可以从中读取一些全局参数 # 在非空情况下中有如下附加属性: # iNowLinkNum = 当前客户端链接数 #WeiYF.20160623 使用GetBindAttrValue和GetLinkAttrValue两个函数来获取动态附加属性 #WeiYF.20160627 以 sClientIPPort 为键值创建一个字典,来保管 oLink 信息。 self.dictObjLinkByCIP = {} # oLink 在 handleClientBegin 中赋值: # sClientIPPort = 客户端的IP地址端口号,冒号分隔 # 在P2P11模式下,还有 # sPeerId = Peer标识 # sPairId = Pair标识 # sSuffix = Pair后缀 # 在非空情况下中有如下附加属性: # iRequestCmdNum = 客户端请求计数 # iReplyCmdNum = 客户端应答计数 self.iTestReplyCnt = 0 self.bQuitLoopFlag = False # 循环控制变量,由主控程序赋值 self.sSelfHubId = '' self.bVerbosePrintCmdStr = True sFNLogClient = 'logClientOnOff.txt' self.sFNameLogClient = '/tmp/' + sFNLogClient if GetSystemPlatform() == 'Windows': self.sFNameLogClient = 'D:\\' + sFNLogClient PrintTimeMsg("CHubCallbackBasicBase.sFNameLogClient=(%s)!" % (self.sFNameLogClient))
class CQueueThread(Thread): def __init__(self, gef, Q, cbDealFunc): self.gef = gef self.Q = Q self.cbDealFunc = cbDealFunc self.sQueueName = self.Q.GetQueueName() Thread.__init__(self, name='Thread' + self.sQueueName) self.setDaemon(True) def run(self ): #Overwrite run() method, put what you want the thread do here iLoopCnt = 0 while not self.gef.IsExitFlagTrue(): iLoopCnt += 1 try: dictObj = self.Q.GetFmQueue(self.getName()) iQueueSize = self.Q.GetQueueSize() # if iQueueSize or dictObj: # PrintTimeMsg("%s#%d.run.QueueSize=%s,dictObj=(%s)" % ( # self.getName(),iLoopCnt,iQueueSize,str(dictObj))) if self.cbDealFunc and dictObj: self.cbDealFunc(self.sQueueName, dictObj) else: if not self.cbDealFunc: PrintTimeMsg("%s#%d.JustPrint.dictObj=(%s)" % (self.getName(), iLoopCnt, str(dictObj))) #PrintAndSleep(5, "_doRun.Just4Debug") except Exception, e: PrintTimeMsg("CQueueThread.%s.Exception:%s" % (self.getName(), str(e))) raise PrintTimeMsg("CQueueThread.%s.END.gbSigExit=%s!" % (self.getName(), str(self.gef.IsExitFlagTrue())))
def ProgramCheckRun(self, bForce=False): secChkInterval = 30 #检查时间最小间隔,也是被监控进程退出 if bForce or int(time.time()) - self.tmLastCheckRun >= secChkInterval: iRunCnt = 0 for programId, rro in self.dictCfgCmdOne.items(): if rro.CheckAndRunOneCmd(False) != 0: iRunCnt += 1 self.tmLastCheckRun = int(time.time()) if iRunCnt > 0 and False: PrintTimeMsg("ProgramCheckRun.RunCnt=%s=" % (iRunCnt)) return True self.iCheckCount += 1 bVerbose = False #self.iCheckCount%10 == 0 if bVerbose: PrintTimeMsg("ProgramCheckRun.ChkCnt=%s=" % (self.iCheckCount)) return False
def __handleClientRead(self, oObj): # 处理从链接上读取数据包 while not oObj.bQuitLoopFlag: try: sRet, oTuple = oObj.ReadCmdStrFromLink( self.iSecondsTimeOut) # 15s 调试用 if sRet == 'OK': (dwCmdId, CmdStr) = oTuple if IsHeartBeat(dwCmdId): oObj.EchoHeartBeatMsg(CmdStr) else: sCmdType = GetCmdType(dwCmdId) if not self.DealSpecialCmdRequest( oObj, dwCmdId, CmdStr): if self.queueRequest.qsize( ) > self.iMaxQueueReqNum: #WeiYF.20160324 进行流控,消息积压则暂缓 gevent.sleep(self.fSecondsFlowCtrl) #0.0001 self.queueRequest.put( [oObj.GetObjIPPort(), dwCmdId, CmdStr]) elif sRet == 'TimeOut': oObj.SendHeartBeatMsg('0', 'HeartBeat TimeOut From Server') else: sErrMsg = oTuple oObj.SetCloseQuitFlag("__handleClientRead.sErrMsg=(%s)" % (oTuple)) #会退出 # gevent.sleep(0) except Exception, e: import traceback traceback.print_exc() #WeiYF.20151022 打印异常整个堆栈 这个对于动态加载非常有用 PrintTimeMsg('__handleClientRead.Exception.e=(%s)' % (str(e)))
def CheckStopFileExists(self): # 检查 stop文件 是否存在 sFN = self.sStopFile bRet = os.path.exists(sFN) if bRet: PrintTimeMsg("CheckStopFileExists(%s)=%s" % (sFN, bRet)) return bRet
def HandleClientEnd(self, sClientIPPort): # 处理客户端结束事件 self.oBind.iNowLinkNum -= 1 del self.dictObjLinkByCIP[sClientIPPort] # delattr(self.oLink,'sClientIPPort') PrintTimeMsg("HandleClientEnd(%s).iNowLinkNum=%d=" % (sClientIPPort, self.oBind.iNowLinkNum)) WyfAppendToFile(self.sFNameLogClient, '%s=Off' % sClientIPPort)
def LaunchTraverseCount(self): lsSuffixOnline = self.sSuffixOnlineList.split(',') lsLeft = [] for sS in lsSuffixOnline: if sS != self.sSuffix: lsLeft.append(sS) if len(lsLeft) <= 0: PrintTimeMsg('LaunchTraverseCount.lsLeft=(%s)!' % ','.join(lsLeft)) else: PrintTimeMsg('LaunchTraverseCount.lsLeft=(%s)!' % ','.join(lsLeft)) sSuffixTarget = lsLeft[0] iCountValueNow = 1 self.SendRequestP2PLayoutCmd(sSuffixTarget, ( CMD3_P2PLAYOUT_TRAVERSE_COUNT, str(iCountValueNow), self.sSuffix, ), 'sLogicParam')
def GetCmdRequestFmReply(dwCmdId): """ 从应答命令转换得到请求命令,返回0表示失败 """ global CMDID_HREAT_BEAT if IsCmdReply(dwCmdId): return dwCmdId-CMDID_HREAT_BEAT else: PrintTimeMsg('GetCmdRequestFmReply.dwCmdId=%.8X,Error' % dwCmdId) return 0
def ProgramQueryAll(self, bVerbose=True): #查询所有程序运行状态 dictRet = {} for programId, rro in self.dictCfgCmdOne.items(): dictRet[programId] = rro.cco.GetStatusDict() if bVerbose: PrintTimeMsg("ProgramQueryAll=" + PrettyPrintStr(self.dictConfig)) return dictRet
def ConnectToServer(self): self.clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.clientsocket.connect((self.sServerIP, self.iServerPort)) self.sockRW = CSockReadWrite(self.clientsocket, 'C') self.sockRW.bVerbosePrintCmdStr = False self.sockRW.SetObjIPPort(self.sServerIPPort) PrintTimeMsg("ConnectToServer(%s).pid=(%s)" % (self.sServerIPPort, os.getpid()))
def TouchPidFile(self): # 更新 pid文件 时间 try: os.utime(self.sPidFile, None) # # PrintTimeMsg("TouchPidFile(%s)OK!" % (self.sPidFile)) except OSError as e: PrintTimeMsg("TouchPidFile(%s)Error=(%s)!" % (self.sPidFile, str(e)))
def HandleServerStart(self, oHub): # 处理服务端启动事件 self.oBind = ClassForAttachAttr() self.oBind.oHub = oHub self.oBind.iNowLinkNum = 0 PrintTimeMsg("HandleServerStart(%s,%s)..." % (self.sHubId, self.GetHubAttrValue('sServerIPPort', '@'))) self.bVerbosePrintCmdStr = self.GetHubAttrValue( 'bVerbosePrintCmdStr', True)
def _loadInitConfig(self, bVerbose=True): self.dictConfig = {} with open(self.sFNameConfig, "r") as f: sData = f.read() # print "sData",sData # 这里configCmd.json要采用UTF-8编码,文件开头有UTF标记 dictJson = json.loads(sData) for programId, dictParam in dictJson.items(): if type(dictParam) == dict: #WeiYF.20150604是dict类型才执行 if not programId.startswith('<'): self.dictConfig[programId] = LoadConfigByProgramId( self.sFNameConfig, programId, False) if bVerbose: PrintTimeMsg(PrettyPrintStr(self.dictConfig)) self.dictCfgCmdOne = {} for programId, dictParam in self.dictConfig.items(): rro = CRepeatRunOne(dictParam) self.dictCfgCmdOne[programId] = rro PrintTimeMsg("_loadInitConfig.Count=(%s)!" % (len(self.dictCfgCmdOne)))
def ImportPythonClassOrVar(sPythonFileName, sClassOrVar): # 从python源码文件动态import try: from import_file import import_file imp = import_file(sPythonFileName) return getattr(imp, sClassOrVar) except Exception, e: import traceback traceback.print_exc() PrintTimeMsg('ImportPythonClassOrVar.Exception.e=(%s)' % (str(e)))
def SendPipeRequest(self, CmdStr): try: if self.sockRW == None: self.ConnectToServer() #放到try内部,避免出异常 dwCmdId = 1225 #WeiYF.20160805 固定取值 bResult = self.sockRW.WriteCmdStrToLink(dwCmdId, CmdStr) if bResult: return bResult except Exception, e: import traceback traceback.print_exc() PrintTimeMsg('SendPipeRequest.Exception={%s}!' % (str(e)))
def __hubQuitAndFreeLink(self, oObj, sHint): if not oObj.bQuitLoopFlag: oObj.SetCloseQuitFlag(sHint) self.oHubCallback.SetCallBackQuitFlag(sHint) if oObj.ChkFirstDoQuitEnd(): sObjIPPort = oObj.GetObjIPPort() self.oHubCallback.HandleClientEnd(sObjIPPort) del (self.dictLinkQueue[sObjIPPort]) PrintTimeMsg("__hubQuitAndFreeLink(%s)ForReason=%s" % (sObjIPPort, sHint))
def SaveMailContentToSend(self, dictMail): sFNameMail = GetThisFilePath('.', 'mailToSend%s.json' % GetCurrentTimeMSs()) PrintTimeMsg('SaveMailContentToSend.sFNameMail=(%s)!' % (sFNameMail)) try: csjMail = CSerialJson(sFNameMail) csjMail.Save(dictMail) except Exception, e: import traceback traceback.print_exc()
def WritePidToFile(self, pid): # 输出 pid 文件 try: with open(self.sPidFile, "w") as f: #覆盖模式输出 sS = "%s" % (pid) f.write(sS) # PrintTimeMsg("_WritePidToFile(%s,%s)OK!" % (self.sPidFile,pid)) except OSError as e: PrintTimeMsg("WritePidToFile(%s)Error=(%s)!" % (self.sPidFile, str(e)))
def HandleRequestCmd(self, sClientIPPort, dwCmdId, CmdIStr): # 处理客户端请求命令,返回bDone=True表示已处理,bDone=False表示未处理 oLink = self.dictObjLinkByCIP.get(sClientIPPort, None) if oLink: oLink.iRequestCmdNum += 1 # PrintTimeMsg("HandleRequestCmd.Fm(%s)=%s=" % (sClientIPPort, ','.join(CmdIStr) )) return False else: PrintTimeMsg("HandleRequestCmd.Fm(%s).oLink=%s=" % (sClientIPPort, str(oLink))) return True
def runCmdStringHub(sHostName4Param): global gDictP2PLayoutByPairId,gDictIPPortByParam dictParam = gDictIPPortByParam.get(sHostName4Param,{}) if not dictParam: PrintTimeMsg('runCmdStringHub.get(%s)={}' % sHostName4Param) sys.exit(-1) sServerIPPort = dictParam.get('sIPPort', '0.0.0.0:9110') sHubId = md5('%s:%s:@HubId' % (sHostName4Param,sServerIPPort)) tupleClsParamP2PLayout = (sHubId,gDictP2PLayoutByPairId,) StartCmdStringHub(sHostName4Param,sServerIPPort, CHubCallbackP2PLayout, tupleClsParamP2PLayout, __file__)