using System; using System.Text; using System.Diagnostics; using System.Threading; using Sog; using Sog.IO; using Google.Protobuf.WellKnownTypes; using Google.Protobuf; namespace SMAgent { /// /// 执行shell命令 /// windows下使用cmd /// linux下使用bash /// public static class SMShell { private static Process m_process; private static long m_processStartTime = 0; private static long m_lastSendMsgTimeMs; public static SMAgentDoCommandReq req; public static int Exec(string cmd, out string result) { result = string.Empty; if (m_process != null) { result = "other shell already running..."; return -1; } try { var escapedArgs = cmd.Replace("\"", "\\\""); Process process; if (OSUtils.IsWindows()) { process = new Process { StartInfo = new ProcessStartInfo { RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true, FileName = "cmd.exe", Arguments = $"/C \"{escapedArgs}\"" } }; } else { process = new Process { StartInfo = new ProcessStartInfo { RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true, FileName = "/bin/bash", Arguments = $"-c \"{escapedArgs}\"" } }; } process.EnableRaisingEvents = true; Thread.Sleep(10); //不在这里start m_processStartTime = 0; m_process = process; return 1; } catch (Exception ex) { TraceLog.Exception(ex); result = "catch one exception:" +ex.Message; } return -1; } public static string ReadOutput() { StringBuilder sb = new StringBuilder(); DateTime readstartTime = DateTime.Now; while(m_process.StandardOutput.EndOfStream == false) { if(m_process.StandardOutput.Peek() == -1) { break; } int iValue = (char)m_process.StandardOutput.Read(); if(iValue == -1) { break; } char ch = (char)iValue; sb.Append(ch); double timePass = (DateTime.Now - readstartTime).TotalMilliseconds; //尽量一行一行读取 if(timePass >= 100 || ch == '\n') { break; } if (timePass >= 500) { break; } } return sb.ToString(); } public static void UpdateProcessExit(long tMs) { if(m_process == null) { return; } if(m_processStartTime == 0) { m_processStartTime = tMs; m_process.Start(); return; } try { Thread.Sleep(10); if (m_process != null) { //进程已经退出可以读取全部输出 if (m_process.HasExited) { string output = ""; output += m_process.StandardError.ReadToEnd(); output += m_process.StandardOutput.ReadToEnd(); SMAgentDoCommandRes res = new SMAgentDoCommandRes(); res.Command = "shell"; res.SeqNum = req.SeqNum; res.ServerId = req.ServerId; res.HostName = SMAgentUtils.HostName; res.ResultCode = ResResultCode.Success; res.Result = output; SMAgentNet.Instance.SendMsgToCenter(res, SMMsgID.AgentDoCommandRes); m_process.Close(); m_process = null; req = null; m_processStartTime = 0; } else { if (m_lastSendMsgTimeMs == 0) { m_lastSendMsgTimeMs = tMs; return; } if (tMs - m_lastSendMsgTimeMs >= 2000) { m_lastSendMsgTimeMs = tMs; string output = ReadOutput(); SMAgentDoCommandRes res = new SMAgentDoCommandRes(); res.Command = "shell"; res.SeqNum = req.SeqNum; res.ServerId = req.ServerId; res.HostName = SMAgentUtils.HostName; res.Result = output; if (m_process.HasExited) { res.Result += m_process.StandardError.ReadToEnd(); res.ResultCode = ResResultCode.Success; } else { res.ResultCode = ResResultCode.Running; } SMAgentNet.Instance.SendMsgToCenter(res, SMMsgID.AgentDoCommandRes); } } } } catch (Exception ex) { TraceLog.Exception(ex); } } public static void CancelShell() { if (m_process == null) { return; } try { m_processStartTime = 0; req = null; m_process.Kill(); m_process.Close(); m_process = null; } catch (Exception ex) { TraceLog.Exception(ex); } } } }