def connDb(self): ''' 连接数据库 ''' try: self.dbObj = ClassDb() self.dbObj.connect(host=dbHost,port=dbPort,user=dbUser,passwd=dbPass,db=dbName,charset="utf8") finally: pass
class RunCmd(): ''' 定义 执行命令行 类, 传入一个队列对象 ''' def __init__(self, iq): self.sqlRes = iq self.sOption = " -i /root/.ssh/id_rsa -o StrictHostKeyChecking=no -o ConnectTimeout=30 " def connDb(self): ''' 连接数据库 ''' try: self.dbObj = ClassDb() self.dbObj.connect(host=dbHost,port=dbPort,user=dbUser,passwd=dbPass,db=dbName,charset="utf8") finally: pass def upStatus(self, id, status): ''' 更新已执行状态,需要传入2个参数 1: 数据库记录编号 2: 需要更新的状态值 ''' try: ## 更新状态SQL sql = "update dbtx_cmd_execute set iStatus=%s,dExecuteTime = now() where iId=%s" % (str(status), str(id)) self.dbObj.execute(sql) finally: pass def upReturnContents(self, id, status, returnContens): ''' 更新命令执行的状态,需要传入3个参数 1: 数据库记录编号 2: 状态 3: 执行命令的返回值 ''' try: ## 更新数据库SQL sql = "update dbtx_cmd_execute set iStatus=%s,sReturnContents='%s',dExecutedTime=now() where iId = %s" % (str(status), addslashes(str(returnContens)),str(id)) self.dbObj.execute(sql) finally: pass def getDependPidStatus(self, dependID): ## 获取依赖任务的执行状态 if not dependID: ## 如果dependID为空, 表示没有依赖任务, 命令可直接运行, 返回True return True try: ## 查询依赖任务状态的SQL sql = "select iStatus from dbtx_cmd_execute where iId = %s" % str(self.dependID) self.dbObj.execute(sql) result = self.dbObj.fetchall() iStatus = result[0]['iStatus'] if iStatus == 3: ## 状态为3, 表示依赖任务已完成, 返回True return True elif iStatus == '': return True elif iStatus is None: return True else: return False finally: pass def doWork(self): ''' 传入一个SQL语句队列对象 参数说明 self.id: 数据库记录编号,用于回填执行结果 self.cmd: 命令 self.type: 命令类型 self.ip: 需要执行该命令的IP地址 self.dependID: 依赖的PID, 即需要等该PID执行完以后才开始运行 ''' self.id = self.sqlRes['iId'] self.cmd = str(self.sqlRes['sCmd']) self.type = self.sqlRes['eType'] self.dependID = self.sqlRes['iDependID'] self.ip = self.sqlRes['sIP'] self.sshPort = self.sqlRes['sSSHport'] self.connDb() ## 连接数据库 if self.dependID: if not self.getDependPidStatus(self.dependID): return ## 执行待执行的命令 ## 定义ssh连接参数 ## 按类型执行命令 if self.type == 'local': ## 即为 本地命令,在中央服本地运行 fullCmd = self.cmd elif self.type == 'remote': ## 即为 远程命令 fullCmd = 'ssh -p%s %s root@%s "%s"' % (self.sshPort,self.sOption,self.ip,self.cmd) elif self.type == 'scp': ## SCP推送文件/目录 tmpCmd = self.cmd.split() srcFile = tmpCmd[0] dstFile = tmpCmd[1] fullCmd = 'scp -r -P%s %s%s root@%s:%s' % (self.sshPort,self.sOption,srcFile,self.ip,dstFile) elif self.type == 'scp_back': ## 从远程服务器拉取文件/目录 tmpCmd = self.cmd.split() srcFile = tmpCmd[0] dstFile = tmpCmd[1] fullCmd = 'scp -r -P%s %s root@%s:%s %s' % (self.sshPort,self.sOption,self.ip,srcFile,dstFile) elif self.type == 'rsync': ## rsync推送文件/目录到远程服务器 tmpCmd = self.cmd.split() srcFile = tmpCmd[0] dstFile = tmpCmd[1] fullCmd = 'rsync -az -e "ssh -p%s %s" %s root@%s:%s' % (self.sshPort,self.sOption,srcFile,self.ip,dstFile) else: ## 否则为不支持的命令类型 saveLog("你输入的命令:%s 不在本机支持的命令类型范围内,请重新输入." % (fullCmd)) print "你输入的命令:%s 不在本机支持的命令类型范围内,请重新输入." % (fullCmd) return ## 开始执行命令 saveLog("%s 开始执行." % fullCmd) self.upStatus(self.id, 2) ## 状态置为2, 即正在运行... try: ssh_master(self.ip) except Exception, err: saveLog("创建 ssh socket 失败: %s" % str(err)) try: p = subprocess.Popen(fullCmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) out, errInfo = p.communicate() ## 返回一个元组,元组第一个元素为标准输出,第二个元素为标准错误输出 if p.returncode != 0: ## 如果stderr不为空,表示命令运行有误,状态置为4 stat = 4 else: stat = 3 ## 运行成功,状态置为3 except Exception, err: saveLog("执行命令,等待命令返回值发生未知错误. %s --- %s" % (str(err), type(self.cmd)))