using System; using System.Net; using System.Net.NetworkInformation; using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Text.RegularExpressions; using ProtoBuf; using static System.Runtime.InteropServices.JavaScript.JSType; namespace Tiobon.PublishHelper { /// /// 辅助类 /// public class Utility { #region 参数 /// /// 停止发布 /// public static bool m_StopPublish = false; /// /// 替换控制指令 /// public static System.Text.RegularExpressions.Regex m_RegexUb = new System.Text.RegularExpressions.Regex(@"\u001b\[\d+[A-z]"); /// /// 测试服务器 /// public static string m_TestServerIp = "192.168.8.60"; #endregion #region 事件 /// /// 记录日志 /// public static Action SendLogHandle; public static void SendLog(string msg, bool status = false) { SendLogHandle("", msg); if (status) { SetStatus(msg); } lock (m_Logs) m_Logs.Add(msg); } public static void SendLog(string oprate, string msg, bool status = false) { SendLogHandle(oprate, msg); if (status) { SetStatus(msg); } lock (m_Logs) { if (string.IsNullOrEmpty(oprate)) m_Logs.Add($"{msg}"); else m_Logs.Add($"[{oprate}] {msg}"); } } /// /// 设置进度条显示/隐藏 /// public static Action SetProgressBarVisible; /// /// 设置进度条状态 /// public static Action SetProgressBarValue; /// /// 设置当前状态 /// public static Action SetStatus; #endregion #region 初始化 public static void Init() { ReadDevServer(); ReadPublishServer(); ReadOprateLog(); Thread log = new Thread(WriteLogger); log.Start(); } #endregion #region 服务器管理 /// /// 开发服务器列表 /// public static List m_DevServers = new List(); /// /// 保存开发服务器配置 /// public static void SaveDevServer() { try { string fname = AppDomain.CurrentDomain.BaseDirectory + "\\DevServers.dat"; if (File.Exists(fname)) File.Delete(fname); using (FileStream fs = new FileStream(fname, FileMode.Create)) { BinaryFormatter bf = new BinaryFormatter(); //将list序列化到文件中 bf.Serialize(fs, m_DevServers); } } catch { } } /// /// 读取开发服务器配置 /// public static void ReadDevServer() { try { string fname = AppDomain.CurrentDomain.BaseDirectory + "\\DevServers.dat"; if (File.Exists(fname)) { using (FileStream fs = new FileStream(fname, FileMode.Open)) { BinaryFormatter bf = new BinaryFormatter(); //将list序列化到文件中 m_DevServers = bf.Deserialize(fs) as List; } } } catch { } if (m_DevServers is null) { m_DevServers = new List(); } m_DevServers.ForEach(s => { if (s.Hospitals is null) { s.Hospitals = new List(); } }); } /// /// 发布服务器列表 /// public static List m_PublishServers = new List(); /// /// 保存发布服务器配置 /// public static void SavePublishServer() { try { string fname = AppDomain.CurrentDomain.BaseDirectory + "\\PublishServers.dat"; if (File.Exists(fname)) File.Delete(fname); using (FileStream fs = new FileStream(fname, FileMode.Create)) { BinaryFormatter bf = new BinaryFormatter(); //将list序列化到文件中 bf.Serialize(fs, m_PublishServers); } } catch { } } /// /// 读取发布服务器配置 /// public static void ReadPublishServer() { try { string fname = AppDomain.CurrentDomain.BaseDirectory + "\\PublishServers.dat"; if (File.Exists(fname)) { using (FileStream fs = new FileStream(fname, FileMode.Open)) { BinaryFormatter bf = new BinaryFormatter(); //将list序列化到文件中 m_PublishServers = bf.Deserialize(fs) as List; } } } catch { } if (m_PublishServers is null) { m_PublishServers = new List(); } m_PublishServers.ForEach(s => { if (s.Folders is null) s.Folders = new List(); s.Folders.ForEach(f => { if (f.Files is null) f.Files = new List(); }); }); } #endregion #region 操作记录 /// /// 操作记录 /// public static OprateLog m_OprateLog = new OprateLog(); /// /// 保存操作记录 /// public static void SaveOprateLog() { try { string fname = AppDomain.CurrentDomain.BaseDirectory + "\\OprateLog.dat"; if (File.Exists(fname)) File.Delete(fname); using (FileStream fs = new FileStream(fname, FileMode.Create)) { BinaryFormatter bf = new BinaryFormatter(); //将list序列化到文件中 bf.Serialize(fs, m_OprateLog); } } catch { } } /// /// 读取操作记录 /// public static void ReadOprateLog() { try { string fname = AppDomain.CurrentDomain.BaseDirectory + "\\OprateLog.dat"; if (File.Exists(fname)) { using (FileStream fs = new FileStream(fname, FileMode.Open)) { BinaryFormatter bf = new BinaryFormatter(); //将list序列化到文件中 m_OprateLog = bf.Deserialize(fs) as OprateLog; } } } catch { } if (m_OprateLog is null) { m_OprateLog = new OprateLog(); } } #endregion #region Ping测试 /// /// Ping测试 /// /// /// /// public static bool Ping(string ip, bool b_log = true) { bool b_suc = false; try { using (Ping ping = new Ping()) { b_suc = ping.Send(ip, 2000).Status == IPStatus.Success; } } catch { b_suc = false; } if (!b_suc && b_log) { SendLog(ip, "ping失败,不继续执行其他远程操作指令"); } return b_suc; } #endregion #region 获取临时文件名 /// /// 获取临时文件名 /// /// /// /// public static string GetTempFileName(string fname, bool random = true) { return $"{System.Environment.GetEnvironmentVariable("TEMP")}\\{fname}" + (random ? $"_{DateTime.Now.Ticks}" : ""); } #endregion #region 获取服务器状态 /// /// 获取服务器状态 /// /// /// public static (bool Success, double Cpu, double MemTotal, double MemUsed, double Disk) GetServerStatus(Server server) { var res = (false, 0, 0, 0, 0); try { var (Success, Result) = SshHelper.ExcuteCmd(server, "cpu=`top -b -n 1 | awk 'NR>7{sum+=$9} END {print sum}'`\n mem=`free -m | awk 'NR==2{print $2,$3}'` \n disk=`df -h | grep \"home\" |awk '{{print $5}}'` \n echo \"$cpu,$mem,$disk\"", false); if (Success) { //87,7981 4369,96% var empties = Result.Trim('\n').Trim().Split(new string[] { "%", ",", " " }, StringSplitOptions.RemoveEmptyEntries); if (empties.Length == 4) { return (true, double.Parse(empties[0]), double.Parse(empties[1]), double.Parse(empties[2]), double.Parse(empties[3])); } } } catch { } return res; } #endregion #region 日志 /// /// 停止记录日志 /// public static bool m_LogRun = true; private static List m_Logs = new List(); /// /// 日志线程 /// private static void WriteLogger() { var path = AppDomain.CurrentDomain.BaseDirectory + "Log\\"; if (!Directory.Exists(path)) Directory.CreateDirectory(path); string fname = string.Empty; var logs = new List(); while (m_LogRun) { try { lock (m_Logs) { if (m_Logs.Count > 0) { m_Logs.ForEach(s => logs.Add(s)); fname = path + DateTime.Now.ToString("yyyy_MM_dd") + ".txt"; m_Logs.Clear(); } } if (logs.Count > 0) { WriteLoggerToFile(fname, logs); logs.Clear(); } } catch { // ignored } finally { System.Threading.Thread.Sleep(3000); } } } /// /// 日志写入文件 /// /// 文件名 /// 日志 private static void WriteLoggerToFile(string fname, List logs) { StringBuilder sb = new StringBuilder(); logs.ForEach(s => sb.AppendLine(DateTime.Now.ToString("HH:mm:ss") + "\t" + s)); if (!File.Exists(fname)) { using (StreamWriter sw = File.CreateText(fname)) { sw.Write(sb.ToString()); } } else { using (StreamWriter sw = File.AppendText(fname)) { sw.Write(sb.ToString()); } } } #endregion #region 发布与打包锁 /// /// 查询锁定文件 /// /// /// /// /// public static bool LockDevFiles(Server server, string oprate) { bool b_in = false; string lfname = GetTempFileName("lockfile"); string rfname = $"/tmp/lockfile"; if (SftpHelper.DownloadFile(server, rfname, lfname)) { if (File.Exists(lfname)) { SendLog(File.ReadAllText(lfname, Encoding.UTF8)); b_in = true; } } else { File.WriteAllText(lfname, $"当前服务器 {server.Ip} 繁忙。用户 [{Environment.MachineName}] 正在 {oprate},请等待 [{Environment.MachineName}] 操作完毕...", Encoding.UTF8); SftpHelper.UploadFile(server, lfname, rfname); } return b_in; } /// /// 删除锁定文件 /// /// public static void RemoveDevFiles(Server server) { SftpHelper.Delete(server, $"/tmp/lockfile"); } #endregion #region HTTP模板 public static CookieContainer m_Cookies = new CookieContainer(); public enum Compression { GZip, Deflate, None, } /// /// 获取HttpWebRequest模板 /// /// URL地址 /// POST /// Cookies /// public static HttpWebRequest GetHttpRequest(string url, string postdata, CookieContainer cookies, string header = null) { HttpWebRequest request = WebRequest.Create(new Uri(url)) as HttpWebRequest; request.CookieContainer = cookies; request.ContentType = !string.IsNullOrEmpty(header) ? "application/json" : "application/x-www-form-urlencoded"; request.ServicePoint.ConnectionLimit = 300; ServicePointManager.Expect100Continue = false; request.Referer = url; request.Accept = "*/*"; request.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)"; request.AllowAutoRedirect = true; if (!string.IsNullOrEmpty(header)) request.Headers.Add("Authorization", header); if (postdata != null && postdata != "") { request.Method = "POST"; byte[] byte_post = Encoding.Default.GetBytes(postdata); request.ContentLength = byte_post.Length; using (Stream stream = request.GetRequestStream()) { stream.Write(byte_post, 0, byte_post.Length); } } else { request.Method = "GET"; } return request; } /// /// 提取HttpWebResponse文本内容 /// /// HttpWebResponse响应包 /// public static string GetResponseContent(HttpWebResponse resp) { if (resp.StatusCode != HttpStatusCode.OK) throw new Exception("远程服务器返回状态码: " + resp.StatusCode); Encoding enc = Encoding.UTF8; if (resp.CharacterSet != null && resp.CharacterSet != "") enc = Encoding.GetEncoding(resp.CharacterSet); Compression comp = Compression.None; if (resp.ContentEncoding != null && resp.ContentEncoding.Trim().ToUpper() == "GZIP") comp = Compression.GZip; else if (resp.ContentEncoding != null && resp.ContentEncoding.Trim().ToUpper() == "DEFLATE") comp = Compression.Deflate; MemoryStream ms = new MemoryStream(); using (StreamWriter sw = new StreamWriter(ms, enc)) { StreamReader sr; switch (comp) { case Compression.GZip: sr = new StreamReader(new System.IO.Compression.GZipStream(resp.GetResponseStream(), System.IO.Compression.CompressionMode.Decompress), enc); break; case Compression.Deflate: sr = new StreamReader(new System.IO.Compression.DeflateStream(resp.GetResponseStream(), System.IO.Compression.CompressionMode.Decompress), enc); break; default: sr = new StreamReader(resp.GetResponseStream(), enc); break; } while (!sr.EndOfStream) { char[] buf = new char[16000]; int read = sr.ReadBlock(buf, 0, 16000); StringBuilder sb = new StringBuilder(); sb.Append(buf, 0, read); sw.Write(buf, 0, read); } sr.Close(); } byte[] mbuf = ms.GetBuffer(); string sbuf = enc.GetString(mbuf); return sbuf; } /// /// 获取HttpWebRequest返回值 /// /// URL地址 /// PostData /// public static string GetHttpResult(string url, string postdata, string header = null) { try { HttpWebRequest request = GetHttpRequest(url, postdata, m_Cookies, header); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); m_Cookies.Add(response.Cookies); return GetResponseContent(response); } catch { //Utilities.sendLog("连接 " + url + " 失败" + ex.Message); return ""; } } /// /// 获取HttpWebRequest返回值 /// /// URL地址 /// PostData /// public static Stream GetHttpResponse(string url, string postdata) { try { HttpWebRequest request = GetHttpRequest(url, postdata, m_Cookies); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); return response.GetResponseStream(); } catch { //Utilities.sendLog("连接 " + url + " 失败" + ex.Message); return null; } } /// /// 去除HTML标记 /// /// 包括HTML的源码 /// 已经去除后的文字 public static string RemoveHTMLFlag(string input) { input = Regex.Replace(input, @"]*?>.*?", "", RegexOptions.IgnoreCase); Regex regex = new Regex("<.+?>", RegexOptions.IgnoreCase); input = regex.Replace(input, ""); input = Regex.Replace(input, @"<(.[^>]*)>", "", RegexOptions.IgnoreCase); input = Regex.Replace(input, @"([\r\n])[\s]+", "", RegexOptions.IgnoreCase); input = Regex.Replace(input, @"-->", "", RegexOptions.IgnoreCase); input = Regex.Replace(input, @"