使用ACE监控启动进程,进程崩溃后自动重启(windows/linux通用)

本文介绍了一种使用ACE库实现的进程监控方案,能够在进程崩溃后自动重启。通过配置文件指定待监控进程,利用ACE提供的进程管理和事件处理机制实现监控逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//使用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 file
	ACE_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 message
	ACE_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")));
	ACE_LOG_MSG->clr_flags(ACE_Log_Msg::OSTREAM);
	delete pLogOutput;
	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);
	// [进程列表信息]不应该为0
	if(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;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值