#!/usr/bin/python #_*_ coding:utf-8 _*_ import MySQLdb import time import threading import random from email.MIMEText import MIMEText from email.MIMEMultipart import MIMEMultipart from email.MIMEBase import MIMEBase from email import Utils, Encoders import mimetypes import sys import smtplib import socket import getopt import os import re import shutil import platform ''' 后端处理脚本:封装了“邮件处理类”和“任务类”。其中“任务类”对应DB,“内部类”对应TABLE 主要完成: 1、定时查询任务 2、标记DB状态 3、判断任务执行、并标记任务 4、形成日常处理日志 5、错误日志上报 6、任务守护 7、任务编号带入SourceCode,工模显示任务编号 8、兼容上海/深圳部署 注意: 先构造类的实例“__init__”,在进行方法调用 调试模式下,辅助调试方法“__str__()” 统一的“config()”接口,对TABLE进行处理,不允许有其它接口 ''' g_daemonMode = 0 g_nullDo = False #单次任务处理类,对应主表Compile class CTask: def __init__(self,data): listIr = str(data[5]).split(",") listIr.append(u"IRKK") self.compileId = data[0] self.userName = data[1] self.userMail = data[2] self.boardName = data[3] self.panelName = data[4] self.irName = set(listIr) self.contentId = data[6] self.complieDate = data[7] self.binFile = data[8] self.compileState = data[9] self.sourcePath = "/kitking/xxx/webSourceCode" #默认的编译目录 self.webPath = "/var/www/web" #默认的WEB目录 self.webErrorMail = "xxxd@163.com" #错误日志上报 self.dbSource = ["ATV","CVBS","YPBPR","PC","HDMI","MULTIMEDIS"] if list(platform.uname())[2] == "3.16.0-23-generic": #深圳服务器更改部署路径 self.sourcePath = "/kk/xxx/share/webSourceCode" class CContent: def __init__(self,data): self.contentID = data[0] self.area = data[1] self.theme = data[2] self.panelID = data[3] self.language = set(str(data[4]+","+data[5]).split(",")) self.deLanguage = data[5] self.keypadName = data[6] self.logoName = data[7] self.pqName = data[8] self.speaker = data[9] self.source = data[10] self.powerState = data[11] self.swArc = data[12] self.swCec = data[13] self.swMhl = data[14] self.swOsdgame = data[15] self.swNes = data[16] self.swBt = data[17] self.swCaptureLogo = data[18] self.swBlueScreen = data[19] self.blstyle = [20] def info(self): return [self.contentID,self.area,self.theme,self.language,self.keypadName,self.logoName] def __str__(self): return ("contentID[%d]-[%s]-[%s]-[%s]-[%s]-[%s]-arc[%s]-cec[%s]-mhl[%s]-osdgame[%s]" %(self.contentID,self.area,self.theme,self.language,self.keypadName,self.logoName,self.swArc,self.swCec,self.swMhl,self.swOsdgame)).encode("utf-8") def config(self,strPath): listPro = [] # 修改主题 /CEC/ARC/OSDGAME/抓图 with open(strPath + '/menuconfig.config',"r") as mFile: listTemp = mFile.readlines() for each in listTemp: if "CONFIG_TV_NEW_UI" in each: if self.theme == u"MSTAR风格": each = "# CONFIG_TV_NEW_UI is not set " elif self.theme == u"蓝色经典": each = "CONFIG_TV_NEW_UI=y " elif "CONFIG_SUPPORT_CAI_UI_STYLE" in each: if self.theme == u"MSTAR风格": each = "#CONFIG_SUPPORT_CAI_UI_STYLE is not set " elif self.theme == u"简约风格": each = "CONFIG_SUPPORT_CAI_UI_STYLE=y " elif "CONFIG_SUPPORT_MSTAR_UI_STYLE" in each: if self.theme == u"MSTAR风格": each = "CONFIG_SUPPORT_MSTAR_UI_STYLE=y " elif self.theme == u"简约风格": each = "# CONFIG_SUPPORT_MSTAR_UI_STYLE is not set " elif "CONFIG_SUPPORT_KK_SIMPLIFIED_CHINESE" in each: each = "# CONFIG_SUPPORT_KK_SIMPLIFIED_CHINESE is not set " elif "CONFIG_SUPPORT_OSDLANGUAGE_KOREAN" in each: if "Korean" in self.language: each = "CONFIG_SUPPORT_OSDLANGUAGE_KOREAN=y " else: each = "# CONFIG_SUPPORT_OSDLANGUAGE_KOREAN is not set " elif "CONFIG_SUPPORT_CEC_TV" in each: if "NONE" in self.swCec: each = "# CONFIG_SUPPORT_CEC_TV is not set " else: each = "CONFIG_SUPPORT_CEC_TV=y CONFIG_SUPPORT_ARC=y " elif "CONFIG_OSDGAME_BOXMAN_SUPPORT" in each: if "NONE" in self.swOsdgame: each = "# CONFIG_OSDGAME_BOXMAN_SUPPORT is not set " else: each = "CONFIG_OSDGAME_BOXMAN_SUPPORT=y " elif "CONFIG_OSDGAME_HITRAT_SUPPORT" in each: if "NONE" in self.swOsdgame: each = "# CONFIG_OSDGAME_HITRAT_SUPPORT is not set " else: each = "CONFIG_OSDGAME_HITRAT_SUPPORT=y " elif "CONFIG_OSDGAME_GOBANG_SUPPORT" in each: if "NONE" in self.swOsdgame: each = "# CONFIG_OSDGAME_GOBANG_SUPPORT is not set " else: each = "CONFIG_OSDGAME_GOBANG_SUPPORT=y " elif "CONFIG_OSDGAME_TETRIS_SUPPORT" in each: if "NONE" in self.swOsdgame: each = "# CONFIG_OSDGAME_TETRIS_SUPPORT is not set " else: each = "CONFIG_OSDGAME_TETRIS_SUPPORT=y " elif "CONFIG_OSDGAME_SUDOKU_SUPPORT" in each: if "NONE" in self.swOsdgame: each = "# CONFIG_OSDGAME_SUDOKU_SUPPORT is not set " else: each = "CONFIG_OSDGAME_SUDOKU_SUPPORT=y CONFIG_OSD_GAME_SUPPORT=y " elif "CONFIG_SUPPORT_TTX" in each: if u"亚太" in self.area: each = "# CONFIG_SUPPORT_TTX is not set " else: each = "CONFIG_SUPPORT_TTX=y CONFIG_TTX_BYPASS_MODE=y CONFIG_TT15_SUPPORT=y CONFIG_TTX_FONT_SIZE_30=y CONFIG_SUPPORT_ATS=y " elif "CONFIG_SUPPORT_CAPTURE_LOGO" in each: if "NONE" in self.swCaptureLogo: each = "# CONFIG_SUPPORT_CAPTURE_LOGO is not set " else: each = "CONFIG_SUPPORT_CAPTURE_LOGO=y CONFIG_CAPTURE_LOGO_MAX_SIZE="80" " listPro.append(each) with open(strPath + '/menuconfig.config',"w") as mFile: mFile.writelines(listPro) listPro = [] if "OFF" in self.swBlueScreen: listPro.append("#define WWW_BLUSCREEN 0 ") else: listPro.append("#define WWW_BLUSCREEN 1 ") #此处创建web_www.h,后面的PQ为追加方式 with open(strPath+"/aps/include/web_www.h","w") as mFile: mFile.writelines(listPro) # 修改语言 通道 listTemp = [] listPro = [] with open(strPath+'/aps/customer/radisson/sub_customer/RAD_radisson/radisson/subcustomer_setting.h',"r") as mFile: listTemp = mFile.readlines() for each in listTemp: pat = re.compile(".*DEFAULT_SUPPORT_OSD_LANGUAGE_(w*?)s+.*") if pat.search(each): if pat.search(each).group(1) in self.language: each = "#define DEFAULT_SUPPORT_OSD_LANGUAGE_%s 1 " % (pat.search(each).group(1)) else: each = "#define DEFAULT_SUPPORT_OSD_LANGUAGE_%s 0 " % (pat.search(each).group(1)) elif "DEFAULT_CURRENT_LANGUAGE" in each: each = "#define DEFAULT_CURRENT_LANGUAGE APP_OSDLANG_%s " % self.deLanguage.upper() elif "DEFAULT_SUPPORT_SOURCE_TYPE_AV2" in each: if "AV2" in self.source: each = "#define DEFAULT_SUPPORT_SOURCE_TYPE_AV2 1 " else: each = "#define DEFAULT_SUPPORT_SOURCE_TYPE_AV2 0 " elif re.search(".*DEFAULT_SUPPORT_SOURCE_TYPE_YPBPR[^d].*",each): if "YPBPR" in self.source: each = "#define DEFAULT_SUPPORT_SOURCE_TYPE_YPBPR 1 " else: each = "#define DEFAULT_SUPPORT_SOURCE_TYPE_YPBPR 0 " listPro.append(each) with open(strPath + '/aps/customer/radisson/sub_customer/RAD_radisson/radisson/subcustomer_setting.h',"w") as mFile: mFile.writelines(listPro) # 功放 开机状态 listTemp = [] with open(strPath + "/aps/customer/radisson/sub_customer/RAD_radisson/radisson/boot_setting.h","r") as mFile: listFile = mFile.readlines() for each in listFile: if "DEFAULT_AMP_POWER" in each: each = "#define DEFAULT_AMP_POWER %s " %(self.speaker) elif "DEFAULT_AC_AUTO_POWERON_STATUS" in each: each = "#define DEFAULT_AC_AUTO_POWERON_STATUS AC_AUTO_%s " %(self.powerState) listTemp.append(each) with open(strPath + "/aps/customer/radisson/sub_customer/RAD_radisson/radisson/boot_setting.h","w") as mFile: mFile.writelines(listTemp) class CPanel: def __init__(self,data): self.panelID = data[0] self.panelName = data[1] self.reverse = data[2] self.pwm = data[3] self.mA = data[4] self.deValue = data[5] self.lvdsMap = data[6] self.freeRun = data[7] def __str__(self): return "Panel[%s]-reverse[%s]-pwm[%s]-mA[%s]-deValue[%s]-lvdsMap[%s]-freeRun[%s]" %(self.panelName,self.reverse,self.pwm,self.mA,self.deValue,self.lvdsMap,self.freeRun) def config(self,strPath): listPro = [] #修改倒屏 with open(strPath+"/aps/customer/radisson/sub_customer/RAD_radisson/radisson/boot_setting.h","r") as mFile: listTemp = mFile.readlines() for each in listTemp: if "PANEL_INVERT" in each: each = "#define PANEL_INVERT %d " % (1 if self.reverse == "ON" else 0) listPro.append(each) with open(strPath+"/aps/customer/radisson/sub_customer/RAD_radisson/radisson/boot_setting.h","w") as mFile: mFile.writelines(listPro) listPro = [] #修改FREEFUN/LVDSMAP with open(strPath+"/aps/customer/radisson/public/panel/%s/panel_setting.h" % self.panelName,"r") as mFile: listTemp = mFile.readlines() for each in listTemp: if "PANEL_INTERFACE" in each: each = "#define PANEL_INTERFACE %d " %(1 if self.freeRun == "ON" else 0) elif "PANEL_LVDS_TYPE" in each: if self.lvdsMap == "JEIDA": each = "#define PANEL_LVDS_TYPE 0 " elif self.lvdsMap == "VESA(LSB)": each = "#define PANEL_LVDS_TYPE 1 " elif self.lvdsMap == "VESA(MSB)": each = "#define PANEL_LVDS_TYPE 2 " listPro.append(each) with open(strPath+"/aps/customer/radisson/public/panel/%s/panel_setting.h" % self.panelName,"w") as mFile: mFile.writelines(listPro) #修改LED背灯电流 listPro = [] with open(strPath + "/menuconfig.config", "r") as mFile: listTemp = mFile.readlines() for each in listTemp: if "CONFIG_INPUT_CURRENT_BL" in each: each = "CONFIG_INPUT_CURRENT_BL=%s " % self.mA listPro.append(each) with open(strPath + "/menuconfig.config", "w") as mFile: mFile.writelines(listPro) class CKeypad: def __init__(self,data): self.keypadName = data[0] self.keyType = data[1] self.k0 = data[2] self.k1 = data[3] self.k2 = data[4] self.k3 = data[5] self.k4 = data[6] self.k5 = data[7] self.k6 = data[8] self.k7 = data[9] self.data = data def __str__(self): return ("keypadName[%s]-[%s]-[%s]-[%s]-[%s]-[%s]-[%s]-[%s]-[%s]-[%s]" %(self.keypadName,self.keyType,self.k0,self.k1,self.k2,self.k3,self.k4,self.k5,self.k6,self.k7)).encode("utf-8") def config(self,strPath,strBoard): keypadPath = strPath + "/aps/customer/radisson/%s/adaptable/keypad_mapping_table.c" %strBoard with open(keypadPath, "r") as mFile: listTemp = mFile.readlines() listPro = [] listTemp1 = [] bWebMark = False mapKey = { "POWER": "POWER", "MENU": "MENU", "SOURCE": "SOURCE", "CH+": "UP", "CH-": "DOWN", "VOL+": "RIGHT", "VOL-": "LEFT", "NULL":"MAX" } for each in listTemp: if "WWW" in each: bWebMark = True listPro.append(each) continue if bWebMark: listTemp1.append(each) else: listPro.append(each) lineNumber = 0 keyDataNumber = 2 ADC0_POWER_ON_KEY = 0x01 for each in listTemp1: if "#" in each: break pat = re.compile("(.*{s*d+,+s*(.*?),+s*)UI_EVENT_KEYPAD_(w*).*") if pat.search(each): if "POWER" in mapKey[self.data[keyDataNumber]]: ADC0_POWER_ON_KEY = pat.search(each).group(2) listTemp1[lineNumber] = pat.search(each).group(1)+"UI_EVENT_KEYPAD_%s }, " %(mapKey[self.data[keyDataNumber]]) keyDataNumber = keyDataNumber+1 lineNumber = lineNumber + 1 listPro = listPro+listTemp1 with open(keypadPath, "w") as mFile: mFile.writelines(listPro) #修改POWER键 listPro = [] listTemp = [] keypadPath = strPath + "/aps/customer/radisson/%s/adaptable/keypad_mapping_table.h" % strBoard with open(keypadPath, "r") as mFile: listTemp = mFile.readlines() for each in listTemp: if "KEYPAD_PWR_ON_KEY" in each: each = "#define KEYPAD_PWR_ON_KEY (ADC1_POWER_ON_KEY|%s) " %(ADC0_POWER_ON_KEY) listPro.append(each) with open(keypadPath, "w") as mFile: mFile.writelines(listPro) class CLogo: def __init__(self,data): self.logoID = data[0] self.userName = data[1] self.logoName = data[2] self.logoType = data[3] self.logoDate = data[4] self.logoFile = data[5] def __str__(self): return ("Logo[%d]-userName[%s]-logoName[%s]-logoType[%s]" %(self.logoID,self.userName,self.logoName,self.logoType)).encode("utf-8") def config(self,strPath): listTemp = [] if len(self.logoFile): with open(strPath + "/aps/customer/radisson/sub_customer/RAD_radisson/radisson/logo/title_logo.jpg","wb") as mFile: mFile.write(self.logoFile) with open(strPath + "/aps/customer/radisson/sub_customer/RAD_radisson/radisson/boot_setting.h","r") as mFile: listFile = mFile.readlines() for each in listFile: if "DEFAULT_POWER_SHOW_LOGO" in each: if len(self.logoFile): each = "#define DEFAULT_POWER_SHOW_LOGO POWER_SHOW_LOGO " else: each = "#define DEFAULT_POWER_SHOW_LOGO POWER_HIDE_LOGO " listTemp.append(each) else: listTemp.append(each) with open(strPath + "/aps/customer/radisson/sub_customer/RAD_radisson/radisson/boot_setting.h","w") as mFile: mFile.writelines(listTemp) class CPq: def __init__(self,data): self.pqName = data[0] self.pqData = data[1].split(",") def __str__(self): return ("pqName[%s]" %(self.pqName)).encode("utf-8") def config(self,strPath,dbSource): listPro = [] for i in range(len(dbSource)): strData = "#define COLOR_TEMP_TYPE_%s_WWW " %(dbSource[i]) for j in range(3): strData += "{" + ','.join(self.pqData[i*18+j*6:i*18+j*6+6]) + "}," strData += " " listPro.append(strData) listCurve = self.pqData[len(dbSource)*18:] for i in range(len(dbSource)): strData = "#define CURVE_TYPE_%s_WWW " %(dbSource[i]) for j in range(5): strData += "{" + ','.join(listCurve[i*25+j*5:i*25+j*5+5]) + "}," strData += " " listPro.append(strData) listPro.append(" ") #content table增加了蓝屏,此处为追加方式 with open(strPath+"/aps/include/web_www.h","a") as mFile: mFile.writelines(listPro) def config(self): listPro = [] #配置mconfig # 板型 屏参 遥控 listPro.append('CONFIG_CUSTOMER_NAME="radisson" ') listPro.append('CONFIG_SUBCUSTOMER_NAME="RAD_radisson" ') listPro.append('CONFIG_SUBSUBCUSTOMER_NAME="radisson" ') if self.tContent.theme == u"蓝色经典": listPro.append('CONFIG_APP_FOLDER_NAME="formal" ') listPro.append('CONFIG_PROJECT_NAME="%s___formal___ATV" ' % self.boardName) else: listPro.append('CONFIG_APP_FOLDER_NAME="atv_project" ') listPro.append('CONFIG_PROJECT_NAME="%s___atv_project___ATV" ' % self.boardName) #根据数据库配置 板型 屏参 listPro.append('CONFIG_MODEL_BOARD_NAME="%s" ' % self.boardName) listPro.append("CONFIG_PANEL_TYPE_="%s" " % (self.panelName)) listPro.append("CONFIG_PANEL_TYPE_DEFAULT_FOLDER="%s" " % self.panelName) #设置默认的EDID pat = re.compile(".*?_(d+)[xX](d+)") if pat.search(self.panelName): listPro.append("CONFIG_DDC_DeafaultTable_%sx%s=y " % (pat.search(self.panelName).group(1), pat.search(self.panelName).group(2))) for each in set(self.irName): listPro.append("CONFIG_%s=y " % (each)) with open(self.sourcePath + "/mconfig.config", "w") as mFile: mFile.writelines(listPro) #拷贝menuconfig boardconfig if os.path.exists(self.webPath + '/scripts/menuconfig.config'): shutil.copy(self.webPath + '/scripts/menuconfig.config', self.sourcePath + '/menuconfig.config') boardConfigPath = self.sourcePath + '/aps/customer/radisson/%s/boardconfig.config' %(self.boardName) print boardConfigPath if os.path.exists(boardConfigPath): shutil.copy(boardConfigPath, self.sourcePath + '/boardconfig.config') def info(self): return [self.compileId,self.userName,self.boardName,self.panelName,self.irName,self.contentId,self.complieDate,self.compileState] def __str__(self): return ("compileId[%d]-[%s]-[%s]-[%s]-[%s]-[%d]" %(self.compileId,self.userName,self.boardName,self.panelName,self.irName,self.contentId)).encode("utf-8") def log(self): #创建实例后才能调用 printLog(self) printLog(self.tContent) printLog(self.tPanel) printLog(self.tLogo) printLog(self.tKeypad) printLog(self.tPq) def sendMail(self): listDir = os.listdir(self.sourcePath + "/mergedir") listBinFile = [x for x in listDir if "RR8501" in x] mail = CSendMail() strIr = "" for strEach in self.irName: strIr = strIr + " " + strEach strTitle = '[WEB][%s][%s][%s][%s]' % (self.userName, self.boardName,self.panelName,strIr) if len(listBinFile): # 编译完成,发送邮件 if g_nullDo == False: ret = mail.send(mail.username, self.userMail, strTitle, u" 感谢您对我们公司的支持,如果有问题请及时与我们联系!", self.sourcePath + "/mergedir/" + listBinFile[0]) # if ret != 'OK': # printLog ret # sys.exit(4) # else: # printLog "Mail %s send ok" %(toAddress) else: ret = mail.send(mail.username, self.webErrorMail, strTitle+" Compile Error", u" 编译错误请尽快查看!") def genTableInstance(self,cur): sql = 'select * from Content where contentID=(select contentID from Compile where compileID=%d)' % self.compileId cur.execute(sql) data = cur.fetchone() self.tContent = self.CContent(data) sql = 'select * from Panel where panelID = %d' % self.tContent.panelID cur.execute(sql) data = cur.fetchone() self.tPanel = self.CPanel(data) sql = 'select * from Logo where logoName = "%s"' % self.tContent.logoName cur.execute(sql) data = cur.fetchone() self.tLogo = self.CLogo(data) sql = 'select * from Keypad where keypadName = "%s"' % self.tContent.keypadName cur.execute(sql) data = cur.fetchone() self.tKeypad = self.CKeypad(data) sql = 'select * from PQ where pqName = "%s"' % self.tContent.pqName cur.execute(sql) data = cur.fetchone() self.tPq = self.CPq(data) self.log() def compile(self): if g_nullDo == False: os.system('cd %s; make WWW=%d clean &> /dev/null; make WWW=%d -j &> /dev/null' % (self.sourcePath,self.compileId,self.compileId)) #os.system('cd %s; make clean&> /dev/null; make -j' % (self.sourcePath)) def finishTask(self,cur): # 更新任务标记 if g_nullDo == True: return listDir = os.listdir(self.sourcePath + "/mergedir") listBinFile = [x for x in listDir if "RR8501" in x] #编译不通过,再有一次编译机会 if len(listBinFile) == 0: self.compile() listDir = os.listdir(self.sourcePath + "/mergedir") listBinFile = [x for x in listDir if "RR8501" in x] if len(listBinFile): with open(self.sourcePath + "/mergedir/" + listBinFile[0], "rb") as mFile: bin = mFile.read() strSql = 'update Compile set binFile=%s where compileID=%s' param = ((MySQLdb.Binary(bin)), self.compileId) cur.execute(strSql, param) cur.execute('update Compile set compileState=1 where compileID=%s', self.compileId) os.system('cd %s; make clean &> /dev/null' % (self.sourcePath)) #编译后清楚BIN文件,不能省略 #self.inform(True) else: cur.execute('update Compile set compileState=2 where compileID=%s', self.compileId) printLog("---------------->error<----------------") #self.inform(False) def handle(self,cur): self.genTableInstance(cur) if os.path.exists(self.sourcePath): self.config() # Compile Table 生成mconfig menuconfig 板型 屏参 遥控 self.tContent.config(self.sourcePath) # Content Table self.tPanel.config(self.sourcePath) # Panel Table self.tLogo.config(self.sourcePath) # LOGO Talbe self.tKeypad.config(self.sourcePath,self.boardName) # Keypad Table self.tPq.config(self.sourcePath,self.dbSource) # PQ Table self.compile() # 编译 CODE self.sendMail() # 发送邮件 self.finishTask(cur) # 更新任务标记 上传文件 class CSendMail: def __init__(self, smtpServer="smtp.163.com", username="henry_rad@163.com", password="radisson123"): #rad_radisson@163.com pwdradisson self.smtpServer = smtpServer self.username = username self.password = password def genMsgInfo(self, fromAddress, toAddress, subject, content, fileList, subtype='plain', charset='gb2312'): msg = MIMEMultipart() msg['From'] = fromAddress msg['To'] = toAddress msg['Date'] = Utils.formatdate(localtime=1) msg['Message-ID'] = Utils.make_msgid() # 标题 if subject: msg['Subject'] = subject # 内容 if content: body = MIMEText(content, subtype, charset) msg.attach(body) # 附件 if fileList: listArr = fileList.split(',') for item in listArr: # 文件是否存在 if os.path.isfile(item) == False: continue att = MIMEText(open(item).read(), 'base64', 'gb2312') att["Content-Type"] = 'application/octet-stream' # 这里的filename邮件中显示什么名字 filename = os.path.basename(item) att["Content-Disposition"] = 'attachment; filename=' + filename msg.attach(att) return msg.as_string() def send(self, fromAddress, toAddress, subject=None, content=None, fileList=None, subtype='plain', charset='gb2312'): try: server = smtplib.SMTP(self.smtpServer) # 登录 try: server.login(self.username, self.password) except smtplib.SMTPException, e: return "ERROR:Authentication failed:", e # 发送邮件 server.sendmail(fromAddress, toAddress.split(',') , self.genMsgInfo(fromAddress, toAddress, subject, content, fileList, subtype, charset)) # 退出 server.quit() except (socket.gaierror, socket.error, socket.herror, smtplib.SMTPException), e: return "ERROR:Your mail send failed!", e return 'OK' def daemonize(stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): try: pid = os.fork() # 父进程(会话组头领进程)退出,这意味着一个非会话组头领进程永远不能重新获得控制终端。 if pid > 0: sys.exit(0) # 父进程退出 except OSError, e: sys.stderr.write("fork #1 failed: (%d) %s " % (e.errno, e.strerror)) sys.exit(1) # 从父进程脱离 os.chdir("/") # chdir确认进程不保持任何目录于使用状态,否则不能umount一个文件系统。也可以改变到对于守护程序运行重要的文件所在目录 os.umask(0) # 调用umask(0)以便拥有对于写的任何东西的完全控制,因为有时不知道继承了什么样的umask。 os.setsid() # setsid调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。 # 执行第二次fork try: pid = os.fork() if pid > 0: sys.exit(0) # 第二个父进程退出 except OSError, e: sys.stderr.write("fork #2 failed: (%d) %s " % (e.errno, e.strerror)) sys.exit(1) # 进程已经是守护进程了,重定向标准文件描述符 for f in sys.stdout, sys.stderr: f.flush() si = open(stdin, 'r') so = open(stdout, 'a+') se = open(stderr, 'a+', 0) os.dup2(si.fileno(), sys.stdin.fileno()) # dup2函数原子化关闭和复制文件描述符 os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(se.fileno(), sys.stderr.fileno()) def fun_parse_InputParam(): global g_daemonMode global g_nullDo global g_bTestMode try: opts, args = getopt.getopt(sys.argv[1:], 'hdnt') except getopt.GetoptError, err: #print str(err) sys.exit() for op, value in opts: if op == "-d": g_daemonMode = 1 elif op == "-n": g_nullDo = 1 elif op == "-h": sys.exit() else: printLog("unhandled option") sys.exit() def printLog(data): print data sys.stdout.flush() def dbHandle(): conn = MySQLdb.connect( host='localhost', port=3306, user='root', passwd='rad_radisson', db='webCompile', charset="utf8" ) cur = conn.cursor() printLog('Daemon started with pid %d ' % os.getpid()) while True: cur.execute("select * from Compile where compileState = 0") info = cur.fetchall() for data in info: task = CTask(data) task.handle(cur) conn.commit() if g_daemonMode: time.sleep(60) else: break conn.commit() cur.close() conn.close() if __name__ == "__main__": fun_parse_InputParam() if g_daemonMode: daemonize('/dev/null', '/tmp/daemon_stdout.log', '/tmp/daemon_error.log') dbHandle()