基于c++ boost库实现进程管理
1.前言
基于c++ boost库与Terminator终端,实现启动进程、进程运行状态监听、自动重启进程、杀死进程、设置进程环境变量等基础功能。
2.原理
启动、杀死进程基于boost::process组件实现。
非阻塞监听进程基于boost::asio、boost::process组件实现。
设置进程环境变量基于boost::this_process、boost::process组件实现。
3.代码实例
3.1 process_manage.hpp
#ifndef PROCESS_MANAGER_HPP
#define PROCESS_MANAGER_HPP
#include <vector>
#include <boost/process.hpp>
#include <ctime>
namespace bp = boost::process;
/**
@class ProcessAttribute
@brief 进程属性.
@member
exception_flag:异常标志.
latest_stop_time:进程最后停止运行时间.
launch_cmd:启动进程命令.
uuid:进程唯一标识.
reboot_count:重启计数.
env:环境变量.
instance:进程的实例.
**/
struct ProcessAttribute {
bool exception_flag;
time_t latest_stop_time;
std::string launch_cmd;
std::string uuid;
uint8_t reboot_count;
bp::environment env;
bp::child instance;
};
class ProcessManager {
public:
explicit ProcessManager();
~ProcessManager();
void start_process();
bool reboot_process();
bool listener();
void kill_process(const std::string &uuid);
private:
void init();
static time_t get_current_sec() {
time_t cur_time;
return time(&cur_time);
}
std::vector<ProcessAttribute> m_instances{};
};
#endif //PROCESS_MANAGER_HPP
3.2 process_manage.cpp
#include "process_manager.hpp"
#include <iostream>
boost::asio::io_service ios;
ProcessManager::ProcessManager() {
init();
}
ProcessManager::~ProcessManager() = default;
/**
@fn init
@brief 初始化进程参数.
@param[in] void.
@param[out] void.
@return void.
**/
void ProcessManager::init() {
auto e = boost::this_process::environment();
bp::environment e_ = e;
e_["DEBUG"] = "hello world.";
ProcessAttribute p{};
p.env = e_;
p.uuid = "test";
p.launch_cmd = "cd ~/Desktop/process;./test";
m_instances.push_back(std::move(p));
}
/**
@fn start_process
@brief 在打开的终端窗口中启动指定进程.
@param[in] void.
@param[out] void.
@return void.
**/
void ProcessManager::start_process() {
for (auto &p : m_instances) {
const std::string cmd = "terminator --title=" + p.uuid + " -e \"" + p.launch_cmd + "\" -x bash";
if (p.env.empty()) {
p.instance = bp::child(cmd, ios);
} else {
p.instance = bp::child(cmd, ios, p.env);
}
}
}
/**
@fn reboot_process
@brief 重启异常退出的进程.
@param[in] void.
@param[out] void.
@return bool.
**/
bool ProcessManager::reboot_process() {
for (auto &p : m_instances) {
if (p.exception_flag) {
const std::string cmd = "terminator --title=" + p.uuid + " -e \"" + p.launch_cmd + "\" -x bash";
if (p.env.empty()) {
p.instance = bp::child(cmd, ios);
} else {
p.instance = bp::child(cmd, ios, p.env);
}
p.exception_flag = false;
p.reboot_count++;
}
}
return true;
}
/**
@fn kill_process
@brief 根据唯一编号杀死指定进程.
@param[in] uuid:进程的唯一编号.
@param[out] void.
@return void.
**/
void ProcessManager::kill_process(const std::string &uuid) {
for (auto &p : m_instances) {
if (p.uuid == uuid) {
pid_t pid = p.instance.id();
const std::string cmd("kill -9 " + std::to_string(pid));
bp::system(cmd);
break;
}
}
}
/**
@fn listener
@brief 非阻塞监听进程状态.
@param[in] void.
@param[out] void.
@return bool.
**/
bool ProcessManager::listener() {
ios.poll();
bool exception = false;
for (auto &p : m_instances) {
if (!p.instance.running()) {
exception = true;
p.exception_flag = true;
p.latest_stop_time = get_current_sec();
std::cout << "The process has exited:" << p.uuid << std::endl;
std::cout << "reboot num=" << (int) p.reboot_count << std::endl;
}
}
return exception;
}
3.3 main.cpp
#include "process_manager.hpp"
#include <signal.h>
bool running_enable = true;
void SigintHandler(int sig) {
running_enable = false;
}
int main() {
signal(SIGINT, SigintHandler);
std::unique_ptr<ProcessManager> m_process_manager = std::make_unique<ProcessManager>();
m_process_manager->start_process();
while (running_enable) {
auto ret = m_process_manager->listener();
if (ret) {
m_process_manager->reboot_process();
}
}
return 0;
}
3.4 CMakeLists.txt
cmake_minimum_required(VERSION 3.10.0)
project(process_manager)
set(CMAKE_CXX_STANDARD 14)
find_package(Boost REQUIRED COMPONENTS system filesystem)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
file(GLOB HRD ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp)
add_executable(${PROJECT_NAME} ${SRC} ${HRD})
target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}
pthread)
3.5 文件树形结构图(进程管理)
├── CMakeLists.txt
├── doc
│ └── process_manager.md
├── include
│ └── process_manager.hpp
└── src
├── main.cpp
└── process_manager.cpp
3.6 test.cpp(被测试的进程)
#include <iostream>
#include <unistd.h>
int main () {
auto e = std::getenv("DEBUG");
while (true) {
std::cout << "env=" << e << std::endl;
usleep(1e6);
}
return 0;
}
4.运行结果
如图所示,进程管理程序将被测试的test进程单独开启终端运行,且test进程读取到了设置的环境变量。
5.总结
process_manager文件中封装了进程管理类以及进程属性结构体,代码只是简单地演示了单进程管理的场景,
也可根据实际需求将初始化改为读取自定义的配置文件的形式, 达到同时管理多个进程的目的。
当然,也可根据进程属性结构体中的进程重启次数、停止时间等参数,增加条件判断,上报运行异常的进程。
6.备注
系统版本:Ubuntu 18.04 LTS。
注意:Ubuntu系统自带的Terminal终端启动后监听不到子进程运行状态,因此需要自行下载Terminator终端运行本程序。