ProcessMonitor:一个跨平台的进程监控守护程序
作为开发者,我很高兴向大家介绍我开发的一个跨平台进程监控守护程序——ProcessMonitor。这是一个用C++17编写的轻量级但功能强大的工具,用于管理和监控多个子进程的生命周期。
项目背景与设计目标
在日常开发和系统运维中,我们经常需要确保关键服务进程持续运行。传统的手动监控方式效率低下,而现有的进程管理工具要么功能过于复杂,要么无法满足特定的跨平台需求。因此,我们决定开发一个简单易用、功能完备的进程监控解决方案。
主要设计目标:
- 🎯 跨平台兼容:支持Windows和Linux系统
- 🔄 自动恢复:进程异常退出时自动重启
- 📝 配置驱动:通过配置文件灵活管理多个进程
- 🧹 资源清理:自动清理僵尸进程,避免资源泄漏
- 📊 状态监控:实时监控进程运行状态
- 🚀 高性能:低资源占用,高效的事件处理
核心架构解析
1. 配置管理系统
ProcessMonitor使用INI格式的配置文件,支持全局配置和进程级配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| struct ProcessConfig { std::string name; std::string path; std::string working_dir; std::string args; std::map<std::string, std::string> env_vars; int restart_delay; int max_restarts; int graceful_timeout; std::atomic<int> restart_count{0}; std::atomic<bool> should_stop{false}; std::atomic<bool> is_running{false}; };
|
配置文件示例:
1 2 3 4 5 6 7 8 9 10 11 12
| [Global] log_level = INFO log_file = process.log check_interval = 2
[Process1] name = demo path = /work/ftpd/lsx/demo working_dir = /work/ftpd/lsx restart_delay = 3 max_restarts = 5 graceful_timeout = 10
|
配置加载的核心逻辑在 loadConfig() 方法中实现,它逐行解析配置文件,处理环境变量引用(如 ${VAR}),并验证配置的有效性。
2. 多线程监控模型
ProcessMonitor采用多线程架构,每个被监控的进程都有两个专用线程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Process { private: std::map<std::string, ProcessConfig> processes_; std::map<std::string, std::thread> monitor_threads_; std::map<std::string, std::thread> zombie_cleaner_threads_; std::atomic<bool> global_stop_{false}; #ifdef _WIN32 std::map<std::string, PROCESS_INFORMATION> process_handles_; #else std::map<std::string, pid_t> process_pids_; #endif };
|
监控线程 (monitorProcess) 定期检查进程状态,处理自动重启逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| void Process::monitorProcess(const std::string &process_name) { while (!global_stop_) { bool running = isProcessRunning(process_name); if (!running && !config.is_running) { if (restart_count < max_restarts || max_restarts == -1) { if (startProcess(config)) { config.restart_count++; config.is_running = true; } } } std::this_thread::sleep_for(std::chrono::seconds(check_interval_)); } }
|
清理线程 (zombieCleaner) 负责回收已终止的进程资源,防止僵尸进程的产生。
3. 跨平台进程管理
Windows平台实现
Windows版本使用作业对象(Job Object)来管理进程组,确保子进程能够被正确清理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| bool Process::createWindowsProcess(ProcessConfig &config, PROCESS_INFORMATION &proc_info) { BOOL success = CreateProcessA( resolved_path.c_str(), const_cast<LPSTR>(command_line.c_str()), NULL, NULL, FALSE, CREATE_NEW_PROCESS_GROUP, env_block.empty() ? NULL : LPVOID(env_block.c_str()), resolved_working_dir.c_str(), &startup_info, &proc_info ); HANDLE job = CreateJobObject(NULL, NULL); if (job) { JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info = {0}; job_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; SetInformationJobObject(job, JobObjectExtendedLimitInformation, &job_info, sizeof(job_info)); AssignProcessToJobObject(job, proc_info.hProcess); } return success; }
|
Linux/Unix平台实现
Unix版本使用进程组和信号机制:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| bool Process::createUnixProcess(ProcessConfig &config, pid_t &pid) { pid = fork(); if (pid == 0) { setsid(); if (!resolved_working_dir.empty()) { chdir(resolved_working_dir.c_str()); } setupEnvironment(config.env_vars); execv(resolved_path.c_str(), argv.data()); exit(1); } return pid > 0; }
|
4. 优雅关闭机制
ProcessMonitor实现了完善的优雅关闭流程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| bool Process::terminateUnixProcess(pid_t pid, pid_t process_group, int timeout_sec) { if (timeout_sec > 0) { kill(-process_group, SIGTERM); for (int i = 0; i < timeout_sec * 10; ++i) { if (!isUnixProcessRunning(pid)) { return true; } std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } kill(-process_group, SIGKILL); return true; }
|
5. 信号处理与主循环
主程序通过信号处理实现优雅退出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| void signalHandler(int signal) { std::cout << "Received signal: " << signal << ". Shutting down..." << std::endl; running = false; if (g_daemon) { g_daemon->stopAll(); } }
int main(int argc, char *argv[]) { signal(SIGINT, signalHandler); signal(SIGTERM, signalHandler); Process daemon; g_daemon = &daemon; daemon.loadConfig(config_file); daemon.startAll(); while (running) { std::this_thread::sleep_for(std::chrono::seconds(1)); } return 0; }
|
关键特性深度解析
1. 线程安全的配置管理
由于配置对象在多个线程间共享,我们使用原子变量和互斥锁确保线程安全:
1 2 3 4 5 6 7 8 9 10 11 12 13
| std::atomic<int> restart_count{0}; std::atomic<bool> should_stop{false}; std::atomic<bool> is_running{false};
std::unique_lock<std::mutex> lock(process_mutex_); auto it = processes_.find(process_name); if (it != processes_.end()) { ProcessConfig &config = it->second; } lock.unlock();
|
2. 智能重启策略
重启逻辑考虑了多种边界情况:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| if (!running && !is_running) { int restart_count = config.restart_count; int max_restarts = config.max_restarts; if (restart_count < max_restarts || max_restarts == -1) { log(LogLevel::WARNING, "Process " + process_name + " is not running. Restarting... (" + std::to_string(restart_count + 1) + "/" + (max_restarts == -1 ? "∞" : std::to_string(max_restarts)) + ")"); if (startProcess(config)) { config.restart_count++; config.is_running = true; } } else { log(LogLevel::ERROR, "Max restarts reached for: " + process_name); } }
|
3. 环境变量解析引擎
支持环境变量引用和动态解析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| std::map<std::string, std::string> Process::parseEnvVars(const std::string &env_str) { size_t var_start; while ((var_start = value.find("${")) != std::string::npos) { size_t var_end = value.find("}", var_start); if (var_end != std::string::npos) { std::string var_name = value.substr(var_start + 2, var_end - var_start - 2); const char *var_value = std::getenv(var_name.c_str()); if (var_value) { value.replace(var_start, var_end - var_start + 1, var_value); } } } return env_vars; }
|
构建与部署
项目使用CMake构建系统,支持交叉编译:
1 2 3 4 5 6 7
| set(COMPILER_TARGET "x86" CACHE STRING "Target architecture: x86, arm32, arm64") set(TARGET_TYPE "executable" CACHE STRING "Build target type: executable | static | shared")
file(GLOB_RECURSE SRC_FILES "${CMAKE_SOURCE_DIR}/*.cpp") file(GLOB_RECURSE HEADER_FILES "${CMAKE_SOURCE_DIR}/*.h")
|
构建命令示例:
1 2 3
| mkdir build && cd build cmake .. -DCOMPILER_TARGET=arm32 -DTARGET_TYPE=executable make -j
|
实际应用场景
ProcessMonitor已经在多个生产环境中稳定运行,主要用于:
- 微服务管理:监控多个微服务进程,确保服务高可用
- 数据处理流水线:管理数据处理任务的启动和恢复
- 嵌入式系统:在资源受限的设备上确保关键进程持续运行
- 开发环境:在开发过程中自动重启测试服务
总结
ProcessMonitor项目展示了现代C++在系统编程中的强大能力。通过合理使用原子操作、RAII、多线程和平台抽象,我们实现了一个既高效又可靠的进程监控解决方案。
项目的核心优势在于:
- ✅ 代码清晰:良好的面向对象设计和模块划分
- ✅ 性能优异:低资源占用,高效的线程调度
- ✅ 稳定可靠:完善的错误处理和边界情况处理
- ✅ 易于扩展:模块化设计便于添加新功能
我们欢迎社区贡献,共同完善这个项目。如果你在使用过程中遇到问题或有改进建议,请随时在项目仓库中提交Issue或Pull Request。
*项目地址:GitHub Repository ProcessMonitor URL *
*文档:详细使用文档 *