.Net自写Task进程监控程序

来源:互联网 发布:驱动保护源码 编辑:程序博客网 时间:2024/06/06 11:36

需求:线上运行的job,有时间可能因为数据库异常、内存不足或者是内部其他异常导致整个进程退出,是偶发事件,但是如果进程停止,业务数据没处理积压起来,会影响业务。为了能自动监控并启动这种意外停止的进程,写了一个程序监控,每分种检查一遍,然后自动处理,实际上是非常有用的。


贴代码如下:

//主要逻辑

            var runday = DateTime.Today;            ConfigFile.Instanse.fileName = CommonFunctions.GetAbsolutePath("Kulv.YCF.KeepTaskRun.ini");//获取配置文件绝对路径            string ExeFile = "";            string ServiceName = "";            var configIndex = 1;            RunTaskAgain(() =>            {                while (true)                {                    try                    {                        ExeFile = ConfigFile.Instanse["ExeFile" + configIndex];                        if (string.IsNullOrEmpty(ExeFile)) break;                        Logger.Info("………………………………………………………… ExeFile" + configIndex + " Start……………………………………………………………");//写日志到文本文件中                        ServiceName = ConfigFile.Instanse["ServiceName" + configIndex];                        var isRun = CommonFunctions.IsProgramRun(ExeFile);//判断exe是否在运行的进程中                        if (DateTime.Today != runday)                        {                            runday = DateTime.Today;                        }                        Logger.Info(string.Format("ExeFile:{0},ServiceName:{1}", ExeFile, ServiceName));                        if (isRun)                        {                            Logger.Info("程序正在运行中");                        }                        else                        {                            Logger.Info(string.Format("程序未运行,尝试启动服务"));                            var startResult = CommonFunctions.RunCmd(string.Format("sc start \"{0}\"", ServiceName));//通过cmd命令启动服务                            var regex = new Regex("(\r\n)+");                            startResult = regex.Replace(startResult, "$1");//多个换行替换成一个                            Logger.Info("\r\n" + startResult);                            if (startResult.Contains("失败") == false)                            {                                Logger.Info(string.Format("启动服务成功!"));                            }                            var phonestr = ConfigFile.Instanse["CellPhone" + configIndex];                            FinanceApiInvoke.ApiDomain = ConfigFile.Instanse["MapApiAddress" + configIndex]; ;                            if (string.IsNullOrEmpty(phonestr))                            {                                Logger.Info(string.Format("短信接收人配置" + configIndex + "为空!"));                            }                            else if (string.IsNullOrEmpty(FinanceApiInvoke.ApiDomain))                            {                                Logger.Info(string.Format("短信发送API配置" + configIndex + "为空!"));                            }                            else                            {                                DateTime dt = DataCache.GetCache<DateTime>("LastSendMsgTime");//用缓存,5分钟内只发一次短信                                if ((DateTime.Now - dt).TotalMinutes >= 5)                                {                                    var phones = phonestr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);                                    List<SMSForSendIModel> msgList = new List<SMSForSendIModel>();                                    foreach (var phone in phones)                                    {                                        msgList.Add(new SMSForSendIModel()                                        {                                            CompanyId = CompanyEnum.YaoChufa,                                            Phone = phone,                                            SendBy = "KeepTaskRun",                                            UserId = 0,                                            TemplateCode = "NOTICE-COMMON0",                                            UserType = UserType.SystemUser,                                            Content = string.Format("库存服务YCF_STOCK_TASK处于停止状态,监控程序已在尝试启动服务,如果自动启动失败,需要人工处理!如正在发布请忽略此信息。")                                        });                                    }                                    var sendRet = FinanceApiInvoke.SendSmsToWithEncryptionBatch(msgList, true);//通过api提交要发的短信给内部系统                                    Logger.InfoFormat("短信返回:{0}", JsonUtility.ToJson(sendRet));                                    DataCache.Set<DateTime>("LastSendMsgTime", DateTime.Now, 60 * 5);                                    Logger.InfoFormat("job监控发短信成功");                                }                            }                        }                        Logger.Info("……………………………………………………………ExeFile" + configIndex + " End………………………………………………………………");                        configIndex++;                    }                    catch (Exception ex)                    {                        Logger.Info("配置" + configIndex + ",ErrorMessage:" + ExceptionMessage.GetOnlyMessage(ex));                    }                }            }, Logger, this.GetType().Name);

//配置文件-Kulv.YCF.KeepTaskRun.ini

[配置1]ExeFile1=D:\Task\StockTask\YCF.Stock.Task.exeServiceName1=YCF_Stock_TaskCellPhone1=15920522222,15920522223MapApiAddress1=[配置2]ExeFile2=D:\Task\StockTask\YCF.Stock.Task2.exeServiceName2=YCF_Stock_Task2CellPhone2=15920522222,15920522223MapApiAddress2=[配置3]ExeFile3=D:\Task\StockTask\YCF.Stock.Task3.exeServiceName3=YCF_Stock_Task3CellPhone3=15920522222,15920522223MapApiAddress3=

//判断方法:

        /// <summary>        /// 判断程序是否正在运行        /// </summary>        /// <param name="exefile">The exefile.</param>        /// <returns></returns>        public static bool IsProgramRun(string exefile)        {//D:\FinancePartTask\Kulv.YCF.Task.exe            Process[] processes = Process.GetProcesses();            string FileName = "";            bool ret = false;            Process toKill = null;            foreach (Process thisproc in processes)            {                try                {                    FileName = thisproc.MainModule.FileName;                    if (FileName == exefile)                    {                        toKill = thisproc;                        break;                    }                }                catch// (Exception ex)                {                    //FileName = "不能访问";                }            }            try            {                if (toKill != null)                {                    ret = true;                }                else                {                    ret = false;                }            }            catch// (Exception ex)            {                ret = false;            }            return ret;        }        /// <summary>        /// 运行传入的cmd命令        /// </summary>        /// <param name="cmd">cmd语句</param>        /// <returns></returns>        public static string RunCmd(string cmd, string cmdCurrentDir = null)        {            string ret = "";            if (!string.IsNullOrEmpty(cmdCurrentDir)) cmd = "cd /d " + cmdCurrentDir + " & " + cmd;            cmd = cmd + " &exit"; //说明:不管命令是否成功均执行exit命令,否则当调用ReadToEnd()方法时,会处于假死状态            using (var p = new Process())            {                p.StartInfo.FileName = "cmd.exe";                p.StartInfo.UseShellExecute = false; //是否使用操作系统shell启动                p.StartInfo.RedirectStandardInput = true; //接受来自调用程序的输入信息                p.StartInfo.RedirectStandardOutput = true; //由调用程序获取输出信息                p.StartInfo.RedirectStandardError = true; //重定向标准错误输出                p.StartInfo.CreateNoWindow = true; //不显示程序窗口                p.Start(); //启动程序                //向cmd窗口写入命令                p.StandardInput.WriteLine(cmd);                p.StandardInput.AutoFlush = true;                p.WaitForExit(); //等待程序执行完退出进程                ret = p.StandardOutput.ReadToEnd();                p.Close();            }            return ret;        }


这样,业务task异常退出之后,程序会自动启动服务,对task正常运行多了一层保障。

有人会问,监控程序本身也会异常退出呀,根据运行情况来看,没有异常退出过,因为程序内部与数据库等等都没交互,不会引发不明情况的异常退出,所以基本上不会异常退出。





0 0
原创粉丝点击