hch
2019-02-27 f473d3c18a3aa6c4c0cd98f9396e488676424f4c
6282 【前端】【2.0】封魔之地的飞跃功能

远程重读配置,开关服;报错汇报等
10个文件已修改
15个文件已添加
6388 ■■■■■ 已修改文件
ServerPython/CoreServerGroup/GameServer/GameServerScript.ini 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/EventReport.py 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/GMT_ReloadConfig.py 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/EventReport.py 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tool/RemoteTool/RemoteServer/bottle.py 4403 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tool/RemoteTool/RemoteServer/config.ini 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tool/RemoteTool/RemoteServer/control.py 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tool/RemoteTool/RemoteServer/controlLog.txt 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tool/RemoteTool/RemoteServer/key.txt 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tool/RemoteTool/RemoteServer/lib/CommFunc.py 371 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tool/RemoteTool/RemoteServer/lib/DBController.py 516 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tool/RemoteTool/RemoteServer/lib/ReadConfig.py 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tool/RemoteTool/RemoteServer/lib/TimeRotatingPathFileHandler.py 155 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tool/RemoteTool/RemoteServer/lib/__init__.py 补丁 | 查看 | 原始文档 | blame | 历史
Tool/RemoteTool/RemoteServer/lib/mylog.py 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tool/RemoteTool/RemoteServer/main.py 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tool/RemoteTool/RemoteServer/qufu.txt 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tool/RemoteTool/RemoteServer/webapp.py 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/GameServerScript.ini
@@ -25,7 +25,14 @@
ClassName = LoadPyGameData
FuncName = LoadPyGameData
;GameServer运行状态
[ChangeGameServerState]
ScriptName = GameWorldLogic\GameWorldProcess.py
Writer = Alee
Releaser = Alee
RegType = 1
ClassName = ChangeGameServerState
FuncName = ChangeGameServerState
;关服处理
[BeforeClose] 
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
@@ -15049,6 +15049,66 @@
#------------------------------------------------------
#B4 0B 根据类型来决定移动的方式 #tagCMMoveByType
class  tagCMMoveByType(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("PosX", c_ushort),    # 目标X
                  ("PosY", c_ushort),    # 目标Y
                  ("MoveType", c_ubyte),    #移动方式
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB4
        self.SubCmd = 0x0B
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xB4
        self.SubCmd = 0x0B
        self.PosX = 0
        self.PosY = 0
        self.MoveType = 0
        return
    def GetLength(self):
        return sizeof(tagCMMoveByType)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''//B4 0B 根据类型来决定移动的方式 //tagCMMoveByType:
                                Cmd:%s,
                                SubCmd:%s,
                                PosX:%d,
                                PosY:%d,
                                MoveType:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.PosX,
                                self.PosY,
                                self.MoveType
                                )
        return DumpString
m_NAtagCMMoveByType=tagCMMoveByType()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMMoveByType.Cmd,m_NAtagCMMoveByType.SubCmd))] = m_NAtagCMMoveByType
#------------------------------------------------------
#B4 02 对象击退 #tagCMNPCBeatBack
class  tagCMNPCPos(Structure):
ServerPython/CoreServerGroup/GameServer/Script/EventReport.py
@@ -109,8 +109,12 @@
        RegionName = GameWorld.GetPlayerServerSID(curPlayer)
        
    else:
        # 合服情况,玩家取自己服发送,非玩家数据按指定平台配置发,没有则取配置主服
        RegionName = 's%s'%GameWorld.GetPlayerMainServerID(OperatorID)
        # 合服情况,玩家取自己服发送,非玩家数据按指定平台配置发
        sid = GameWorld.GetPlayerMainServerID(OperatorID)
        if not sid:
            GameWorld.ErrLog("GetPlayerMainServerID: %s-%s"%(OperatorID, sid))
            return
        RegionName = 's%s'%sid
        
    getUrl = "%s?ProductID=%s&OperatorID=%s&RegionName=%s&EventID=%s%s&Time=%s&%s"%(\
             ReportUrl, ProductID, OperatorID, RegionName, eventActionID, playerInfo,
ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/GMT_ReloadConfig.py
New file
@@ -0,0 +1,33 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#
##@package GMT_ReloadConfig
#
# @todo: GM 重读配置
#
# @author: Alee
# @date 2019-2-21 下午08:16:16
# @version 1.0
#
# @note:
#
#---------------------------------------------------------------------
"""Version = 2014-05-17 12:30"""
#导入
import GMCommon
import ReadChConfig
#---------------------------------------------------------------------
## 执行逻辑
#  @param curPlayer 当前玩家
#  @param gmCmdDict: 命令字典
#  @return None
#  @remarks 函数详细说明.
def OnExec(orderId, gmCmdDict):
    ReadChConfig.ReloadConfig()
    # 回复
    GMCommon.GMCommandResult(orderId, gmCmdDict, GMCommon.Def_Success)
    return
ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py
@@ -437,15 +437,19 @@
def GetPlatform():
    return ReadChConfig.GetPyMongoConfig("platform", "PlatformName")
##获得当前服务器ID
# @param 无
# @return
def GetServerID():
    return ToIntDef(GetServerSID()[1:], 0)
#===============================================================================
# ##获得当前服务器ID
# # @param 无
# # @return
# def GetServerID():
#    return ToIntDef(GetServerSID()[1:], 0)
#===============================================================================
def GetServerSID():
    ##获得当前服务器ID, 带s的
    return ReadChConfig.GetPyMongoConfig("platform", "ServerID")
#===============================================================================
# def GetServerSID():
#    ##获得当前服务器ID, 带s的
#    return ReadChConfig.GetPyMongoConfig("platform", "ServerID")
#===============================================================================
Def_AccID_Split_Sign = "@"
@@ -470,7 +474,7 @@
    mainServerID = ToIntDef(ReadChConfig.GetPyMongoConfig("platform", "%sMainServerID" % accIDPlatform), None)
    if mainServerID != None:
        return mainServerID
    return GetServerID()
    return 0
#===============================================================================
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py
@@ -1426,6 +1426,10 @@
    SendMapCommMapLinePlayerCount(True) # 同步一次普通地图线路人数信息
    #随机假仙盟
    PlayerFamily.RandomFakeFamily()
    # 记录服务器是否正常开启完毕
    getUrl = ReadChConfig.GetPyMongoConfig("EventReport", "OpenStateUrl") + "?Type=MapInit&MapCount=%s"%GameWorld.GetGameWorld().GetGameMapManager().GetCount()
    GameWorld.GetGameWorld().EventReport_EventReport("", "", "", "", 0, getUrl)
    return
## 服务器合服首次启动数据加载处理
@@ -1832,14 +1836,27 @@
    gameMapManager = GameWorld.GetGameWorld().GetGameMapManager()
    
    curMap = gameMapManager.Find(mapServerPack.GetRouteServerIndex(), mapServerPack.GetMapID())
    if curMap == None:
        return
    
    if mapServerPack.GetState() not in [0,1,2,3] and curMap.GetState() != mapServerPack.GetState():
        # 记录服务器是否正常开启完毕, 避免重复发送
        GameWorld.DebugLog("MapServer_RunningStateRefresh--_%s"%([mapServerPack.GetState(), curMap.GetState(), mapServerPack.GetMapID(), curMap.GetID()]))
        SendGameError("MapError")
    curMap.SetState(mapServerPack.GetState())
    curMap.SetRefreshTick(tick)
    return
def SendGameError(state):
    getUrl = ReadChConfig.GetPyMongoConfig("EventReport", "OpenStateUrl")
    groupID = ReadChConfig.GetPyMongoConfig("platform", "GroupID")
    userDBName = ReadChConfig.GetPyMongoConfig("connect", "USER_DB_NAME")
    getUrl = getUrl + "?Type=%s&groupID=%s&userDBName=%s"%(state, groupID, userDBName)
    GameWorld.GetGameWorld().EventReport_EventReport("", "", "", "", 0, getUrl)
## 刷新地图服务器状态, 如果1分钟没有状态回报, 刷新为消失状态
#  @param tick 当前时间
#  @return None
@@ -1851,6 +1868,7 @@
    gameMapManager = GameWorld.GetGameWorld().GetGameMapManager()
    
    isSendMapClose = False
    for i in range(0, gameMapManager.GetCount()):
        curMap = gameMapManager.GetAt(i)
@@ -1861,8 +1879,12 @@
        if tick - curMap.GetRefreshTick() < ChConfig.Def_Tick_MapServer_MssNone:
            #间隔未到
            continue
        curMap.SetState(IPY_GameServer.mssNone)
        if not isSendMapClose:
            # 避免多地图发送过多邮件, 如关服的时候
            SendGameError("MapDisconnect")   # 状态报告
            isSendMapClose = True
    return
#---------------------------------------------------------------------
@@ -1914,3 +1936,10 @@
    GameWorld.Log("通知C++关服!")
    GameWorld.GetGameWorld().OnServerClose()
    
def ChangeGameServerState(state):
    # 只接收大于等于mssPyError
    GameWorld.DebugLog("ChangeGameServerState:%s"%state)
    SendGameError("GameServerError")
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -369,9 +369,9 @@
PacketSubCMD_5=0x26
PacketCallFunc_5=QueryFamilyArrestAwardReceiveState
PacketCMD_6=
PacketSubCMD_6=
PacketCallFunc_6=
PacketCMD_6=0xB4
PacketSubCMD_6=0x0B
PacketCallFunc_6=OnMoveByType
PacketCMD_7=0xA2
PacketSubCMD_7=0x13
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -15049,6 +15049,66 @@
#------------------------------------------------------
#B4 0B 根据类型来决定移动的方式 #tagCMMoveByType
class  tagCMMoveByType(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("PosX", c_ushort),    # 目标X
                  ("PosY", c_ushort),    # 目标Y
                  ("MoveType", c_ubyte),    #移动方式
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB4
        self.SubCmd = 0x0B
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xB4
        self.SubCmd = 0x0B
        self.PosX = 0
        self.PosY = 0
        self.MoveType = 0
        return
    def GetLength(self):
        return sizeof(tagCMMoveByType)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''//B4 0B 根据类型来决定移动的方式 //tagCMMoveByType:
                                Cmd:%s,
                                SubCmd:%s,
                                PosX:%d,
                                PosY:%d,
                                MoveType:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.PosX,
                                self.PosY,
                                self.MoveType
                                )
        return DumpString
m_NAtagCMMoveByType=tagCMMoveByType()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMMoveByType.Cmd,m_NAtagCMMoveByType.SubCmd))] = m_NAtagCMMoveByType
#------------------------------------------------------
#B4 02 对象击退 #tagCMNPCBeatBack
class  tagCMNPCPos(Structure):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/EventReport.py
@@ -128,8 +128,12 @@
        RegionName = GameWorld.GetPlayerServerSID(curPlayer)
        
    else:
        # 合服情况,玩家取自己服发送,非玩家数据按指定平台配置发,没有则取配置主服
        RegionName = 's%s'%GameWorld.GetPlayerMainServerID(OperatorID)
        # 合服情况,玩家取自己服发送,非玩家数据按指定平台配置发
        sid = GameWorld.GetPlayerMainServerID(OperatorID)
        if not sid:
            GameWorld.ErrLog("GetPlayerMainServerID: %s-%s"%(OperatorID, sid))
            return
        RegionName = 's%s'%sid
    if eventParam:
        eventParam = "&%s"%eventParam
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py
@@ -1041,15 +1041,19 @@
def GetPlatform():
    return ReadChConfig.GetPyMongoConfig("platform", "PlatformName")
##获得当前服务器ID
# @param 无
# @return
def GetServerID():
    return ToIntDef(GetServerSID()[1:], 0)
#===============================================================================
# ##获得当前服务器ID
# # @param 无
# # @return
# def GetServerID():
#    return ToIntDef(GetServerSID()[1:], 0)
#===============================================================================
def GetServerSID():
    ##获得当前服务器ID, 带s的
    return ReadChConfig.GetPyMongoConfig("platform", "ServerID")
#===============================================================================
# def GetServerSID():
#    ##获得当前服务器ID, 带s的
#    return ReadChConfig.GetPyMongoConfig("platform", "ServerID")
#===============================================================================
def GetCreateRoleDays(curPlayer):
    # 获取创角第几天
@@ -1080,7 +1084,7 @@
    mainServerID = ToIntDef(ReadChConfig.GetPyMongoConfig("platform", "%sMainServerID" % accIDPlatform), None)
    if mainServerID != None:
        return mainServerID
    return GetServerID()
    return 0
#===============================================================================
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -1823,6 +1823,42 @@
    return
#===============================================================================
# //B4 14 根据类型来决定移动的方式 #tagMCMoveByType
#
# struct    tagMCMoveByType
# {
#    tagHead        Head;
#    DWORD        ID;    //玩家ID
#    WORD        PosX;    // 目标X
#    WORD        PosY;    // 目标Y
#    BYTE        MoveType;    //移动方式
# };
#===============================================================================
def OnMoveByType(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    #玩家移动通用检查
    if not __CheckPlayerCanMove(curPlayer):
        return
    #先验证目标点是否合法
    if not GameWorld.GetMap().CanMove(clientData.PosX, clientData.PosY):
        return
    curPlayer.StopMove()
    curPlayer.ChangePos(clientData.PosX, clientData.PosY)
    sendPack = ChPyNetSendPack.tagMCMoveByType()
    sendPack.Clear()
    sendPack.ID = curPlayer.GetID()
    sendPack.ObjType = curPlayer.GetGameObjType()
    sendPack.PosX = clientData.PosX
    sendPack.PosY = clientData.PosY
    sendPack.MoveType = clientData.MoveType
    PlayerControl.PyNotifyAll(curPlayer, sendPack, False, -1)
    return
#===============================================================================
# //B4 04 战前冲锋 #tagCMRush
# struct    tagCMRush
@@ -1856,6 +1892,14 @@
    if GameWorld.GetDist(curPlayer.GetPosX(), curPlayer.GetPosY(), clientData.PosX, clientData.PosY) > curPlayer.GetSight():
        return
    
    #玩家移动通用检查
    if not __CheckPlayerCanMove(curPlayer):
        return
    #先验证目标点是否合法
    if not GameWorld.GetMap().CanMove(clientData.PosX, clientData.PosY):
        return
    curPlayer.StopMove()
    #GameWorld.DebugLog("战前冲锋 %s %s"%([curPlayer.GetPosX(), curPlayer.GetPosY()], [clientData.PosX, clientData.PosY]))
    curPlayer.ChangePos(clientData.PosX, clientData.PosY)
Tool/RemoteTool/RemoteServer/bottle.py
New file
Diff too large
Tool/RemoteTool/RemoteServer/config.ini
New file
@@ -0,0 +1,4 @@
[Remote]
IsDebug = False
Port = 53009
Tool/RemoteTool/RemoteServer/control.py
New file
@@ -0,0 +1,134 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#
##@package
#
# @todo: 远程控制开关服
#
# @author: Alee
# @date 2019-2-20 下午05:26:59
# @version 1.0
#
# @note: 需要注意 《服务器控制台》 在开机后和关服后保持运行状态;开机可以设置随机启动,关服后可以添加命令行开启(需cd定位下路径)
# 1.控制台被链接的情况 无法有效重启
#---------------------------------------------------------------------
import urllib
import urllib2
import md5
import os
import json
import datetime
g_fileLog = None
key = "slkfjlaskjf'lasjfjj1j4r1;2j;15r1-id-ig-k1r51-0id-sfgk1=-i1-m;az01m,-k-1-i4-14-1fmm1-"
port = 53009
# 远程CMD命令
def control(url, cmdstr):
    sign = md5.md5("%s1234666%s"%(cmdstr, key)).hexdigest()
    values = {'control' : cmdstr,
              'sign' : sign }
    try:
        data = urllib.urlencode(values)
        req = urllib2.Request("http://%s:%s/control/openandclose.php"%(url, port), data)
        response = urllib2.urlopen(req, timeout=30)
        the_page = response.read()
        if not the_page:
            WriteResult( "%s:运行失败===="%url)
        else:
            WriteResult( "%s:运行成功 %s"%(url, the_page))
        response.close()
    except Exception, e:
        WriteResult("%s:运行失败, 如果是超时可能是运行慢是实际是成功,清配合其他工具或者直接远程查看 %s"%(url, str(e)))
        #WriteResult("如果是超时可能是运行慢是实际是成功,清配合其他工具或者直接远程查看")
# 只用于首次完整开服后的服务器启动查询,因为地图是最后初始化完毕,可以根据地图数据判断是否完整开启
# 地图关闭后不会改变数量,故地图有异常关闭会另外通过邮件通知
# 如果《服务器控制台》重启则无法确认开服情况
def QueryMapInit(url):
    try:
        req = urllib2.Request("http://%s:%s/control/state.php?Type=QueryMapOK"%(url, port))
        response = urllib2.urlopen(req, timeout=5)
        the_page = response.read()
        WriteResult("查询服务器 %s: %s"%(url, the_page))
        response.close()
    except Exception, e:
        WriteResult("%s:运行失败%s"%(url, str(e)))
# 重读配置,对应GMkey
def ReloadConfig(pushurl):
    # 默认端口80,有需要直接改地址
    try:
        # GM推送地址
        gmurl = "http://%s/Server/Tool.php"%(pushurl)
        gmkey = "Y25GVFoyOVFjbWtyTDJJckt5OU1OQ3RtUFQxPV"
        if not gmkey or not gmurl:
            return
        pack_data = {};
        pack_data["pack_type"] = "GMT_ReloadConfig"
        pack_data["key"] = gmkey;
        pack_data['coding'] = "utf8";
        #使用key加密
        pack_data_dict = json.dumps(pack_data)
        sign = md5.md5(pack_data_dict+gmkey).hexdigest()
        post = {}
        post['pack'] = pack_data_dict;
        post['sign'] = sign;
        result = urllib2.urlopen(gmurl, urllib.urlencode(post), 10)
        content = result.read()
        result.close()
        resultDict = json.loads( content)
        if resultDict["ResultType"] == 0:
            WriteResult( pushurl + " 重读成功!!!")
            return True
        WriteResult( pushurl+ " 重读失败")
        return False
    except Exception, e:
        WriteResult( pushurl+ " 重读失败" + str(e))
    return False
def WriteResult(msg):
    global g_fileLog
    if not g_fileLog:
        g_fileLog = open(r".\controlLog.txt", "a")
    g_fileLog.write(str(datetime.datetime.today()) + '\t' + msg + "\n")
    print msg
    return
#control("vm-mobilecom", "open")
#control("vm-mobilecom", "close")
if __name__=='__main__':
    # 服务器列表
    f = open(r'.\qufu.txt','r')
    result = raw_input("请输入字母 k.开服 g.关服 c.查看地图运行情况(首开服) r.重读配置")
    result = result.strip()
    WriteResult("==开始执行命令:%s"%result)
    if result == 'k':
        for line in f.readlines():
            control(line.strip(), "open")
    elif result == 'g':
        for line in f.readlines():
            control(line.strip(), "close")
    elif result == 'c':
        for line in f.readlines():
            QueryMapInit(line.strip())
    elif result == 'r':
        for line in f.readlines():
            ReloadConfig(line.strip())
    else:
        WriteResult("==执行错误的命令:%s"%result)
    f.close()
    if g_fileLog:
        g_fileLog.close()
    os.system('pause')
Tool/RemoteTool/RemoteServer/controlLog.txt
New file
@@ -0,0 +1,75 @@
2019-02-25 22:42:26.475000    ==开始执行命令:k
2019-02-25 22:42:28.550000    运行成功open success
2019-02-25 22:43:50.122000    ==开始执行命令:c
2019-02-25 22:44:38.373000    ==开始执行命令:c
2019-02-25 22:46:16.684000    ==开始执行命令:c
2019-02-25 22:47:46.540000    ==开始执行命令:c
2019-02-25 22:47:46.899000    运行失败HTTP Error 404: Not Found
2019-02-25 22:49:57.346000    ==开始执行命令:c
2019-02-25 22:49:57.783000    运行失败HTTP Error 404: Not Found
2019-02-25 22:51:27.670000    ==开始执行命令:c
2019-02-25 22:51:28.045000    查询服务器 vm-mobile-v8: =========地图服务器未初始化成功========
2019-02-25 22:57:58.638000    ==开始执行命令:c
2019-02-25 22:57:59.043000    查询服务器 vm-mobile-v8:
2019-02-25 23:00:11.300000    ==开始执行命令:c
2019-02-25 23:00:11.690000    查询服务器 vm-mobile-v8: ===暂无反馈,稍等后查询===
2019-02-25 23:06:52.274000    ==开始执行命令:k
2019-02-25 23:06:55.694000    运行失败<urlopen error timed out>
2019-02-25 23:13:47.721000    ==开始执行命令:c
2019-02-25 23:13:48.111000    查询服务器 vm-mobile-v8: 服务器开启完毕,地图数:1
2019-02-25 23:25:52.500000    ==开始执行命令:r
2019-02-25 23:25:53.892000    vm-mobile-v8重读成功!!!
2019-02-25 23:26:39.693000    ==开始执行命令:g
2019-02-25 23:26:40.114000    运行成功close success
2019-02-25 23:36:52.735000    ==开始执行命令:k
2019-02-25 23:36:56.147000    运行成功open success
2019-02-25 23:39:14.662000    ==开始执行命令:k
2019-02-25 23:39:15.239000    运行成功服务器已经开启,清再次确认服务器情况, EventServer.exe运行中
2019-02-25 23:42:35.603000    ==开始执行命令:k
2019-02-25 23:42:38.318000    运行成功open success
2019-02-25 23:56:28.518000    ==开始执行命令:g
2019-02-25 23:56:28.985000    vm-mobile-v8:运行成功 close success
2019-02-26 00:09:52.598000    ==开始执行命令:k
2019-02-26 00:09:56.349000    vm-mobile-v8:运行成功 open success
2019-02-26 00:10:54.078000    ==开始执行命令:c
2019-02-26 00:10:54.445000    查询服务器 vm-mobile-v8: 服务器开启完毕,地图数:1
2019-02-26 10:28:07.775000    ==开始执行命令:k
2019-02-26 10:28:11.270000    vm-mobile-v8:运行成功 open success
2019-02-26 10:29:27.366000    ==开始执行命令:c
2019-02-26 10:29:27.731000    查询服务器 vm-mobile-v8: 服务器开启完毕,地图数:1
2019-02-26 10:29:28.096000    vm-mobilecom:运行失败HTTP Error 404: Not Found
2019-02-26 10:30:18.670000    ==开始执行命令:r
2019-02-26 10:30:19.756000    vm-mobile-v8 重读成功!!!
2019-02-26 10:30:20.202000    vm-mobilecom 重读失败'ResultType'
2019-02-26 10:32:08.710000    ==开始执行命令:r
2019-02-26 10:32:09.721000    vm-mobile-v8 重读成功!!!
2019-02-26 10:32:10.047000    vm-mobilecom 重读失败'ResultType'
2019-02-26 10:32:54.783000    ==开始执行命令:g
2019-02-26 10:32:55.212000    vm-mobile-v8:运行成功 close success
2019-02-26 10:32:55.637000    vm-mobilecom:运行成功 close success
2019-02-26 10:35:47.807000    ==开始执行命令:k
2019-02-26 10:35:49.175000    vm-mobile-v8:运行失败, 如果是超时可能是运行慢是实际是成功,清配合其他工具或者直接远程查看 <urlopen error [Errno 10061] >
2019-02-26 10:35:52.783000    vm-mobilecom:运行成功 open success
2019-02-26 10:37:15.142000    ==开始执行命令:k
2019-02-26 10:37:18.094000    vm-mobile-v8:运行成功 open success
2019-02-26 10:37:20.188000    vm-mobilecom:运行成功 open success
2019-02-26 10:38:11.631000    ==开始执行命令:k
2019-02-26 10:38:13.687000    vm-mobile-v8:运行成功  =======服务器已经开启,请再次确认服务器情况, EventServer.exe运行中
2019-02-26 10:44:00.575000    ==开始执行命令:c
2019-02-26 10:44:00.946000    查询服务器 vm-mobile-v8: 服务器开启完毕,地图数:2
2019-02-26 10:44:30.158000    ==开始执行命令:c
2019-02-26 10:44:35.524000    vm-mobile-v8:运行失败<urlopen error timed out>
2019-02-26 10:44:46.878000    ==开始执行命令:c
2019-02-26 10:44:52.241000    vm-mobile-v8:运行失败<urlopen error timed out>
2019-02-26 10:46:33.503000    ==开始执行命令:c
2019-02-26 10:46:38.871000    vm-mobile-v8:运行失败<urlopen error timed out>
2019-02-26 10:46:50.062000    ==开始执行命令:g
2019-02-26 10:47:20.438000    vm-mobile-v8:运行失败, 如果是超时可能是运行慢是实际是成功,清配合其他工具或者直接远程查看 <urlopen error timed out>
2019-02-26 10:53:01.709000    ==开始执行命令:k
2019-02-26 10:53:05.037000    vm-mobile-v8:运行成功 open success
2019-02-26 10:54:06.014000    ==开始执行命令:c
2019-02-26 10:54:06.363000    查询服务器 vm-mobile-v8: 服务器开启完毕,地图数:1
2019-02-26 10:54:23.429000    ==开始执行命令:c
2019-02-26 10:54:28.776000    vm-mobile-v8:运行失败<urlopen error timed out>
2019-02-26 10:57:01.934000    ==开始执行命令:c
2019-02-26 10:57:07.302000    vm-mobile-v8:运行失败<urlopen error timed out>
Tool/RemoteTool/RemoteServer/key.txt
New file
@@ -0,0 +1 @@
slkfjlaskjf'lasjfjj1j4r1;2j;15r1-id-ig-k1r51-0id-sfgk1=-i1-m;az01m,-k-1-i4-14-1fmm1-
Tool/RemoteTool/RemoteServer/lib/CommFunc.py
New file
@@ -0,0 +1,371 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#
##@package
#
# @todo:
#
# @author: Alee
# @date 2018-7-18 上午11:22:43
# @version 1.0
#
# @note:
#
#---------------------------------------------------------------------
import struct
import string
import datetime
import os
import binascii
import socket
import sys
#python的读取/写入库
#要进行反转高低位的话,可使用!符号,如struct.unpack_from('!B', buf, pos)
#------------------------读取
def ReadBYTE(buf, pos):
    curValue = struct.unpack_from('b', buf, pos)
    pos += 1
    return curValue[0], pos
def ReadWORD(buf, pos):
    curValue = struct.unpack_from('H', buf, pos)
    pos += 2
    return curValue[0], pos
def ReadDWORD(buf, pos):
    curValue = struct.unpack_from('i', buf, pos)
    pos += 4
    return curValue[0], pos
def ReadFloat(buf, pos):
    curValue = struct.unpack_from('f', buf, pos)
    pos += 4
    return curValue[0], pos
def ReadDouble(buf, pos):
    curValue = struct.unpack_from('d', buf, pos)
    pos += 8
    return curValue[0], pos
def ReadString(buf, pos, _len):
    curValue = struct.unpack_from('%ds'%_len, buf, pos)
    pos += _len
    return curValue[0], pos
#----------------------写入
def WriteBYTE(buf, value):
    buf += struct.pack('b', value)
    return buf
def WriteWORD(buf, value):
    buf += struct.pack('H', value)
    return buf
def WriteDWORD(buf, value):
    buf += struct.pack('i', value)
    return buf
def WriteFloat(buf, value):
    buf += struct.pack('f', value)
    return buf
def WriteDouble(buf, value):
    buf += struct.pack('d', value)
    return buf
def WriteString(buf, len, value):
    buf += struct.pack('%ds'%len, value)
    return buf
#获得当前系统时间
def GetCurrentDataTimeStr():
    curTime = datetime.datetime.today()
    curTimeStr = str(curTime)
    curTimeStr = curTimeStr.split(".")[0]
    return curTimeStr
#获得系统时间(参数 -> 时间列表)
def GetDateTimeByStr(timeStr):
    timeStr = timeStr.split(".")[0]
    return  datetime.datetime.strptime(timeStr, "%Y-%m-%d %H:%M:%S")
#字符串转换为整型, 如果不能转换, 返回默认值
def ToIntDef(input, defValue = 0):
    try:
        result = int(input)
        return result
    except ValueError:
        return defValue
#字符串转换为整型, 如果不能转换, 返回False,原值
def StrToInt(input):
    try:
        result = int(input)
        return True,result
    except ValueError:
        return False,input
#16进制颜色转换
#"#FFFFFF"--"255,255,255"
def HcToSc(h):
    h="0x"+h[1:7]
    red=string.atoi(h[:2]+h[2:4], base=16)
    green=string.atoi(h[:2]+h[4:6], base=16)
    blue=string.atoi(h[:2]+h[6:8], base=16)
    cStr=str(red)+","+str(green)+","+str(blue)
    return cStr
#"255,255,255"--"#FFFFFF"
def ScToHc(s):
    red=hex(string.atoi(s.split(",")[0]))[2:]
    green=hex(string.atoi(s.split(",")[1]))[2:]
    blue=hex(string.atoi(s.split(",")[2]))[2:]
    hStr="#"+str(red+green+blue)
    return hStr
#16进制转换
#"0xFFFFFF"--"255,255,255"
def HdToSd(h):
    red=string.atoi(h[0:2]+h[2:4], base=16)
    green=string.atoi(h[0:2]+h[4:6], base=16)
    blue=string.atoi(h[0:2]+h[6:8], base=16)
    cStr=str(red)+","+str(green)+","+str(blue)
    return cStr
#"255,255,255"--"0xFFFFFF"
def SdToHd(s):
    red=hex(string.atoi(s.split(",")[0]))[2:]
    green=hex(string.atoi(s.split(",")[1]))[2:]
    blue=hex(string.atoi(s.split(",")[2]))[2:]
    hStr="0x"+str(red+green+blue)
    return hStr
def GetPercent(value1, value2):
    if value2 == 0:
        return 0
    return int(float(value1) / float(value2) * 100)
def OpenFileForWrite(fileName):
    dirName = os.path.dirname(fileName)
    if not os.path.isdir(dirName):
        os.makedirs(dirName)
    if os.path.isfile(fileName):
        return open(fileName, 'w')
    return  open(fileName, 'a')
#函数调用
def ParseNameGetObj(curCallObj, callName):
    callList = callName.split(".")
    if len(callList) <= 1:
        return None
    for curCallName in callList:
        if hasattr(curCallObj, curCallName) != True:
            #无此属性
            return None
        curCallObj = getattr(curCallObj, curCallName)
    return curCallObj
#获得执行函数
def GetExecFunc(curCallObj, callName):
    curCallObj = ParseNameGetObj(curCallObj, callName)
    if curCallObj == None:
        return None
    if callable(curCallObj) != True:
        #不可调用
        return None
    return curCallObj
#字符串异或处理
def str_xor(astring, xornum=150):
    a=[]
    for x in astring:
        a.append(chr(ord(x)^xornum))
    return ''.join(a)
#解析封包
def ParseBuff(buff):
    result=''
    for i in  range(len(buff)):
        if i%2==0 and i!=0:
            result=result + ' ' + buff[i]
        else:
            result = result + buff[i]
    return result
def b2a_hex(data):
    return ParseBuff(binascii.b2a_hex(data))
def GetHostName():
    return socket.gethostname()
def GetHostIP():
    return socket.gethostbyname(GetHostName())
def compact_traceback():
    t, v, tb = sys.exc_info()
    tbinfo = []
    if not tb: # Must have a traceback
        raise AssertionError("traceback does not exist")
    while tb:
        tbinfo.append((
            tb.tb_frame.f_code.co_filename,
            tb.tb_frame.f_code.co_name,
            str(tb.tb_lineno)
            ))
        tb = tb.tb_next
    # just to be safe
    del tb
    info = ' '.join(['[%s|%s|%s]' % x for x in tbinfo])
    return t, v, info
import base64
import urllib
import urllib2
#---------------------------------------------------------------------
## 加密算法需要的定义
Def_NumEncodeCnt = 3  # 加密的次数
Def_NumXorKey = 151  # 异或的key
## 公司内部解密算法
def GetDecodePwd(strPwd):
    strResult = strPwd
    for index in xrange(Def_NumEncodeCnt):
        strResult = base64.b64decode(strResult)
    tempResult = ""
    for index in xrange(len(strResult)):
        tempResult += chr(ord(strResult[index])^Def_NumXorKey)
    return tempResult
## 公司内部加密算法
def GetEncodePwd(strPwd):
    strResult = ""
    for index in xrange(len(strPwd)):
        strResult += chr(ord(strPwd[index])^Def_NumXorKey)
    for index in xrange(Def_NumEncodeCnt):
        strResult = base64.b64encode(strResult)
    return strResult
#---------------------------------------------------------------------
## UTF-8 <==> GBK
def gbk2utf8(content):
    if type( content ) is not str:
        content = str(content)
    try:
        return content.decode('gbk').encode('utf-8')
    except:
        return content
def utf82gbk(content):
    if type( content ) is not str:
        content = str(content)
    try:
        return content.decode('utf-8').encode('gbk')
    except:
        return content
## GET请求
def DoGet(url, data=None, headers={}):
    if data:
        request = urllib2.Request(url + "?" + urllib.urlencode(data), None, headers)
    else:
        request = urllib2.Request(url, None, headers)
    response = urllib2.urlopen(request, timeout=5)
    content = response.read()
    response.close()
    return content
## POST请求
def DoPost(url, data, headers={}):
    try:
        data = urllib.urlencode(data)
    except:
        pass
    request = urllib2.Request(url, data, headers)
    try:
        response = urllib2.urlopen(request, timeout=30)
        content = response.read()
        response.close()
    except:
        content = "error timeout"
    return content
FileTypeDict = {
'.txt':'text/html',
'.html':'text/html',
'.htm':'text/html',
'.bmp':'application/x-bmp',
'.ico':'image/x-icon',
'.jpe':'image/jpeg',
'.jpeg':'image/jpeg',
'.jpg':'application/x-jpg',
'.png':'application/x-png',
'.gif':'image/gif',
'.bin':'application/octet-stream',
'.*':'application/octet-stream'
}
def GetHttpContentType(strType):
    return FileTypeDict[strType]
## 编码
#  @param srcEncoding 编码格式
#  @param input 字符串
#  @return None
def EncodingToUnicode(srcEncoding, msg):
    try:
        result = unicode(msg, srcEncoding)    #translate to utf-8
    except:
        return "EncodingToUnicode error"
    return result
## 编码
#  @param srcEncoding 编码格式
#  @param input 字符串
#  @return None
def UnicodeToEncoding(dstEncoding, msg):
    try:
        result = msg.encode(dstEncoding)
    except:
        return "UnicodeToEncoding error"
    return result
Tool/RemoteTool/RemoteServer/lib/DBController.py
New file
@@ -0,0 +1,516 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
#-------------------------------------------------------------------------------
#
import pymongo
from pymongo.son_manipulator import SONManipulator
import base64
from functools import wraps
from time import (sleep)
import CommFunc
#模拟SQL的IDENT
def seq(db, collectionName, fieldName, feed, increment):
    try:
        result = 0
        collection = db['%s_seq'%collectionName]
        resultObj = collection.find_and_modify(query={'_id':fieldName}, update={'$inc':{'seq':increment}}, new=True)
        if resultObj:
            result = resultObj['seq']
        else:
            resultObj = collection.find_and_modify(query={'_id':fieldName}, update={'$set':{'seq':feed}}, new=True,
                                                   upsert=True)
            if resultObj:
                result = resultObj['seq']
            else:
                return False, None
    except Exception, e:
        return False, None
    return True, result
class ObjectIdRemover(SONManipulator):
    def transform_outgoing(self, son, collection):
        if '_id' in son:
            del son['_id']
        return son
class EncodeStringManipulator(SONManipulator):
    def __init__(self, encoding):
        self.encoding = encoding
    def transform_incoming(self, son, collection):
        def transform_value(value):
            if isinstance(value, dict):
                return transform_dict(value)
            elif isinstance(value, list):
                return [transform_value(v) for v in value]
            elif isinstance(value, basestring):
                result, value = CommFunc.EncodingToUnicode(self.encoding, value)
                return value
            return value
        def transform_dict(object):
            for (key, value) in object.items():
                object[key] = transform_value(value)
            return object
        def transform_list(container):
            for item in container:
                transform_dict(item)
            return container
        if isinstance(son, dict):
            return transform_dict(son)
        elif isinstance(son, list):
            return transform_list(son)
        return son
    def transform_outgoing(self, son, collection):
        def transform_value(value):
            if isinstance(value, dict):
                return transform_dict(value)
            elif isinstance(value, list):
                return [transform_value(v) for v in value]
            elif isinstance(value, basestring):
                result, value =CommFunc.UnicodeToEncoding(self.encoding, value)
                return value
            return value
        def transform_dict(object):
            for (key, value) in object.items():
                object[key] = transform_value(value)
            return object
        def transform_list(container):
            for item in container:
                transform_dict(item)
            return container
        if isinstance(son, dict):
            return transform_dict(son)
        elif isinstance(son, list):
            return transform_list(son)
        return son
class Base64StringManipulator(SONManipulator):
    def transform_incoming(self, son, collection):
        def transform_value(value):
            if isinstance(value, dict):
                return transform_dict(value)
            elif isinstance(value, list):
                return [transform_value(v) for v in value]
            elif isinstance(value, basestring):
                return base64.b64encode(value)
            return value
        def transform_dict(object):
            for (key, value) in object.items():
                object[key] = transform_value(value)
            return object
        def transform_list(container):
            for item in container:
                transform_dict(item)
            return container
        if isinstance(son, dict):
            return transform_dict(son)
        elif isinstance(son, list):
            return transform_list(son)
        return son
    def transform_outgoing(self, son, collection):
        def transform_value(value):
            if isinstance(value, dict):
                return transform_dict(value)
            elif isinstance(value, list):
                return [transform_value(v) for v in value]
            elif isinstance(value, basestring):
                return base64.b64decode(value)
            return value
        def transform_dict(object):
            for (key, value) in object.items():
                object[key] = transform_value(value)
            return object
        def transform_list(container):
            for item in container:
                transform_dict(item)
            return container
        if isinstance(son, dict):
            return transform_dict(son)
        elif isinstance(son, list):
            return transform_list(son)
        return son
#用于修饰DBController的数据库操作函数
#断线自动重试
def reconnect_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwds):
        MAX_RECONNECT = 10
        RECONNECT_INTERVAL = 0.1
        failCnt = 0
        while True:
            try:
                #去掉self
                return func(*args, **kwds)
            except pymongo.errors.AutoReconnect, e:
                failCnt += 1
                sleep(RECONNECT_INTERVAL)
                if failCnt > MAX_RECONNECT:
                    raise e
    return wrapper
class DBController:
    def __init__(self, host, port, dbName, user, pwd, encoding):
        self.host = host
        self.port = port
        self.dbName = dbName
        self.user = user
        self.pwd = pwd
        self.connected = False
        self.con = None
        self.db = None
        self.lastError = None
        self.translator = None
        #===========================================================================================
        # if encoding == 'base64':
        #    self.translator = Base64StringManipulator()
        # else:
        #    self.translator = EncodeStringManipulator(encoding)
        #===========================================================================================
        self.initialize()
    def initialize(self):
        if not self.connected:
            if not self.doConnect(self.host, self.port):
                return False
            authResult = self.doAuthentication(self.dbName, self.user, self.pwd)
            if self.db:
                self.db.add_son_manipulator(ObjectIdRemover())
            return authResult
        return True
    def doConnect(self, ip, port):
        try:
            self.con = pymongo.Connection(ip, port)
        except TypeError, typeError:
            raise
        except pymongo.errors.ConnectionFailure, failure:
            self.lastError = failure
            return False
        except Exception, e:
            self.lastError = e
            return False
        except:
            self.lastError = 'Unknown exception occur!'
            return False
        self.connected = True
        return True
    def doAuthentication(self, dbName, user, pwd):
        if not self.connected or not self.con:
            self.lastError = 'Not connected yet!'
            return False
        self.db = self.con[dbName]
        authDB = self.con['admin']
        try:
            return authDB.authenticate(user, pwd)
#            return self.db.authenticate(user, pwd)
        except TypeError, typeError:
            self.lastError = typeError
            return False
        except Exception, e:
            self.lastError = e
            return False
        except:
            self.lastError = 'Unknown exception occur!'
            return False
    def find_one(self, colName, spec, filter = None):
        result, recList = self.find(colName, spec, filter, 1)
        if not result:
            return False, None
        for rec in recList:
            return True, rec
        return True, None
    @reconnect_decorator
    def find(self, colName, spec = None, filter = None, maxCnt = 0, sortBy = None):
        if not self.connected:
            if not self.initialize():
                return False, []
        result = False
        resultDictList = []
        col = self.db[colName]
        if self.translator:
            spec = self.translator.transform_incoming(spec, None)
        try:
            resultCollection = col.find(spec, filter, limit = maxCnt, sort = sortBy)
            if self.translator:
                resultDictList = self.translator.transform_outgoing(list(resultCollection), None)
            else:
                resultDictList = list(resultCollection)
            return True, resultDictList
        except TypeError, typeError:
            self.lastError = typeError
            return result, resultDictList
        except pymongo.errors.OperationFailure, err:
            self.lastError = err
            return result, resultDictList
        except Exception, e:
            self.lastError = e
            return result, resultDictList
        except:
            self.lastError = 'Unknown exception occur!'
            return result, resultDictList
    @reconnect_decorator
    def insert(self, colName, doc_or_docs, isSafe = True):
        if not self.connected:
            if not self.initialize():
                return False
        col = self.db[colName]
        if self.translator:
            doc_or_docs = self.translator.transform_incoming(doc_or_docs, None)
        try:
            col.insert(doc_or_docs, safe = isSafe)
        except pymongo.errors.OperationFailure, err:
            self.lastError = err
            return False
        except Exception, e:
            self.lastError = e
            return False
        except:
            self.lastError = 'Unknown exception occur!'
            return False
        return True
    @reconnect_decorator
    def update(self, colName, spec, doc, isUpsert = False, isSafe = True, isMulti = False):
        if not self.connected:
            if not self.initialize():
                return False
        col = self.db[colName]
        #需要先对doc进行处理,但由不能开启collection.update的manipulate,因为那会应用所有处理
        if self.translator:
            spec = self.translator.transform_incoming(spec, None)
            doc = self.translator.transform_incoming(doc, None)
        try:
            col.update(spec, doc, upsert = isUpsert, safe = isSafe, multi = isMulti)
        except TypeError, typeError:
            self.lastError = typeError
            return False
        except pymongo.errors.OperationFailure, err:
            self.lastError = err
            return False
        except Exception, e:
            self.lastError = e
            return False
        except:
            self.lastError = 'Unknown exception occur!'
            return False
        return True
    @reconnect_decorator
    def save(self, colName, doc, isSafe = True):
        if not self.connected:
            if not self.initialize():
                return False
        col = self.db[colName]
        if self.translator:
            doc = self.translator.transform_incoming(doc, None)
        try:
            col.save(doc, safe = isSafe)
        except TypeError, typeError:
            self.lastError = typeError
            return False
        except pymongo.errors.OperationFailure, err:
            self.lastError = err
            return False
        except Exception, e:
            self.lastError = e
            return False
        except:
            self.lastError = 'Unknown exception occur!'
            return False
        return True
    @reconnect_decorator
    def remove(self, colName, spec = None, isSafe = True):
        if not self.connected:
            if not self.initialize():
                return False
        col = self.db[colName]
        if self.translator:
            spec = self.translator.transform_incoming(spec, None)
        try:
            col.remove(spec, safe = isSafe)
        except pymongo.errors.OperationFailure, err:
            self.lastError = err
            return False
        except Exception, e:
            self.lastError = e
            return False
        except:
            self.lastError = 'Unknown exception occur!'
            return False
        return True
    @reconnect_decorator
    def drop(self, colName):
        if not self.connected:
            if not self.initialize():
                return False
        col = self.db[colName]
        try:
            col.drop()
        except TypeError, typeError:
            self.lastError = typeError
            return False
        except Exception, e:
            self.lastError = e
            return False
        except:
            self.lastError = 'Unknown exception occur!'
            return False
        return True
    @reconnect_decorator
    def count(self, colName):
        if not self.connected:
            if not self.initialize():
                return False, 0
        col = self.db[colName]
        try:
            cnt = col.count()
        except pymongo.errors.OperationFailure, err:
            self.lastError = err
            return False, 0
        except Exception, e:
            self.lastError = e
            return False, 0
        except:
            self.lastError = 'Unknown exception occur!'
            return False, 0
        return True, cnt
def test_seq():
    con = pymongo.Connection()
    db = con.admin
    if not db.authenticate('sa', 'sa'):
        print 'auth failed!'
        return
    colName = 'tagSeqTest'
    fieldName = 'ID'
    db = con['test']
    db.drop_collection(colName)
    db.drop_collection('%s_seq'%colName)
    result, ID = seq(db, colName, fieldName, 1, 1)
    assert (result and ID == 1)
    result, ID = seq(db, colName, fieldName, 1, 1)
    assert (result and ID == 2)
def test_StringManipulator():
    translator = Base64StringManipulator()
    son = []
    result = translator.transform_incoming(son, None)
    assert (son == result)
    result = translator.transform_outgoing(son, None)
    assert (son == result)
    son = [{'a':1}]
    result = translator.transform_incoming(son, None)
    assert (son == result)
    result = translator.transform_outgoing(son, None)
    assert (son == result)
    son = [{'a':'a'}]
    result = translator.transform_incoming(son, None)
    assert (result and result == [{'a':base64.b64encode('a')}])
    result = translator.transform_outgoing(result, None)
    assert (result and result == son)
    son = [{'a':[{'b':'b'}, {'c':'c'}]}]
    result = translator.transform_incoming(son, None)
    assert (result and result == [{'a':[{'b':base64.b64encode('b')}, {'c':base64.b64encode('c')}]}])
    result = translator.transform_outgoing(result, None)
    assert (result and result == son)
def test_DBController():
    testColName = 'tagTestController'
    dbController = DBController('localhost', 27017, 'test', 'test', '1')
    result = dbController.drop(testColName)
    assert result
    result, cnt = dbController.count(testColName)
    assert (result and cnt == 0)
    doc = {'a':1}
    result = dbController.insert(testColName, doc)
    assert result
    result, recs = dbController.find(testColName)
    assert (result and len(recs) == 1)
    rec = recs[0]
#    del rec['_id']
#    print 'rec = %s\r\ndoc = %s'%(rec, doc)
    assert (rec == doc)
    spec = {'a':1}
    updateDoc = {'a':2}
    updateDocWithModifier = {'$set':updateDoc}
    result = dbController.update(testColName, spec, updateDocWithModifier)
    assert result
    result, recs = dbController.find(testColName)
    assert (result and len(recs) == 1)
    rec = recs[0]
    del rec['_id']
#    print 'rec = %s\r\nupdateDoc = %s'%(rec, updateDoc)
    assert (rec == updateDoc)
    result = dbController.remove(testColName)
    assert result
    result, recs = dbController.find(testColName)
    assert (result and recs == [])
    saveDoc = {'b':3}
    result = dbController.save(testColName, saveDoc)
    assert result
    result, recs = dbController.find(testColName)
    assert (result and len(recs) == 1)
    rec = recs[0]
#    del rec['_id']
    assert (rec == saveDoc)
def test():
    test_seq()
    test_StringManipulator()
    test_DBController()
    print 'test ok!'
if __name__ == '__main__':
    test()
Tool/RemoteTool/RemoteServer/lib/ReadConfig.py
New file
@@ -0,0 +1,74 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#
##@package
#
# @todo:
#
# @author: Alee
# @date 2018-6-5 下午08:20:53
# @version 1.0
#
# @note:
#
#---------------------------------------------------------------------
import ConfigParser
class ReadConfig():
    def __init__(self, filePath):
        self.__config = ConfigParser.ConfigParser()
        self.__config.read(filePath)
    def GetValue(self, section, option, default=None, isThrowException=False):
        try:
            return self.__config.get(section, option);
        except Exception, err:
            if not isThrowException:
                return default;
            raise Exception, "Error:配置问题,%s"%err;
    get = GetValue;
    def GetInt(self, section, option, default = 0, isThrowException=False):
        try:
            return self.__config.getint(section, option);
        except Exception, err:
            if not isThrowException:
                return default;
            raise Exception, "Error:配置问题,%s"%err;
    getint = GetInt;
    def GetBoolean(self, section, option, default = False):
        try:
            return self.__config.getboolean(section, option);
        except ValueError:
            default = str(default).lower();
            if default not in self.__config._boolean_states:
                return False;
            else:
                return self.__config._boolean_states[default];
    getboolean = GetBoolean;
    def HasSection(self, section):
        return self.__config.has_section(section)
    def HasOption(self, section, option):
        return self.__config.has_option(section, option)
#===============================================================================
# ## 读取Eval的值
# def GetEvalConfig(path):
#    with open(path, "r") as file:
#        content = file.read()
#        try:
#            value = eval(content)
#        except:
#            value = None
#
#    return value
#===============================================================================
Tool/RemoteTool/RemoteServer/lib/TimeRotatingPathFileHandler.py
New file
@@ -0,0 +1,155 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#
##@package
#
# @todo:
#
# @author: Alee
# @date 2018-7-18 上午11:40:53
# @version 1.0
#
# @note:
#
#---------------------------------------------------------------------
#根据时间切换目录和文件的文件处理器
from logging.handlers import *
class TimeRotatingPathFileHandler(TimedRotatingFileHandler):
    def __init__(self, root, filename, when = 'h', interval = 1, backupCount = 0, encoding = None, delay = False, utc = False):
        #创建输出目录数
        t = int(time.time())
        if utc:
            timeTup = time.gmtime(t)
        else:
            timeTup = time.localtime(t)
        year = timeTup[0]
        month = timeTup[1]
        day = timeTup[2]
        self.root = root
        self.filename = filename
        self.baseFilename = self.getBaseFileName(self.root, year, month, day, self.filename)
        #print 'baseFileName = %s'%self.baseFilename
        filepath = os.path.dirname(self.baseFilename)
        self.ensurePath(filepath)
        #改变当前工作目录
        #if not (os.getcwd() == filepath):
        #    os.chdir(filepath)
        TimedRotatingFileHandler.__init__(self, self.baseFilename, when, interval, backupCount, encoding, delay, utc)
        #self.suffix = ''#不指定后缀
    def getBaseFileName(self, root, year, month, day, filename):
        filenameWithoutExt = filename.split('.')[0]
        return os.path.join(root, '%04d-%02d\\%s\\%02d\\%s'%(year, month, filenameWithoutExt, day, filename))
    def ensurePath(self, filepath):
        if not os.path.exists(filepath):
            os.makedirs(filepath)
    def doRollover(self):
        lastRolloverTime = self.rolloverAt
        #TimedRotatingFileHandler.doRollover(self)
        if self.stream:
            self.stream.close()
            self.stream = None
        #获取上一次切换的时间
        t = self.rolloverAt - self.interval
        if self.utc:
            timeTuple = time.gmtime(t)
        else:
            timeTuple = time.localtime(t)
        filenameTuple = self.filename.split('.')
        filename = ''
        if len(filenameTuple) == 1:
            filename = '%s-%s'%(filenameTuple[0], time.strftime(self.suffix, timeTuple))
        else:
            filename = '%s-%s.%s'%(filenameTuple[0], time.strftime(self.suffix, timeTuple), filenameTuple[len(filenameTuple) - 1])
        dfn = os.path.join(self.root, '%04d-%02d\\%s\\%02d\\%s'%(timeTuple[0], timeTuple[1], filenameTuple[0], timeTuple[2], filename))
        #dfn = self.baseFilename + "." + time.strftime(self.suffix, timeTuple)
        if os.path.exists(dfn):
            os.remove(dfn)
#        print 'dfn = %s baseFilename = %s'%(dfn, self.baseFilename)
        #可能由于改系统时间或其他人为原因造成文件找不到
        if os.path.exists(self.baseFilename):
            os.rename(self.baseFilename, dfn)
        if self.backupCount > 0:
            # find the oldest log file and delete it
            #s = glob.glob(self.baseFilename + ".20*")
            #if len(s) > self.backupCount:
            #    s.sort()
            #    os.remove(s[0])
            for s in self.getFilesToDelete():
                os.remove(s)
        currentTime = int(time.time())
        newRolloverAt = self.computeRollover(currentTime)
        while newRolloverAt <= currentTime:
            newRolloverAt = newRolloverAt + self.interval
        #If DST changes and midnight or weekly rollover, adjust for this.
        if (self.when == 'MIDNIGHT' or self.when.startswith('W')) and not self.utc:
            dstNow = time.localtime(currentTime)[-1]
            dstAtRollover = time.localtime(newRolloverAt)[-1]
            if dstNow != dstAtRollover:
                if not dstNow:  # DST kicks in before next rollover, so we need to deduct an hour
                    newRolloverAt = newRolloverAt - 3600
                else:           # DST bows out before next rollover, so we need to add an hour
                    newRolloverAt = newRolloverAt + 3600
        self.rolloverAt = newRolloverAt
        #判断是否需要切换文件夹
        nextRolloverTime = self.rolloverAt
        if self.utc:
            lastRolloverTimeTup = time.gmtime(lastRolloverTime)
            nextRolloverTimeTup = time.gmtime(nextRolloverTime)
        else:
            lastRolloverTimeTup = time.localtime(lastRolloverTime)
            nextRolloverTimeTup = time.localtime(nextRolloverTime)
        lastRolloverYear = lastRolloverTimeTup[0]
        lastRolloverMonth = lastRolloverTimeTup[1]
        lastRolloverDay = lastRolloverTimeTup[2]
        nextRolloverYear = nextRolloverTimeTup[0]
        nextRolloverMonth = nextRolloverTimeTup[1]
        nextRolloverDay = nextRolloverTimeTup[2]
        if lastRolloverYear != nextRolloverYear or lastRolloverMonth != nextRolloverMonth or lastRolloverDay != nextRolloverDay:
            #年或月改变,更换文件夹
            self.baseFilename = self.getBaseFileName(self.root, nextRolloverYear, nextRolloverMonth, nextRolloverDay, self.filename)
#            print 'need to rollove path:%s-%s -> %s-%s'%(lastRolloverYear, lastRolloverMonth,
#                                                         nextRolloverYear, nextRolloverMonth)
            filepath = os.path.dirname(self.baseFilename)
            self.ensurePath(filepath)
        else:
            pass
        self.mode = 'w'
        self.stream = self._open()
def test():
    import logging
    mylogger = logging.getLogger('test')
    mylogger.setLevel(logging.DEBUG)
    hdlr = TimeRotatingPathFileHandler('d:\\ServerLog\\', 'AD.txt')
    fs = '%(asctime)s\t%(levelname)-8s\t%(message)s'
    dfs = '%Y-%m-%dT%H:%M:%S'
    fmt = logging.Formatter(fs, dfs)
    hdlr.setLevel(logging.DEBUG)
    hdlr.setFormatter(fmt)
    mylogger.addHandler(hdlr)
#    mylogger.info('test')
#    os.system('pause')
    exit = False
    cnt = 0
    lastTime = time.time()
    while not exit:
        curTime = time.time()
        if curTime - lastTime >= 60:
            lastTime = curTime
            mylogger.info('test')
if __name__ == "__main__":
    test()
Tool/RemoteTool/RemoteServer/lib/__init__.py
Tool/RemoteTool/RemoteServer/lib/mylog.py
New file
@@ -0,0 +1,158 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#
##@package
#
# @todo:
#
# @author: Alee
# @date 2018-7-18 上午11:40:23
# @version 1.0
#
# @note:
#
#---------------------------------------------------------------------\
import logging
from time import localtime
import TimeRotatingPathFileHandler
import CommFunc
__gLogger = None
def InitLog( LogPath, LogName, printToConsole = True, isDebug = True, mode = 'H' ):
    global __gLogger
    logLevel = logging.INFO
    if isDebug:
        logLevel = logging.DEBUG
    #设置日志的过滤等级
    __gLogger = logging.getLogger(LogName)
    __gLogger.setLevel(logLevel)
    hdlr = TimeRotatingPathFileHandler.TimeRotatingPathFileHandler(LogPath, LogName, mode)
    fs = '%(asctime)s\t%(levelname)-8s\t%(message)s'
    dfs = '%Y-%m-%dT%H:%M:%S'
    fmt = logging.Formatter(fs, dfs)
    hdlr.suffix = "%Y-%m-%d_%H-%M-%S"
    hdlr.setLevel(logLevel)
    hdlr.setFormatter(fmt)
    __gLogger.addHandler(hdlr)
    if printToConsole:
        console = logging.StreamHandler()
        console.setFormatter(fmt)
        __gLogger.addHandler(console)
        console.setLevel(logLevel)
__WARN_COUNT = 0
__ERR_COUNT = 0
__FATAL_COUNT = 0
__LastWarnInfo = ""
__LastWarnTime = ""
__LastErrInfo = ""
__LastErrTime = ""
__LastFatalInfo = ""
__LastFatalTime = ""
def GetLastWarnInfo():
    global __LastWarnInfo
    return __LastWarnInfo
def GetLastWarnTime():
    global __LastWarnTime
    return __LastWarnTime
def GetLastErrInfo():
    global __LastErrInfo
    return __LastErrInfo
def GetLastErrTime():
    global __LastErrTime
    return __LastErrTime
def GetLastFatalInfo():
    global __LastFatalInfo
    return __LastFatalInfo
def GetLastFatalTime():
    global __LastFatalTime
    return __LastFatalTime
def Get_Warn_Count():
    global __WARN_COUNT
    return __WARN_COUNT
def Get_Err_Count():
    global __ERR_COUNT
    return __ERR_COUNT
def Get_Fatal_Count():
    global __FATAL_COUNT
    return __FATAL_COUNT
def debug(msg):
    global __gLogger
    __gLogger.debug(msg)
def info(msg):
    global __gLogger
    __gLogger.info(msg)
def warn(msg):
    global __WARN_COUNT
    global __LastWarnInfo
    global __LastWarnTime
    global __gLogger
    __WARN_COUNT += 1
    __LastWarnInfo = msg
    __LastWarnTime = CommFunc.GetCurrentDataTimeStr()
    __gLogger.warning(msg)
__ErrInfoList = []
__OnErr = None
def OnErr(onErr):
    global __OnErr
    __OnErr = onErr
def error(msg):
    global __ERR_COUNT
    global __LastErrInfo
    global __LastErrTime
    global __gLogger
    global __ErrInfoList
    global __OnErr
    __ERR_COUNT += 1
    __LastErrInfo = msg
    __LastErrTime = CommFunc.GetCurrentDataTimeStr()
    if msg not in __ErrInfoList:
        __ErrInfoList.append(msg)
        if __OnErr:
            errInfo = ""
            for info in __ErrInfoList:
                errInfo += "%s\r\n"%info
            __OnErr(errInfo[:-2])
    __gLogger.error(msg)
def fatal(msg):
    global __FATAL_COUNT
    global __LastFatalInfo
    global __LastFatalTime
    global __gLogger
    __FATAL_COUNT += 1
    __LastFatalInfo = msg
    __LastFatalTime = CommFunc.GetCurrentDataTimeStr()
    __gLogger.critical(msg)
def test():
    import os
    InitLog(os.getcwd(), "AD")
    info('test')
if __name__ == '__main__':
    test()
Tool/RemoteTool/RemoteServer/main.py
New file
@@ -0,0 +1,42 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#
##@package
#
# @todo: 开关服处理
#
# @author: Alee
# @date 2019-2-20 下午04:45:00
# @version 1.0
#
# @note:
#
#---------------------------------------------------------------------
#
#需要安装第三方库
#waitress-1.1.0.tar.gz
#requests-2.18.4.tar.gz
#---------------------------------------------------------------------
import webapp
from bottle import run
from lib import mylog
import time
import os
import datetime
from lib import ReadConfig
Def_Debug = ReadConfig.ReadConfig(os.getcwd() + "\\config.ini").GetValue("Remote", "IsDebug")
#center.secondworld.net.cn
def main():
    time.sleep(1)
    os.system("title 服务器控制台-%s"%datetime.datetime.today())
    mylog.InitLog(r"D:/ServerLog", "RemoteServer.txt", False, Def_Debug)
    CenterPort = int(ReadConfig.ReadConfig(os.getcwd() + "\\config.ini").GetValue("Remote", "Port"))
    run(host='0.0.0.0', port=CenterPort, app=webapp.myapp)
    return
if __name__ == '__main__':
    main()
Tool/RemoteTool/RemoteServer/qufu.txt
New file
@@ -0,0 +1 @@
vm-mobile-v8
Tool/RemoteTool/RemoteServer/webapp.py
New file
@@ -0,0 +1,149 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#
##@package
#
# @todo:
#
# @author: Alee
# @date 2019-2-20 下午04:50:04
# @version 1.0
#
# @note:
#
#---------------------------------------------------------------------
#---------------------------------------------------------------------
from bottle import Bottle, request
from lib import mylog
import os
import md5
import smtplib
from email.mime.text import MIMEText
from email.header import Header
import datetime
# get: request.query.username request.GET.get('username','')
# post: request.forms.get('username')  request.POST.get('username')
#===============================================================================
# @myapp.route('/cool/kk/:name3/:count#\\d+#')
# def maybe(name3, count):
# client_ip = request.environ.get('REMOTE_ADDR')
# client_ip = request.environ.get('HTTP_X_FORWARDED_FOR') or request.environ.get('REMOTE_ADDR')
#===============================================================================
g_AllMapCnt = 0
myapp = Bottle()
# 可执行固定的远程命令
@myapp.route('/control/openandclose.php', method='POST')
def RemoteCmd():
    dataDict = request.POST
#    for key in dataDict:
#        print key
#        mylog.debug("---%s"%dataDict[key])
    result = dataDict.get("control", "")
    if not result:
        return
    sign = dataDict.get("sign", "")
    if not sign:
        return
    ofile = open(r".\key.txt")
    text = ofile.read().strip()
    ofile.close()
    if sign != md5.md5("%s1234666%s"%(result, text)).hexdigest():
        mylog.debug("签名失败")
        return
    if result == "open":
        pResult = os.popen('tasklist /FI "IMAGENAME eq EventServer.exe"')
        pResult = pResult.read()
        if "PID" in pResult or "pid" in pResult:
            return " =======服务器已经开启,请再次确认服务器情况, EventServer.exe运行中"
        os.system(r"call D:\ProjectServer\LaunchServerManager\正常开服.bat")
        return "open success"
    elif result == "close":
        # 记得关服后或者重启机器需自动启动服务器控制台
        os.system(r"call D:\ProjectServer\LaunchServerManager\正常关服.bat")
        return "close success"
    return
# OnLogError OnPyError
# 服务器开启的状态汇报
@myapp.route('/control/state.php')
def ServerState():
    global g_AllMapCnt
    try:
        dataDict = request.GET
        stateType = dataDict.get("Type", "")
        if not stateType:
            return
        if stateType == "MapInit":
            # 服务器关闭的时候会重启,此状态只用于开服的时候是否初始化OK
            g_AllMapCnt = dataDict.get("MapCount", 0)
            if g_AllMapCnt:
                ifile = open(".\MapCount.txt", "w")
                ifile.write(str(datetime.datetime.today()) + "\t服务器开启完毕,地图数=%s"%g_AllMapCnt)
                ifile.close()
            #return "服务器开启完毕,地图数=%s"%dataDict.get("MapCount", 0)
            return
        elif stateType in ["MapError", "GameServerError", "PyMongoError"]:
            #groupID=%s&userDBName=%s&Type=PyMongoError
            ServerInfo = "错误类型:%s 服务器组:%s, dbname:%s"%(stateType,
                                                       dataDict.get("groupID", 0),
                                                       dataDict.get("userDBName", 0))
            SendEmail(ServerInfo)
            return
        elif stateType == "MapDisconnect":
            # 地图5分钟未响应,可以卡了或者闪退 关闭
            #groupID=%s&userDBName=%s&Type=PyMongoError
            ServerInfo = "错误类型:地图被关闭%s 服务器组:%s, dbname:%s"%(stateType,
                                                       dataDict.get("groupID", 0),
                                                       dataDict.get("userDBName", 0))
            SendEmail(ServerInfo)
            return
        elif stateType == "QueryMapOK":
            if g_AllMapCnt == 0:
                if not os.path.exists(".\MapCount.txt"):
                    return "===暂无反馈,稍等后查询==="
                ifile = open(".\MapCount.txt")
                text = ifile.read()
                ifile.close()
                return "=========上一次记录的开启情况, 请过会再查询========", text
            return "服务器开启完毕,地图数:%s"%g_AllMapCnt
    except Exception, e:
        print e
# 邮件汇报
def SendEmail(ServerInfo):
    # 第三方 SMTP 服务
    mail_host="smtp.qq.com"  #设置服务器
    mail_user="2199274165@qq.com"    #用户名
    mail_pass="asmizpysxngtdjic"   # 开通QQ邮箱的SMTP,短信验证后获取的,非密码
    sender = '2199274165@qq.com'
    # 这里可以填写需要接收汇报的邮件地址
    receivers = ['305670599@qq.com']#, '1142397645@qq.com']
    message = MIMEText('异常汇报:%s'%ServerInfo, 'plain', 'gbk')
    message['From'] = Header("游戏服务器异常汇报", 'gbk')
    message['To'] =  Header("运维", 'gbk')    # 不发送的话会被记录为垃圾邮件
    subject = '游戏服务器异常'
    message['Subject'] = Header(subject, 'gbk')
    smtpObj = smtplib.SMTP()
    smtpObj.connect(mail_host, 25)    # 25 为 SMTP 端口号, 如果用SSL 需要换端口
    smtpObj.login(mail_user,mail_pass)
    smtpObj.sendmail(sender, receivers, message.as_string())
    print "邮件发送成功"