使用ACE监控启动进程,进程崩溃后自动重启(windows/linux通用)
//使用ACE监控启动进程,进程崩溃后自动重启(windows/linux通用)
原理:
监护程序使用子进程的方式启动各个进程,
子进程退出时,监护程序能够得到相应的退出信号,
从而在子进程退出后,在重新启动相应的子进程。
//----------------------
//配置文件ProcessManager.conf格式
//./PROCESS_MANAGER 1
//./PROCESS_MANAGER 2
//----------------------
// main.cpp
// main.cpp#include "CProcessManager.h"int main(int argc, char *argv[]){// Running as a child for test.if (argc > 1){ACE_OS::sleep(10);return 0;}// set output log fileACE_OS::setprogname("ProcessManager");ACE_Date_Time tvTime(ACE_OS::gettimeofday());char szLogFileName[256];memset(szLogFileName, 0, sizeof(szLogFileName));snprintf(szLogFileName, sizeof(szLogFileName), "log/%s_%04d%02d%02d_%02d%02d%02d.log", ACE_OS::getprogname(), (int)tvTime.year(), (int)tvTime.month(), (int)tvTime.day(), (int)tvTime.hour(), (int)tvTime.minute(), (int)tvTime.second());ACE_OSTREAM_TYPE *pLogOutput = new ofstream(szLogFileName);ACE_LOG_MSG->msg_ostream(pLogOutput, true);ACE_LOG_MSG->set_flags(ACE_Log_Msg::OSTREAM);// Prepends timestamp and message priority to each messageACE_LOG_MSG->set_flags(ACE_Log_Msg::VERBOSE_LITE);//ACE_LOG_MSG->clr_flags(ACE_Log_Msg::STDERR);ACE_DEBUG((LM_INFO, ACE_TEXT("[%N:%l]: ---ProcessManager START---.\n")));int nRet = 0;CProcessManager *pProcMng = new CProcessManager();// 启动进程监控nRet = pProcMng->ProcessMonitor();if(nRet != 0){ACE_DEBUG((LM_ERROR, ACE_TEXT("[%N:%l]: ---ProcessMonitor Error---\n")));}delete pProcMng;ACE_DEBUG((LM_INFO, ACE_TEXT("[%N:%l]: ---ProcessManager STOP---.\n")));return 0;}
头文件CProcessManager.h
类的定义如下
//CProcessManager.h#include <stdio.h>#include <stdlib.h>#include <vector>#include <string>#include <map>using namespace std;#include "ace/OS.h"#include "ace/streams.h"#include "ace/Log_Msg.h"#include "ace/Date_Time.h"#include "ace/Event_Handler.h"#include "ace/Reactor.h"#include "ace/Process_Manager.h"// 进程监控,进程崩溃后,自动重新启动进程class CProcessManager{public:CProcessManager(){};virtual ~CProcessManager(){};// 从配置文件读取进程列表信息virtual int ReadConfigProcessInfo(char *pFileName);// 启动进程,并进行进程监控,进程崩溃后,自动重新启动进程virtual int ProcessMonitor();private:vector<string> m_vConfigProcessInfo; // 进程列表信息};// 回调事件,程序退出后,执行handle_exit函数class CProcessExitHandler: public ACE_Event_Handler{public:CProcessExitHandler(){};virtual ~CProcessExitHandler(){};// 程序退出后,执行该函数virtual int handle_exit(ACE_Process* process);};
//CProcessManager.cpp类中函数的实现
//实现自动重新启动进程
//CProcessManager.cpp#include "CProcessManager.h"ACE_Process_Manager *g_pPM; // 进程管理map<string, pid_t> g_mapProcessInfo; // 进程ID管理列表// 读取进程列表配置文件int CProcessManager::ReadConfigProcessInfo(char *pFileName){char *pTemp = NULL;char szTemp[1024];string strTemp = "";if(NULL == pFileName) {ACE_DEBUG((LM_ERROR, ACE_TEXT("[%N:%l]: Parameter FileName is null.\n")));return -1;}// 文件格式//./PROCESS_MANAGER 1//./PROCESS_MANAGER 2// 打开进程列表配置文件FILE *fp = fopen(pFileName, "r");if(NULL == fp){ACE_DEBUG((LM_ERROR, ACE_TEXT("[%N:%l]: file open error.[%s]\n"), pFileName));return -2;}// 循环读取进程列表配置文件while(1){memset(szTemp, 0, sizeof(szTemp));pTemp = fgets(szTemp, sizeof(szTemp), fp);if(NULL == pTemp){break;}// 去掉注释if(szTemp[0] == '#'){continue;}strTemp = szTemp;if(strTemp.length() == 0){continue;}// 去掉回车换行if(strTemp[strTemp.length() - 1] == '\n'){strTemp[strTemp.length() - 1] = 0;}if(strTemp.length() == 0){continue;}if(strTemp[strTemp.length() - 1] == '\r'){strTemp[strTemp.length() - 1] = 0;}if(strTemp.length() == 0){continue;}// 把读取的进程信息放到[进程列表信息]全局变量m_vConfigProcessInfo.push_back(strTemp);}// 关闭进程列表配置文件fclose(fp);// [进程列表信息]不应该为0if(m_vConfigProcessInfo.size() == 0){ACE_DEBUG((LM_ERROR, ACE_TEXT("[%N:%l]: Process list is null.[%s]\n"), pFileName));return -3;}return 0;}// 进程监控// 根据配置文件启动进程,并注册进程退出时回调函数int CProcessManager::ProcessMonitor(){int nRet = 0;vector<string>::iterator itrConfig;string strStartProcess;m_vConfigProcessInfo.clear();// 读取进程列表配置文件nRet = ReadConfigProcessInfo("ProcessManager.conf");if(nRet != 0){ACE_DEBUG((LM_ERROR, ACE_TEXT("[%N:%l]: ReadConfigProcessInfo[%s] error.\n"), "ProcessManager.conf"));return -1;}// Instantiate a process manager with space for 100 processes.g_pPM = new ACE_Process_Manager(ACE_Process_Manager::DEFAULT_SIZE, ACE_Reactor::instance());CProcessExitHandler procExitHandler;// 循环配置进程列表,启动进程for(itrConfig = m_vConfigProcessInfo.begin(); itrConfig != m_vConfigProcessInfo.end(); ++itrConfig){strStartProcess = *itrConfig;// 启动进程ACE_Process_Options options;options.command_line(strStartProcess.c_str());pid_t pid = g_pPM->spawn(options);// 启动进程失败if (pid == ACE_INVALID_PID){ACE_DEBUG((LM_ERROR, ACE_TEXT("[%N:%l]: start a child process success(%d)%s\n"), pid, strStartProcess.c_str()));return -1;}ACE_DEBUG((LM_INFO, ACE_TEXT("[%N:%l]: start a child process success(%d)%s\n"), pid, strStartProcess.c_str()));// 注册回调(进程退出时,调用该回调)g_pPM->register_handler(&procExitHandler, pid);// 添加启动成功的进程到进程ID管理列表g_mapProcessInfo[strStartProcess] = pid;ACE_OS::sleep(1);}// Run the reactor event loop waiting for events to occur.ACE_Reactor::instance()->run_reactor_event_loop();//ACE_Reactor::instance()->end_reactor_event_loop();return 0;}// 进程退出回调函数// 程序退出后,执行该函数,重新启动进程int CProcessExitHandler::handle_exit(ACE_Process* process){map<string, pid_t>::iterator itrProcess;ACE_DEBUG((LM_INFO,ACE_TEXT("[%N:%l]: Process %d exited with exit code %d\n"),process->getpid (), process->return_value()));// 循环进程ID管理列表,根据进程ID找到退出的进程,重新启动进程for(itrProcess = g_mapProcessInfo.begin(); itrProcess != g_mapProcessInfo.end(); ++itrProcess){// 根据进程ID,查找进程名if(itrProcess->second == process->getpid()){// 重新启动进程ACE_Process_Options options;options.command_line(itrProcess->first.c_str());pid_t pid = g_pPM->spawn(options);// 重新启动进程失败if (pid == ACE_INVALID_PID){ACE_DEBUG((LM_ERROR, ACE_TEXT("[%N:%l]: restart a child process error(%d)%s\n"), pid, itrProcess->first.c_str()));return -1;}ACE_DEBUG((LM_INFO, ACE_TEXT("[%N:%l]: restart a child process success(%d)%s\n"), pid, itrProcess->first.c_str()));// 注册回调(进程退出时,调用该回调)g_pPM->register_handler(this, pid);// 添加启动成功的进程到进程ID管理列表itrProcess->second = pid;break;}}return 0;}