使用 boost::process 读取 cout 并写入进程的 cin
Posted
技术标签:
【中文标题】使用 boost::process 读取 cout 并写入进程的 cin【英文标题】:Read cout and write to cin of a process with boost::process 【发布时间】:2019-07-30 00:07:38 【问题描述】:我正在尝试生成一个 shell 并读取标准输出和标准错误,并让用户通过写入标准输入来运行命令。我似乎无法从 stdout 或 stderr 读取数据,而且写入 stdin 显然也无济于事。
如果我不尝试重定向任何 stdin、stdout 或 stderr,它会生成一个正常的 shell,就像我期望的那样。然而,重定向它们只会让一切都消失。 >>
只是神秘地挂起。我从孩子的标准输出中取出,然后将其放回实际的标准输出中,所以我希望至少会出现类似我的用户名的内容,但就像我说的那样,它只是阻塞,因为缓冲区中必须没有任何内容。
boost::process::child shell;
boost::process::opstream instream;
boost::process::ipstream errstream;
boost::process::ipstream outstream;
void console_out_read()
char ch;
do
outstream >> ch;
std::cout << ch;
while(true);
void console_err_read()
char ch;
do
errstream >> ch;
std::cerr << ch;
while(true);
void console_in_write()
int ch;
do
std::cin >> ch;
instream << ch;
while(true);
int main()
std::error_code ec;
shell = boost::process::child("bash",
boost::process::std_out > outstream,
boost::process::std_err > errstream,
boost::process::std_in < instream,
ec);
boost::thread cro(console_out_read);
boost::thread cre(console_err_read);
boost::thread cwi(console_in_write);
shell.wait();
return 0;
【问题讨论】:
console_out_read
永远不会对 ch
做任何事情并且永远不会返回。
【参考方案1】:
您发布的代码存在几个问题。
首先,在console_in_write
中,您将ch
声明为int
而不是char
。这意味着std::cin
将只接受看起来像数字的东西。如果您输入的不是数字,这会导致std::cin
进入错误状态。
其次,即使将ch
更改为char
,std::cin >> ch
也永远不会读取换行符,因为格式化的输入操作会丢弃空格。解决这个问题最简单的方法是使用std::getline
逐行读取而不是逐字符读取,并且在您读取的每一行之后写一个换行符。
第三,boost 的管道流是完全缓冲的。这意味着您需要在编写换行符后刷新流,以便将数据发送到您的子进程。否则,您将键入一个命令,但不会发生任何事情,因为数据只是位于流的缓冲区中。
第四,std::thread
s 在超出范围之前必须是join
ed 或detach
ed。由于您目前没有对 I/O 线程执行此操作,因此一旦您的子进程退出,父进程就会崩溃。
把这些放在一起,我希望一个最小的例子看起来像这样:
boost::process::child shell;
boost::process::opstream instream;
boost::process::ipstream errstream;
boost::process::ipstream outstream;
void console_out_read()
std::string line;
while (std::getline(outstream, line))
std::cout << line << '\n';
void console_err_read()
std::string line;
while (std::getline(errstream, line))
std::cout << line << '\n';
void console_in_write()
std::string line;
while (std::getline(std::cin, line))
instream << line << std::endl;
if (line == "exit") return;
int main()
std::error_code ec;
shell = boost::process::child("bash",
boost::process::std_out > outstream,
boost::process::std_err > errstream,
boost::process::std_in < instream,
ec);
std::thread cro(console_out_read);
std::thread cre(console_err_read);
std::thread cwi(console_in_write);
shell.wait();
cro.join();
cre.join();
cwi.join();
【讨论】:
是否可以在不写换行符的情况下使它们无缓冲或刷新,就像在 c 中一样? 如果你想要原始的无缓冲管道 I/O,你可以传递boost::process::pipe
而不是 pstream
。以上是关于使用 boost::process 读取 cout 并写入进程的 cin的主要内容,如果未能解决你的问题,请参考以下文章
Boost.Process - 如何让一个进程运行一个函数?
如何使用 Boost.Process 从“类型”(Windows)获取跟踪?
Windows 上的 Boost::process - 使用 MinGW?
带有标准输出重定向的`boost :: process`在Ubuntu 16中随机失败