You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

236 lines
6.6 KiB

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
{
/// <summary>
/// 执行shell命令
/// windows下使用cmd
/// linux下使用bash
/// </summary>
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);
}
}
}
}