c++ - 如果命令的结果很长,`boost::process::child` 将挂起
问题描述
我有一个简单的 C++ 程序,用于boost::process:child
接收终端命令并执行它,然后打印出结果。但是,如果我执行类似的命令ps aux
,整个程序将没有响应。我不确定如何解决。我试过调试它,调试器只会停在cp.wait()
.
try{
child cp(cmd+" "+param, (std_out & std_err) > pipe);
cp.wait();
return_code = cp.exit_code();
}catch (process_error e){
return_code = -1;
}
解决方案
您需要消耗管道。管道连接到什么(换句话说,谁在使用它?)。
如果看起来确实如此,您对输出根本不感兴趣,只需重定向到 null 设备:
作为旁注,我强烈反对
using namespace boost::process
,因为它看起来像你正在做的。该命名空间中有许多名称很容易与 C/标准库名称发生冲突。例如,是pipe
局部变量吗?是类型boost::process::pipe
吗?是 POSIX 系统库调用::pipe
吗?
使固定
#include <boost/process.hpp>
#include <iostream>
int main()
{
namespace bp = boost::process;
std::string cmd = "cat", param = "/etc/dictionaries-common/words";
//bp::pipe pipe;
int return_code = -1;
try {
bp::child cp(cmd + " " + param, (bp::std_out & bp::std_err) > bp::null);
cp.wait();
return_code = cp.exit_code();
} catch (bp::process_error const& e) {
return_code = -1;
}
std::cout << "return_code: " << return_code << "\n";
return return_code;
}
请注意,它会1
在 Coliru 上返回,因为该字典不存在。在我的系统上它正确返回0
(没有阻塞。
安全
请注意,将命令拼凑成字符串可能非常容易出错并引发安全漏洞(如果传入的文件名是“foot.txt; rm -rf *”怎么办?)。
我会使用参数向量样式:
std::string cmd = "cat";
std::vector<std::string> params{"-n", "--",
"/etc/dictionaries-common/words"};
bp::child cp(bp::search_path(cmd), params,
(bp::std_out & bp::std_err) > bp::null);
更安全的是不使用
search_path
,但它要求 exe 是完全指定的路径(如/bin/cat
or./bin/myexe
)。
请注意,现在接受来自外部输入的文件名已经足够安全了:
std::vector<std::string> params{"-n", "--"};
params.insert(end(params), argv + 1, argv + argc);
作为画龙点睛的一笔,让我们关闭子进程的标准输入(这样我们就不会在那里泄露隐私,如果命令行上没有列出文件也不会挂起......):
#include <boost/process.hpp>
#include <iostream>
int main(int argc, char** argv)
{
namespace bp = boost::process;
int return_code = -1;
try {
std::string cmd = "/bin/cat";
std::vector<std::string> params{"-n", "--"};
params.insert(end(params), argv + 1, argv + argc);
bp::child cp(cmd, params, //
bp::std_in.close(), //
(bp::std_out & bp::std_err) > bp::null);
cp.wait();
return_code = cp.exit_code();
} catch (bp::process_error const& e) {
return_code = -1;
}
std::cout << "return_code: " << return_code << "\n";
return return_code;
}
现在它打印return_code: 0
了,因为文件实际上存在于 Coliru 上。
推荐阅读
- swift - Hackerrank 苹果和橙子问题测试用例在快速提交时失败
- excel - 使用actxserver MATLAB在单元格中提取条件格式的公式
- java - 为什么在生产代码中使用断言框架不好?
- javascript - 使用ajax(JQuery)在html文档中填充选择
- visual-studio-code - VSCode 扩展:获取自定义大纲的功能大纲
- java - 使用 Apache POI 为 Cell 设置值时出现 NoSuchMethodError
- linux - 如何使用 sed 删除两个模式之间的所有换行符(“\n”)
- postgresql - 如何访问只能从本地 Kubernetes 集群访问的数据库?
- json - 迭代对象并打印选择值
- python - 如何在给定条件下用其他行的值填充 DataFrame 的数据?