using System; using System.Collections.Generic; using System.Linq; using Sog; using Google.Protobuf.WellKnownTypes; namespace SMCenter { // public class ShellAgentResult { public ResResultCode ResultCode; public string Result; public string Message; } //执行shell命令 //调用的是bash //请不要执行不会退出的命令,比如top之类的,没处理这样情况,会挂掉的 public class ShellCmdProc : BaseCmdProc { private Dictionary m_agents = new Dictionary(); private long m_startCancelTime = 0; public override void ClearData() { m_nowCmd = null; m_agents.Clear(); m_startCancelTime = 0; } public override int DoCmd(out string msg) { try { 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); var req = new SMAgentDoCommandReq(); req.Command = m_nowCmd.CMD; req.SeqNum = m_nowCmd.SeqNum; req.ExeFileName = "bash"; req.CmdArgs = string.Empty; for (int i = 1; i < m_nowCmd.CmdParams.Count; i++) { req.CmdArgs += m_nowCmd.CmdParams[i]; if (i != m_nowCmd.CmdParams.Count - 1) { req.CmdArgs += " "; } } foreach (var name in m_nowCmd.m_procs.Values.Select(p => p.SMApp.HostName).Distinct()) { m_agents.Add(name, new ShellAgentResult() ); var client = SMCenterNet.Instance.GetClientInfoByName(name); if (client == null) { TraceLog.Error("ShellCmdProc.DoCmd agent {0} not register", name); m_agents[name].Result = "failed"; m_agents[name].Message = "no connected agent"; continue; } SMCenterNet.Instance.SendMsg(client, SMMsgID.AgentDoCommandReq, req); } } catch (Exception e) { TraceLog.Exception(e); msg = "ShellCmdProc.DoCmd throw a exception ..."; return -1; } msg = string.Empty; return 0; } public override int UpdateCmd(long tMs) { if(m_startCancelTime > 0 && tMs - m_startCancelTime > 5000) { //超时退出 return 0; } bool allFinish = true; int successCount = 0; int failedCount = 0; foreach(var agent in m_agents) { if(agent.Value.ResultCode == ResResultCode.Success) { successCount++; } else { failedCount++; } if(agent.Value.ResultCode == ResResultCode.Running) { allFinish = false; break; } if(agent.Value.ResultCode == ResResultCode.NoRes) { allFinish = false; break; } } if(allFinish) { var res = new SMConsoleCommandRes(); res.Command = m_nowCmd.CMD; res.Message = string.Format("shell cmd {0} finish. succ {1} failed {2}", m_nowCmd.ConsoleInput, successCount, failedCount); SMCenterNet.Instance.SendMsg(m_nowCmd.SessionId, SMMsgID.ConsoleCommandRes, res); return 0; } return 1; } public override void OnAgentDoCommandRes(ClientInfo client, SMAgentDoCommandRes res) { TraceLog.Trace("ShellCmdProc.OnAgentDoCommandRes cmd {0} res from {1}", m_nowCmd.CMD, client.HostName); if(m_agents.ContainsKey(res.HostName) == false) { TraceLog.Error("ShellCmdProc.OnAgentDoCommandRes cmd {0} res no agent {1}", m_nowCmd.CMD, client.HostName); return; } var info = m_agents[res.HostName]; info.ResultCode = res.ResultCode; info.Result = res.Result; info.Message = res.AddInfo; var consoleres = new SMConsoleCommandRes(); consoleres.Nonewline = 1; consoleres.Command = m_nowCmd.ConsoleInput; if(res.ResultCode == ResResultCode.Running) { consoleres.Message = string.Format("host {0} ack \n{1} {2}", res.HostName, res.Result, res.AddInfo); } else { consoleres.Message = string.Format("shell cmd host {0} finish. Msg: \n{1} {2}", res.HostName, res.Result, res.AddInfo); } SMCenterNet.Instance.SendMsg(m_nowCmd.SessionId, SMMsgID.ConsoleCommandRes, consoleres); } public int DoCancel(out string msg) { msg = "success"; var req = new SMAgentDoCommandReq(); req.Command = "cancelshell"; req.SeqNum = m_nowCmd.SeqNum; req.CmdArgs = string.Empty; foreach (var agent in m_agents) { var client = SMCenterNet.Instance.GetClientInfoByName(agent.Key); if (client == null) { TraceLog.Error("ShellCmdProc.DoCancel agent {0} not register", agent.Key); agent.Value.ResultCode = ResResultCode.Fail; agent.Value.Result = "failed"; agent.Value.Message = "no connected agent"; continue; } SMCenterNet.Instance.SendMsg(client, SMMsgID.AgentDoCommandReq, req); } return 0; } } }