我在 VSCode 中有一个 Linux C++ 程序,我正在尝试调试它。我正在使用 Boost process::ipstream 发送像“ip -a”这样的命令行命令,然后尝试使用 std::getLine() 读取 iostream 并处理响应,该响应是所有网络接口的多行列表信息。我尝试了很多不同的方法,但无论我做什么,只要我发出命令,我就会在 VSCode 终端中看到响应,而我的编码阅读器逻辑什么也得不到。我已经阅读了 VSCode 终端设置,以了解如何不解析响应,但发现没有在 VSCode 的 settings.json 文件中起作用的设置。
我觉得核心问题是 VSCode 窃取终端中的响应,因此我无法在代码中获取它们。有没有人见过这样的事情以及如何禁用终端解析对我发送的 CLI 命令的响应?
郑重声明,我真正想做的是从我的 C++ 代码中运行 speedtest cli 应用程序并解析那里的响应,但我想我应该先尝试一些简单的东西,所以只是尝试能够解析来自“ip -a”命令。
我知道,代码很好。这是我最近想做的事情(绝望中我尝试了 ChatGPT 中的一些东西):
io_service io;
ip::tcp::resolver resolver(io);
boost::process::ipstream output;
// Set up the command
std::string command = "ip -a";
// Set a timeout (in seconds) for the operation
int timeout = 5;
// Start the child process to run the ping command
boost::process::child c(command, boost::process::std_out > output, io);
// As soon as I step over the above line I see the response in VSCode Terminal view
// Wait for the process to exit or timeout
if (c.wait_for(std::chrono::seconds(timeout)) == 0) {
// Process completed within the timeout
// Read and parse the output of the ping command
std::string line;
while (std::getline(output, line)) {
// Parse and process the ping output here
std::cout << "GLH: " << line << std::endl;
}
} else {
// Process didn't complete within the timeout
// I hit this timeout every time
std::cout << "Timeout occurred." << std::endl;
}
谢谢
我无法重现该问题。首先,
ip -a
似乎是无效命令。有可能输出出现在终端中是因为是错误信息,所以转到stderr
?
这是我的简化方法:
#include <boost/asio.hpp>
#include <boost/process.hpp>
#include <iomanip>
#include <iostream>
using namespace std::chrono_literals;
namespace bp = boost::process;
int main() {
boost::asio::io_context io;
std::future<std::string> output;
bp::child c("ip a", bp::std_out > output, io);
io.run_for(5s);
std::istringstream iss(output.get());
for (std::string line; std::getline(iss, line);) {
std::cout << "GLH: " << quoted(line) << std::endl;
}
}
打印:
GLH: "1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000"
GLH: " link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00"
GLH: " inet 127.0.0.1/8 scope host lo"
GLH: " valid_lft forever preferred_lft forever"
GLH: " inet6 ::1/128 scope host "
GLH: " valid_lft forever preferred_lft forever"
GLH: "2: enp4s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000"
GLH: " link/ether 90:2b:34:37:2d:9a brd ff:ff:ff:ff:ff:ff"
GLH: " inet 192.168.xx.xxx/24 brd 192.168.50.255 scope global dynamic noprefixroute enp4s0"
GLH: " valid_lft 85841sec preferred_lft 85841sec"
GLH: " inet6 fe80::def5:7afe:7fd8:fd8b/64 scope link noprefixroute "
GLH: " valid_lft forever preferred_lft forever"
GLH: "3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default "
GLH: " link/ether 02:42:92:1e:41:c3 brd ff:ff:ff:ff:ff:ff"
GLH: " inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0"
GLH: " valid_lft forever preferred_lft forever"
我会考虑立即解析,例如:
// #define BOOST_SPIRIT_X3_DEBUG 1
#include <boost/asio.hpp>
#include <boost/fusion/adapted/struct.hpp>
#include <boost/process.hpp>
#include <boost/spirit/home/x3.hpp>
#include <iomanip>
#include <iostream>
using namespace std::chrono_literals;
namespace bp = boost::process;
namespace NIC {
using boost::asio::ip::address_v4;
struct Entry {
std::string iface;
address_v4 net;
unsigned mask_number;
};
} // namespace NIC
BOOST_FUSION_ADAPT_STRUCT(NIC::Entry, iface, net, mask_number)
namespace NIC {
std::vector<Entry> parse(std::string_view sv) {
using namespace boost::spirit::x3;
auto to_address = [](auto& ctx) {
auto raw = _attr(ctx);
_val(ctx) = address_v4::from_string(std::string(raw.begin(), raw.end()));
};
auto cidr = rule<void, address_v4>{"cidr"} //
= raw[+(digit | '.')][to_address];
auto ignore = omit[*(char_ - eol) % (eol >> !(+digit | " inet "))];
auto entry = rule<void, Entry>{"entry"} = //
omit[+digit] >> ": " >> +alnum >> ": <" //
>> ignore // skip irrelevant
>> eol >> " inet " >> cidr >> '/' >> uint_ >> //
ignore;
std::vector<Entry> entries;
parse(sv.begin(), sv.end(), entry % eol, entries);
return entries;
}
} // namespace NIC
int main() {
boost::asio::io_context io;
std::future<std::string> output;
bp::child c("ip a", bp::std_out > output, io);
io.run_for(5s);
for (auto [iface, cidr, mask] : NIC::parse(output.get()))
std::cout << "iface " << iface << " net " << cidr << " mask " << mask << "\n";
}
哪个打印: