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
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|