c#实现的守护进程

这段时间在做一个关于数据交互的项目。接收到客户发送过来的文件后,通过Windows服务将文件按一定的规则分发到不同的MQ消息队列,然后再由不同的处理程序处理。虽然在编码中尽可能的考虑到了异常以及记录了详细的日志,但是服务还是偶尔抽风停掉了,这样就造成了文件堆积,客户请求得不到及时的响应。所以需要一个守护进程来保证服务始终是启动状态的。

首先,要保证需要监控的进程可配置,以及指定日志的保存位置。在App.config中配置日志保存路径以及需监控进程和对应的exe可执行程序的位置(之前考虑是如果没有该服务,则使用exe安装服务)。

  <appSettings>
    <add key="LogPath" value="D:\Study"/>
    <add key="YTGDataExchangeProcess" value="d:\Study\YTGDataExchangeProcess.exe"/>
  </appSettings>
public class ServiceSearch
    {
        static List<ServiceProcessInfo> _ServiceList = new List<ServiceProcessInfo>();
        static object _logLocker = new Object();
        //日志记录位置
        static readonly string _logPath;

        static ServiceSearch()
        {
            try
            {
                string[] appSettingsKeys = ConfigurationManager.AppSettings.AllKeys;

                foreach (string item in appSettingsKeys)
                {
                    string value = ConfigurationManager.AppSettings[item].Trim();
                    //日志配置
                    if (item == "LogPath")
                    {
                        if (!string.IsNullOrEmpty(value))
                        {
                            _logPath = string.Format("{0}\\ProcessMonitorLog", value);
                            if (!Directory.Exists(_logPath))
                            {
                                Directory.CreateDirectory(_logPath);
                            }
                        }
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(value))
                        {
                            //应用程序是否存在
                            if (File.Exists(value))
                            {
                                _ServiceList.Add(new ServiceProcessInfo
                                {
                                    ServiceExePath = value,
                                    ServiceName = item
                                });
                            }
                        }

                    }

                }
            }
            catch (Exception ex)
            {
                WriteLog(ex.Message);
            }
        }

        public static void StartMonitor()
        {
            if (_ServiceList.Count != 0)
            {
                foreach (ServiceProcessInfo info in _ServiceList)
                {
                    string sevName = info.ServiceName;
                    string sevExePath = info.ServiceExePath;

                    if (!string.IsNullOrEmpty(sevExePath))
                    {
                        //校验exe文件是否存在
                        if (File.Exists(sevExePath))
                        {
                            ScanServiceManager(sevName, sevExePath);
                        }
                    }
                }
            }
            else
            {
                WriteLog("没有配置需要监控的服务!");
            }
        }

        /// <summary>
        /// 查找服务的进程
        /// 有则判断进程是否运行,非运行状态则启动
        /// </summary>
        public static void ScanServiceManager(string serviceName, string serviceExePath)
        {
            try
            {
                ServiceController sevCtrler = new ServiceController(serviceName);
                //该服务已存在
                //如果服务状态不为启动
                if (sevCtrler.Status != ServiceControllerStatus.Running)
                {
                    sevCtrler.Start();
                }
                //创建监控线程
                WatchService(serviceName);
            }
            catch (Exception ex)
            {
                //该服务不存在
                WriteLog(string.Format(ex.Message));
            }
        }

        /// <summary>
        /// 为配置的进程添加监控进程
        /// </summary>
        /// <param name="pro"></param>
        /// <param name="processAddress"></param>
        public static void WatchService(string ServiceName)
        {
            ServiceMonitor monitor = new ServiceMonitor(ServiceName);
            Thread thread = new Thread(new ThreadStart(monitor.Monitor));
            thread.IsBackground = true;
            thread.Start();
        }

        /// <summary>
        /// 写日志
        /// </summary>
        /// <param name="errMessage"></param>
        public static void WriteLog(string errMessage)
        {
            string logPath = _logPath;
            //没有配置日志目录,不记录
            if (!string.IsNullOrEmpty(logPath))
            {
                lock (_logLocker)
                {
                    string fullName = string.Format("{0}\\{1}.log", logPath, DateTime.Now.ToString("yyyy-MM-dd"));
                    if (!File.Exists(fullName))
                    {
                        File.Create(fullName).Close();
                    }
                    using (StreamWriter sw = new StreamWriter(fullName, true, Encoding.UTF8))
                    {
                        sw.WriteLine(String.Format("[{0}]{1}", DateTime.Now.ToString("hh:mm:ss fff"), errMessage));
                        sw.Close();
                    }
                }
            }
        }

        public class ServiceProcessInfo
        {
            /// <summary>
            /// 服务名称
            /// </summary>
            public string ServiceName
            {
                get;
                set;
            }
            /// <summary>
            /// 应用程序位置
            /// </summary>
            public string ServiceExePath
            {
                get;
                set;
            }
        }

    }

上面ScanServiceManager方法中,使用serviceName实例化ServiceController对象,并启用一个单独的线程对其轮询,监控其状态;否则只会对第一个服务进行监控后阻塞。

    public class ServiceMonitor
    {
        /// <summary>
        /// 服务名称
        /// </summary>
        private string _ServiceName;

        public string ServiceName
        {
            get { return _ServiceName; }
            set { _ServiceName = value; }
        }

        public ServiceMonitor(string ServiceName)
        {
            this._ServiceName = ServiceName;
        }

        /// <summary>
        /// 监听服务
        /// </summary>
        public void Monitor()
        {
            while (true)
            {
                try
                {
                    ServiceController ctrler = new ServiceController(_ServiceName);
                    if (ctrler.Status != ServiceControllerStatus.Running)
                    {
                        ServiceSearch.WriteLog(string.Format("正在启动服务{0}...", _ServiceName));
                        ctrler.Start();
                        ServiceSearch.WriteLog(string.Format("服务{0}启动成功!", _ServiceName));
                    }
                }
                catch (Exception ex)
                {
                    ServiceSearch.WriteLog(string.Format("服务{0}启动失败,错误原因:{1}", _ServiceName, ex.Message));
                }
                Thread.Sleep(1000 * 40);
            }
        }

    }
时间: 2024-12-16 15:32:21

c#实现的守护进程的相关文章

Python setdaemon守护进程

setdaemon守护进程 #_*_coding:utf-8_*_ __author__ = 'gaogd' import time import threading ''' 守护进程,如果主线程down了,子线程也就没有了. 下面先通过主进程生成main主线程,之后main主线程再生成10个子线程. ''' ''' def run(num):     if not num == 5:         time.sleep(1)     print 'Hi, I am thread %s..la

转:linux守护进程的启动方法

Linux 守护进程的启动方法 作者: 阮一峰 日期: 2016年2月28日 "守护进程"(daemon)就是一直在后台运行的进程(daemon). 本文介绍如何将一个 Web 应用,启动为守护进程. 一.问题的由来 Web应用写好后,下一件事就是启动,让它一直在后台运行. 这并不容易.举例来说,下面是一个最简单的Node应用server.js,只有6行. var http = require('http'); http.createServer(function(req, res)

Python实例浅谈之五Python守护进程和脚本单例运行

一.简介 守护进程最重要的特性是后台运行:它必须与其运行前的环境隔离开来,这些环境包括未关闭的文件描述符.控制终端.会话和进程组.工作目录以及文件创建掩码等:它可以在系统启动时从启动脚本/etc/rc.d中启动,可以由inetd守护进程启动,也可以有作业规划进程crond启动,还可以由用户终端(通常是shell)执行. Python有时需要保证只运行一个脚本实例,以避免数据的冲突. 二.Python守护进程 1.函数实现 #!/usr/bin/env python #coding: utf-8

#python#守护进程的实现

找了整天,终于找到一个可以用的代码 #! /usr/bin/env python2.7 #encoding:utf-8 #@description:一个python守护进程的例子 #@tags:python,daemon import sys import os import time import atexit from signal import SIGTERM      class Daemon:   """   A generic daemon class.     

linux守护进程

#include <iostream>#include <unistd.h>//#include "curl/curl.h"#include "app_curl.h"#include "youtube_package.h"#include "CAutoMail.h"#include <fcntl.h>#include <signal.h>#include <unistd.h

C#开发Linux守护进程

C#开发Linux守护进程 Linux守护进程是Linux的后台服务进程,相当于Windows服务,对于为Linux开发服务程序的朋友来说,Linux守护进程相关技术是必不可少的,因为这个技术不仅仅是为了开发守护进程,还可以拓展到多进程,父子进程文件描述符共享,父子进程通讯.控制等方面,是实现Linux大型服务的基础技术之一. 去年我也曾写了一篇关于守护进程的帖子,名字叫<.NET跨平台实践:用C#开发Linux守护进程>,这篇文章的的确确实现了一个Daemon,不过,它有一个弱点,不能运行多

守护进程的创建过程

编写守护进程需要5步 1 创建子进程,父进程结束(让这个进程由init进程托管) pid = fork(); if(pid > 0) //父进程 { exit(0); }2 在子进程中创建新会话(此进程就可以脱离原来进程,脱离控制终端,脱离原来进程组) setsid(); //最主要是脱离控制终端 3 改变当前目录(每一个进程都有一个当前目录), 不是必须的 chdir("/tmp"); 4 重新设置文件权限掩码(不是必须的) umask(0); 5 关闭打开的文件描述符(如果父

Linux守护进程实现程序只运行一次

1.守护进程 守护进程(Daemon)是一种运行在后台的特殊进程,它独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件. 2.让程序只运行一次 如果让程序只运行一次,有很多方法,此处的一种方法是创建一个名字古怪的文件(保证不跟系统文件或其他文件重名),判断文件存在则让程序不再运行且提示程序正在运行,如果不存在则可以运行. 3.测试代码 此代码额外添加了系统LOG,记录操作的信息. 1 #include <stdio.h> 2 #include <unistd.h> 3

Linux系统开发7 进程关系,守护进程

[本文谢绝转载原文来自http://990487026.blog.51cto.com] <大纲> Linux系统开发7  进程关系守护进程 终端 网络终端 Linux PCB结构体信息 进程组 修改子进程.父进程的组ID 会话组 设置一个会话脱离控制终端 生成一个新的会话 守护进程 守护进程模板 获取当前系统时间  终端 在UNIX系统中用户通过终端登录系统后得到一个Shell进程这个终端成为Shell进 程的控制终端Controlling Terminal在讲进程时讲过控制终端是保存在PCB

linux中的守护进程

//一.守护进程 守护进程,也叫精灵进程(daemon) 它和普通后台进程的区别在于以下三点 1.守护进程自成会话,而普通后台进程则不一定 2.守护进程不受终端的控制 3.守护进程就是后台进程,而后台进程不同于守护进程 用ps axj命令查看系统中的进程,TPGID一栏为 -1 的进程(这些进程没有控制终端)就是守护进程. //二.实现 创建守护进程的步骤如下: 1.调用umask把[文件模式创建屏蔽字] 设置为 0 由于 umask 接收的参数会被取反,所以这个 0 传进去取反以后是最大的,也