基于c++ boost库实现进程管理

基于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 
#include 
#include 

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 

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 

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 
#include 

int main () {

    auto e = std::getenv("DEBUG");
    while (true) {
        std::cout << "env=" << e <<  std::endl;
        usleep(1e6);
    }

    return 0;
}
    

4.运行结果

基于c++ boost库实现进程管理_第1张图片
如图所示,进程管理程序将被测试的test进程单独开启终端运行,且test进程读取到了设置的环境变量。

5.总结

process_manager文件中封装了进程管理类以及进程属性结构体,代码只是简单地演示了单进程管理的场景,
也可根据实际需求将初始化改为读取自定义的配置文件的形式, 达到同时管理多个进程的目的。
当然,也可根据进程属性结构体中的进程重启次数、停止时间等参数,增加条件判断,上报运行异常的进程。

6.备注

系统版本:Ubuntu 18.04 LTS。
注意:Ubuntu系统自带的Terminal终端启动后监听不到子进程运行状态,因此需要自行下载Terminator终端运行本程序。

你可能感兴趣的:(c++,boost,linux,c++,ubuntu)