using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography; using Sog; using Google.Protobuf.WellKnownTypes; using FileTransDataObject; namespace SMCenter { public class CheckAgentCmdProc : BaseCmdProc { private long LastCheckTimeoutSecond; public override void ClearData() { m_nowCmd = null; } public override int DoCmd(out string msg) { if (m_nowCmd.CmdParams.Count < 1 || string.IsNullOrEmpty(m_nowCmd.CmdParams[0])) { msg = "invalid cmd param"; return -1; } if (CmdUtils.CheckValidServerId(m_nowCmd.CmdParams[0], out string fixSvrId) == false) { msg = "invalid server id"; return -1; } if (fixSvrId != null) { m_nowCmd.CmdParams[0] = fixSvrId; } SMProcAppMgr.Instance.GetAllMatchingProc(m_nowCmd.CmdParams[0], m_nowCmd.m_procs); m_nowCmd.m_procs = m_nowCmd.m_procs.OrderBy(o => o.Value.SMApp.HostName).ToDictionary(p => p.Key, o => o.Value); msg = ""; int ret = 0; var fileList = new List(); switch (m_nowCmd.CMD) { case "checkagent": ret = GetAgentFile(fileList, out msg); break; case "checkpushfile": ret = GetPushFile(fileList, out msg); break; } if (ret != 0) { return -1; } // 上面算完文件列表后再对procs去重, 否则会少算文件 CmdProcInfoDistinct(); SendCmdToHost(fileList); return 0; } // 检测agent运行目录下的dll和pdb private int GetAgentFile(List fileList, out string msg) { // center和agent的部署层级是一样的, center的运行目录就是agent的运行目录 string dllPath = Path.Combine(SMCenterUtils.Config.centerPush, "SMAgent.dll"); var dll = FileUtils.CreateFileData(dllPath, false); if (dll == null) { msg = string.Format("{0} not exist", dllPath); return -1; } string pdbPath = Path.Combine(SMCenterUtils.Config.centerPush, "SMAgent.pdb"); var pdb = FileUtils.CreateFileData(pdbPath, false); if (pdb == null) { msg = string.Format("{0} not exist", pdbPath); return -1; } dll.writeFilePath = Path.GetFullPath("../bin"); fileList.Add(dll); pdb.writeFilePath = Path.GetFullPath("../bin"); fileList.Add(pdb); msg = ""; return 0; } //主要检测服务器运行需要的 cfg文件和bin 文件 private int GetPushFile(List fileList, out string msg) { int ret = CmdUtils.GetPushBinFile(m_nowCmd, fileList, false); if (ret == -1) { msg = "GetPushBinFile fail"; return -1; } ret = CmdUtils.GetPushCfgFile(m_nowCmd, fileList, false); if (ret == -1) { msg = "GetPushCfgFile fail"; return -1; } msg = ""; return 0; } public override int UpdateCmd(long tMs) { if (m_nowCmd.m_procs.Count == 0) { return 0; } if (IsAllProcCmdAcked()) { return 0; } CheckProcTimeout(tMs); return 1; } private void SendCmdToHost(List fileList) { var req = new SMAgentDoCommandReq(); req.Command = m_nowCmd.CMD; req.SeqNum = m_nowCmd.SeqNum; foreach (FileData file in fileList) { var attr = new FileAttr { FileMd5 = file.fileMd5, FileName = file.fileName, FileSize = file.FileSize, FilePath = file.writeFilePath, FileTime = file.fileWriteTime.ToFileTimeUtc() }; req.FileList.Add(attr); } foreach (var cmdInfo in m_nowCmd.m_procs.Values) { if (cmdInfo.SendCmdToHostTime == 0) { req.ServerId = cmdInfo.SMApp.AppId; cmdInfo.SendCmdToHostTime = SMCenterUtils.GetTimeSecond(); ClientInfo client = SMCenterNet.Instance.GetClientInfoByName(cmdInfo.SMApp.HostName); if (client != null) { client.SendMsg(req, SMMsgID.AgentDoCommandReq); } } } } public override void OnAgentDoCommandRes(ClientInfo client, SMAgentDoCommandRes res) { if (m_nowCmd.SeqNum != res.SeqNum) { TraceLog.Error("CheckAgentCmdProc.OnAgentDoCommandRes CMD {0} svrId {1} seq not same, local {2} res {3}" , res.Command, res.ServerId, m_nowCmd.SeqNum, res.SeqNum); return; } if (m_nowCmd.m_procs.ContainsKey(res.ServerId) == false) { TraceLog.Error("CheckAgentCmdProc.OnAgentDoCommandRes CMD {0} serverId {1} not in m_procs, skip" , res.Command, res.ServerId); return; } CmdProcInfo proc = m_nowCmd.m_procs[res.ServerId]; proc.AckResultCode = res.ResultCode; proc.AckMessage = res.Result; proc.AckAddInfo = res.AddInfo; if (IsAllProcCmdAcked()) { AckConsoleCmdResult(); } TraceLog.Trace("CommCmdProc.OnAgentDoCommandRes CMD {0} agent {1}, result {2}" , res.Command, res.HostName, res.Result); } private void CheckProcTimeout(long tMs) { long nowSecond = tMs / 1000; if (nowSecond - LastCheckTimeoutSecond < 2) { return; } LastCheckTimeoutSecond = nowSecond; foreach (var cmdInfo in m_nowCmd.m_procs.Values) { if (cmdInfo.SendCmdToHostTime > 0 && cmdInfo.AckResultCode == ResResultCode.NoRes) { int timeoutSecond = 15; if (nowSecond - cmdInfo.SendCmdToHostTime > timeoutSecond) { TraceLog.Error("CheckAgentCmdProc.CheckProcTimeout cmd {0} serverid {1} timeout" , m_nowCmd.CMD, cmdInfo.SMApp.ServerIDStr); cmdInfo.AckResultCode = ResResultCode.TimeOut; if (IsAllProcCmdAcked()) { AckConsoleCmdResult(); } } } } } private bool IsAllProcCmdAcked() { foreach (var proc in m_nowCmd.m_procs) { if (proc.Value.AckResultCode == ResResultCode.NoRes) { return false; } } return true; } private void AckConsoleCmdResult() { SMConsoleCommandRes res = new SMConsoleCommandRes(); res.Command = m_nowCmd.ConsoleInput; res.Message = ""; List hostName = new List(); foreach (var procInfo in m_nowCmd.m_procs) { string procResult = ""; if (! hostName.Contains(procInfo.Value.SMApp.HostName)) { procResult += string.Format("\n--------------- HostName:{0} ---------------", procInfo.Value.SMApp.HostName); hostName.Add(procInfo.Value.SMApp.HostName); } procResult += "\n " + procInfo.Value.SMApp.HostName + "\t"; switch (procInfo.Value.AckResultCode) { case ResResultCode.NoRes: procResult += "NoRes"; break; case ResResultCode.TimeOut: procResult += "timeout"; break; case ResResultCode.Success: procResult += "success"; break; case ResResultCode.Fail: procResult += "Fail"; break; case ResResultCode.Exception: procResult += "Exception"; break; case ResResultCode.Running: procResult += "Running"; break; case ResResultCode.NotRunning: procResult += "Not Running"; break; default: break; } //不会空的情况下定义为错误信息 if (string.IsNullOrEmpty(procInfo.Value.AckMessage) == false) { procResult += "\n" + procInfo.Value.AckMessage; } if (string.IsNullOrEmpty(procInfo.Value.AckAddInfo) == false) { procResult += "\n" + procInfo.Value.AckAddInfo; } res.Message += procResult; } SMCenterNet.Instance.SendMsg(m_nowCmd.SessionId, SMMsgID.ConsoleCommandRes, res, m_nowCmd.HttpId); } } }