我需要执行一个程序并在c ++中检索它的stdout输出.我希望我的代码也是跨平台的.
最近我发现了针对您所有跨平台需求的Boost c ++库的精彩世界,我想我会去boost.org并阅读Boost.Process的文档.令我惊讶的是,它不存在!然后我开始弄清楚Boost给他们的跨平台库启动外部进程的名称,但到目前为止还没有找到它.
谷歌搜索带我去了Julio M. Merino Vidal的Boost.Process,它似乎是我正在寻找的非官方Boost库.奇怪的是,我似乎无法在该网站上找到下载链接.似乎该项目最近没有任何进展.
我终于能够在外部网站上找到Vidal的Boost.Process的下载链接,并且现在将使用它,但是我非常惊讶于我需要付出的努力才能获得跨平台的c ++库.与外部流程互动.
那么,为什么没有正式的Boost.Process?这似乎是一个非常有价值的补充.或者我完全忽视了这里明显的解决方案?您是否可以建议其他跨平台库来管理外部流程的简单启动和交互?
我在boost::child
文档页面上看到了以下代码,它们解释了如何读取子进程的输出.
http://www.boost.org/doc/libs/1_64_0/doc/html/boost_process/tutorial.html
他们说在运行您的子进程后,我们可以通过这个循环读取它: -
bp::ipstream is; //reading pipe-stream
bp::child c(bp::search_patk("nm"), file, bp::std_out > is);
//then later
while (c.running() && std::getline(is, line) && !line.empty())
data.push_back(line);
Run Code Online (Sandbox Code Playgroud)
我在这里有2个问题: -
c.running()
返回false,我们只需退出循环.在这种情况下,is
上面的流可能仍会携带丢失的数据?我想捕捉两者stdout
,stderr
而不必担心nm
已经退出或不退出.
根据Boost文档("管道为什么不关闭?"部分),以下代码将导致死锁:
#include <boost/process.hpp>
#include <iostream>
namespace bp = ::boost::process;
int main(void)
{
bp::ipstream is;
bp::child c("ls", bp::std_out > is);
std::string line;
while (std::getline(is, line))
{
std::cout << line << "\n";
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
文件说:
这也会死锁,因为子进程退出时管道不会关闭.因此,即使进程已经结束,ipstream仍将查找数据.
但是,我无法重现死锁(在Linux下).此外,我不明白为什么首先会发生僵局.子进程退出后,它会关闭管道的写入端.管道的读取端仍然可供父进程读取,并且std::getline()
一旦管道缓冲区中没有更多数据可用就会失败,并且写入端已关闭,对吗?如果在执行子进程期间管道缓冲区填满,子进程将阻止等待父进程从管道读取足够的数据,以便它可以继续.
因此,如果上面的代码可以死锁,有没有一种简单的方法来重现死锁场景?
更新:
实际上,使用Boost进程的下面一段代码死锁:
#include <boost/process.hpp>
#include <iostream>
namespace bp = ::boost::process;
int main()
{
bp::ipstream is;
bp::child c("/bin/bash", bp::args({"-c", "ls >&40"}), bp::posix::fd.bind(40, is.rdbuf()->pipe().native_sink()));
std::string line;
while (std::getline(is, line))
{
std::cout << line << "\n";
}
c.wait();
return …
Run Code Online (Sandbox Code Playgroud) 我正在尝试将boost库导入到我的C++项目中,并且由于某种原因它找不到Boost.Process,尽管它找到了其他的.
我的CMakeLists.txt文件:
cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
set (PROJECT_NAME "test-stuff" CXX)
project (${PROJECT_NAME})
set(Boost_USE_MULTITHREADED ON)
find_package(Boost 1.64.0 REQUIRED system filesystem process)
if(Boost_FOUND)
include_directories (SYSTEM ${Boost_INCLUDE_DIR})
endif()
include_directories(include)
file(GLOB SOURCES "src/*.cpp")
add_executable(${PROJECT_NAME} ${SOURCES})
target_link_libraries (${PROJECT_NAME} ${Boost_LIBRARIES})
Run Code Online (Sandbox Code Playgroud)
完整的错误跟踪(使用调试设置):
The CXX compiler identification is AppleClang 8.1.0.8020042
-- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++
-- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile …
Run Code Online (Sandbox Code Playgroud) 我正在尝试重定向子进程的标准输入和标准输出。想用来自缓冲区的二进制数据填充进程的标准输入并读取它,(但现在我只需要知道有多少写入标准输出)
namespace bp = boost::process;
bp::opstream in;
bp::ipstream out;
bp::child c(Cmd.c_str(), bp::std_out > out, bp::std_in < in);
in.write((char*)buffer,bufferSize);
integer_type totalRead = 0;
char a[10240];
while (out.read(a,10240)) totalRead += out.gcount();
c.terminate();
Run Code Online (Sandbox Code Playgroud)
write 看起来是成功的,但程序卡在了 read-while 循环中,进程(子进程和父进程)在此期间保持空闲
文档提升没有提供任何使用自定义环境创建子进程的示例process::child(...)
。
给出了一个示例,process::system(...)
但该函数的system
可能操作较少(例如管道或 waitpid),因此如果可能的话,我希望有一个完整的示例process::child
。
在以下示例中,我尝试将一些数据写入子进程,该子进程处理数据并将其写入文件。关闭流后,父进程无限期地等待子进程完成。我不知道如何表明我已经完成了数据的写入,并希望子进程停止读取并完成它正在做的任何事情。根据文档调用 terminate会发送一个SIGKILL
我认为不是我想要的。
我错过了什么?我检查了这个问题,但我宁愿先尝试使实际代码与同步 IO 一起工作。
#include <boost/process.hpp>
#include <iostream>
namespace bp = boost::process;
int main(int argc, char **argv)
{
boost::process::opstream in{};
boost::process::child child("/path/to/test.py", bp::std_in < in);
in << "test1\n";
in << "test2\n";
in << "test3\n";
in << std::flush;
std::cerr << "Closing the stream…\n";
in.close();
std::cerr << "Waiting for the child to exit…\n";
child.wait(); // Parent seems to hang here.
return 0;
}
Run Code Online (Sandbox Code Playgroud)
test.py 只是将数据写入文件,如下所示:
#!/usr/local/homebrew/opt/python@3.8/bin/python3
import sys
with open("/tmp/test.txt", "w") as f:
for line in …
Run Code Online (Sandbox Code Playgroud) boost::process
我正在尝试从字符串参数向量创建一个:
void runProcess( const std::string& exe, const std::vector<std::string>& args )
{
bp::ipstream out;
bp::child c(exe, args, std_out > out);
...
}
Run Code Online (Sandbox Code Playgroud)
这显然有效,但我收到以下警告:
警告 C4503:'boost::fusion::detail::for_each_linear':超出修饰名称长度,名称被截断
如果一一传递参数,它就会消失bp::child c(exe, "param1", "param2", std_out > out);
。
在这种情况下调用child
构造函数的正确方法是什么?
我有一个主程序,它使用 boost 进程库来生成一个打印的子进程
Hello World !
Run Code Online (Sandbox Code Playgroud)
每 5 秒在其标准输出上。
我想在主进程中读取/监视子进程的标准输出,当它与在主程序中执行其他操作一起可用时。
我已经尝试了boost asynchronous IO
(http://www.boost.org/doc/libs/1_66_0/doc/html/boost_process/tutorial.html)的示例,但所有这些似乎都阻止了主程序,直到子进程退出。
我们是否需要在单独的线程中读取孩子的标准输出?有人可以提供一个示例,其中主程序可以同时做其他事情而不是阻止来自孩子的 stdout 吗?
我正在尝试使用 boost.process 写入和读取子级的 stdio,如下所示:
boost::asio::io_service writeService, readService;
bp::async_pipe in{writeService};
bp::async_pipe out{readService};
bp::child process(CompressCmd.c_str(), bp::std_in < in, bp::std_out > out);
Buffer src;
src.reserve(4 * 1024 * 1024);
integer_type read = 0;
//std::atomic_int64_t totalWrite{0};
integer_type totalWrite = 0;
while (callback(CallbackActions::NeedMoreInput, src, read)) {
in.async_write_some(
boost::asio::buffer(src.data(), read),
[](const boost::system::error_code &e, std::size_t) { });
// written data is not important, that's why using same buffer
out.async_read_some(boost::asio::buffer(src.data(), src.capacity()),
[&](const boost::system::error_code &e,
std::size_t byte_transferred) { totalWrite += byte_transferred; });
}
writeService.run();
in.close();
readService.run();
Run Code Online (Sandbox Code Playgroud)
所有读写操作都被通知为成功,但totalWrite的值完全不正确,报告为29356032,实际值应该约为50000000
我注意到程序正在中途终止,
在readService.run()冻结子进程后使用process.wait(), …
boost ×10
boost-process ×10
c++ ×10
boost-asio ×2
windows ×2
boost-fusion ×1
boost-thread ×1
cmake ×1
stderr ×1
stdio ×1
stdout ×1