加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

如何在进程运行时捕获标准输出并打印到控制台和文件(C /Boost.Pr

发布时间:2020-12-16 07:10:04 所属栏目:百科 来源:网络整理
导读:我正在开发一个使用Boost的C Process库启动子进程的应用程序 ( http://www.highscore.de/boost/process0.5) 并使用以下代码将标准从该进程重定向到文件: ????boost :: process :: initializers :: bind_stdout(boost :: iostreams :: file_descriptor_sink
我正在开发一个使用Boost的C Process库启动子进程的应用程序
( http://www.highscore.de/boost/process0.5)
并使用以下代码将标准从该进程重定向到文件:
????boost :: process :: initializers :: bind_stdout(boost :: iostreams :: file_descriptor_sink到这里)

上述解决方案和代码运行良好.

但是,现在,我需要能够将子进程的标准输出到文件和控制台.

我发现下面的代码似乎应该做的工作:

#include <boost/process.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <iostream>

using namespace boost::process;
using namespace boost::process::initializers;
using namespace boost::iostreams;

int main()
{
    boost::process::pipe p = create_pipe();
    {
        file_descriptor_sink sink(p.sink,close_handle);
        execute(
            run_exe("/bin/echo"),set_cmd_line("echo hello"),bind_stdout(sink)
        );
    }
    file_descriptor_source source(p.source,close_handle);
    stream<file_descriptor_source> is(source);
    std::string s;
    while (std::getline(is,s))
    {
            std::cout << s << std::endl;
            //will write line by line to file here
    }
}

我已经尝试运行上面的代码,事实上我能够将输出打印到控制台和文件.
但是上面的代码存在一个主要问题(至少在我的情况下),
while循环(while(std :: getline(is,s)))仅在调用的进程退出后启动,这意味着在进程完成后立即打印在进程运行期间累积的所有输出.

现在,
我需要的是能够在运行期间从调用的进程获取输出,并在它到来时将其打印到控制台和文件(而不是仅在结束时).

(由于我启动的进程不受我的控制,甚至可能需要几分钟才能运行,目前屏幕控制台只是空的,直到进程退出).

我已经找了很多网站试图找到这个解决方案,并且在代码中玩了很多,但我似乎无法解决这个问题.

如何实现这一目标? (甚至可以使用Boost.Process吗?)
如何在运行时期间使用std从子进程填充该字符串/流,而不是只在它完成时?

解决方法

原则上它应该按照您的要求工作.

也许你需要冲洗. (尝试使用std :: unitbuf).

或者,您可能在Windows上,它不支持异步管道.文档描述了create_async_pipe函数:

bp::pipe create_async_pipe()
{
#if defined(BOOST_WINDOWS_API)
    std::string name = "\.pipeboost_process_async_io";
    HANDLE handle1 = ::CreateNamedPipeA(name.c_str(),PIPE_ACCESS_INBOUND |
        FILE_FLAG_OVERLAPPED,1,8192,NULL);
    HANDLE handle2 = ::CreateFileA(name.c_str(),GENERIC_WRITE,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);
    return make_pipe(handle1,handle2);
#elif defined(BOOST_POSIX_API)
    return create_pipe();
#endif
}

所以,这是一个结合了它的版本,完整的tee设备:

#include <boost/process.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/tee.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <iostream>
#include <fstream>

namespace bp = boost::process;
namespace io = boost::iostreams;
using namespace bp;
using namespace bp::initializers;

bp::pipe create_async_pipe()
{
#if defined(BOOST_WINDOWS_API)
    std::string name = "\.pipeboost_process_async_io";
    HANDLE handle1 = ::CreateNamedPipeA(name.c_str(),handle2);
#elif defined(BOOST_POSIX_API)
    return create_pipe();
#endif
}

int main()
{
    bp::pipe p = create_async_pipe();

    {
        io::file_descriptor_sink sink(p.sink,io::close_handle);
        execute(
            run_exe("/bin/sh"),set_cmd_line("sh -c "echo started; sleep 3 && date""),bind_stdout(sink)
        );
    }

    io::file_descriptor_source source(p.source,io::close_handle);
    io::stream<io::file_descriptor_source> is(source);

    std::cout << "Process is running,let's wait before printingn";

    system("sleep 1");

    std::ofstream ofile("test.log");
    io::filtering_ostream filt(io::tee(std::cout << std::unitbuf,ofile << std::unitbuf));

    std::string s;
    while (std::getline(is,s))
        filt << s << "n";
}

已经选择了这些命令,您可以验证它是否以异步方式工作.

如果您想要“真正的”异步,您也可以使用Boost Asio,有关详细信息,请参阅文档:http://www.highscore.de/boost/process0.5/boost_process/tutorial.html#boost_process.tutorial.asynchronous_i_o

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读