2014-10-17 57 views
4

我上啓動子進程的應用工作使用Boost的C++程序庫 (http://www.highscore.de/boost/process0.5) 和重定向使用以下代碼將該過程標準化爲文件: boost::process::initializers::bind_stdout(boost::iostreams::file_descriptor_sink go here )如何捕獲標準輸出和打印到控制檯都和工藝運行時文件(C++/Boost.Process)

上述解決方案和代碼運行良好。

但是,現在,我需要能夠將子進程的標準輸出到文件和控制檯。

我已經找到低於該代碼似乎它應該做的工作:

#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?) 我怎麼能夠使它的字符串/流填充的孩子過程中的標準出它的運行時,而不是隻有當它完成後?

+0

'的std ::函數getline(S,是)'是一個錯字 – sehe 2014-10-17 21:44:39

+0

右鍵,感謝。我相應地修復了原來的帖子。 – MichaelEr 2014-10-17 22:07:28

回答

1

原則上它應該按照你的要求工作。

也許你需要刷新。 (嘗試使用std::unitbuf)。

或者,您可能在Windows上,它不容易支持異步管道。該文檔描述create_async_pipe功能:

bp::pipe create_async_pipe() 
{ 
#if defined(BOOST_WINDOWS_API) 
    std::string name = "\\\\.\\pipe\\boost_process_async_io"; 
    HANDLE handle1 = ::CreateNamedPipeA(name.c_str(), PIPE_ACCESS_INBOUND | 
     FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, NULL); 
    HANDLE handle2 = ::CreateFileA(name.c_str(), GENERIC_WRITE, 0, 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 = "\\\\.\\pipe\\boost_process_async_io"; 
    HANDLE handle1 = ::CreateNamedPipeA(name.c_str(), PIPE_ACCESS_INBOUND | 
     FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, NULL); 
    HANDLE handle2 = ::CreateFileA(name.c_str(), GENERIC_WRITE, 0, NULL, 
     OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); 
    return make_pipe(handle1, 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 printing\n"; 

    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"; 
} 

的命令已經被選擇以這樣的方式,你可以驗證它以異步方式工作。

如果你想「真」不同步,也可以採用升壓短耳,詳見文件:http://www.highscore.de/boost/process0.5/boost_process/tutorial.html#boost_process.tutorial.asynchronous_i_o

+0

非常感謝。在你注意到它應該按原樣工作之後,我決定仔細檢查我正在作爲子進程執行的應用程序,結果發現問題出在Python可執行文件中(Python緩衝了標準 - 這裏是一個解決方案:http://stackoverflow.com/questions/107705/python-output-buffering) – MichaelEr 2014-10-18 17:49:12

+0

在另一個說明中,我無法編譯上面的代碼,在編譯這行時出現錯誤:'io: :filtering_ostream filt(io :: tee(std :: cout << std :: unitbuf,ofile << std :: unitbuf));'這個異常是沿着這些線的:2個重載都不能轉換所有的參數類型。任何想法爲什麼會發生,以及如何解決這個問題? – MichaelEr 2014-10-18 17:53:09

+0

btw,我測試了我的原始代碼,現在它工作得很好。你認爲我寧願適應你發佈的代碼嗎? – MichaelEr 2014-10-18 17:54:50

相關問題