使用Boost.Process能否在进程运行时读取其输出,如何实现?
核心结论
不需要等待进程终止,就可以在进程运行期间读取其输出,你当前写法的问题在于直接将进程输出绑定到固定Asio缓冲的逻辑会阻塞到进程输出完毕、管道关闭才返回,调整为异步分段读取方案即可实现需求。
实现方案
核心思路
不将输出全量绑定到固定缓冲,而是通过异步管道逐段读取进程输出,每读到一段数据就立刻检查是否包含启动成功的特征标识,一旦检测到标识就停止读取逻辑,进程仍会保持正常运行。
示例代码
#include <boost/process.hpp> #include <boost/asio.hpp> #include <string> #include <functional> #include <iostream> namespace bp = boost::process; namespace asio = boost::asio; int main() { asio::io_service ios; // 存储已读到的输出内容 std::string output_buf; // 替换为你的进程启动成功的特征字符串 const std::string success_flag = "Service started successfully"; bool is_start_verified = false; // 创建异步管道绑定进程标准输出 bp::async_pipe out_pipe(ios); bp::child target_proc("process_that_needs_to_keep_running", bp::args({/* 你的进程参数 */}), bp::std_out > out_pipe, ios); // 异步读回调 std::function<void(const boost::system::error_code&, std::size_t)> read_handler; read_handler = [&](const boost::system::error_code& ec, std::size_t read_len) { if (ec || is_start_verified) { return; } // 追加新读到的内容 output_buf.resize(output_buf.size() + read_len); // 检查是否包含启动成功标识 if (output_buf.find(success_flag) != std::string::npos) { is_start_verified = true; // 验证通过,取消读操作、停止io_service,不会终止目标进程 out_pipe.cancel(); ios.stop(); return; } // 未匹配到标识,继续异步读下一段 out_pipe.async_read_some( asio::buffer(&output_buf[output_buf.size()], 1024), read_handler ); }; // 启动首次异步读 out_pipe.async_read_some(asio::buffer(output_buf, 1024), read_handler); // io_service会在验证通过/读取出错时返回,不会等待进程结束 ios.run(); if (is_start_verified) { std::cout << "进程启动验证通过,进程持续运行中" << std::endl; // 注意:如果后续不需要管理进程生命周期,可调用detach,否则要保留target_proc对象的生命周期 target_proc.detach(); // 此处执行后续业务逻辑 } else { std::cerr << "进程启动验证失败" << std::endl; // 验证失败可主动终止异常进程 target_proc.terminate(); } return 0; }
注意事项
- 如果特征字符串较长,可能出现被分段截断的情况,可保留上一次读取末尾、长度等于特征串长度的内容,和新读到的内容拼接后再做匹配,避免漏判
- 可额外加异步定时器实现超时逻辑,避免进程启动失败时io_service长期阻塞
- 若不需要后续对进程做终止等管理操作,调用
detach()即可,否则要保证bp::child对象的生命周期和进程运行周期一致,避免对象析构时自动终止进程
内容的提问来源于stack exchange,提问作者FlashMcQueen
相关产品推荐
相关产品推荐

