首页 文章

我可以单独捕获stdout / stderr并保持原始顺序吗?

提问于
浏览
8

我使用原生win32 API编写了一个Windows应用程序 . 我的应用程序将启动其他进程并捕获输出并以红色突出显示stderr输出 .

为了实现这一点,我为stdout和stderr创建了一个单独的管道,并在调用CreateProcess时在STARTUPINFO结构中使用它们 . 然后,我为每个stdout / stderr句柄启动一个单独的线程,该句柄从管道读取并将输出记录到窗口 .

这在大多数情况下都能正常工作我遇到的问题是,如果子进程快速连续记录到stderr和stdout,我的应用程序有时会以错误的顺序显示输出 . 我假设这是由于使用两个线程从每个句柄读取 .

是否有可能以他们写入的原始顺序捕获stdout和stderr,同时能够区分这两者?

6 回答

  • 0

    我很确定它无法完成,没有编写生成的程序来写入数据包并为每个程序添加时间戳 . 如果没有这个,你通常可以计划在子进程的标准库中进行缓冲,所以当它们甚至通过管道传输给父进程时,它们很可能已经出现故障 .

  • 0

    在我见过的stdout和stderr的大多数实现中,stdout是缓冲的而stderr不是 . 基本上这意味着即使在直接命令行上运行程序,也不能保证它们能够正常运行 .

    http://en.wikipedia.org/wiki/Stderr#Standard_error_.28stderr.29

    简短的回答:您无法确保以与cmd.exe上显示的顺序相同的顺序读取行,因为它们在cmd.exe上的显示顺序无法保证 .

  • 0

    不是真的,你会这么认为,但是std_out是由系统设计师控制的 - 确切地说std_out的编写方式和时间取决于系统调度程序,我的测试通过系统调度程序从属于未记录的问题 .

    我有一天写了一些东西并在系统上的某个设备上做了一些工作,而我在编辑器中打开了代码并发现系统正在给驱动程序提供实时优先级,留下我精心设计的c-代码大约是专有代码的十分之一 .

    重新反转这一点,以便您获得写入的顺序排序,至少可以说具有挑战性 .

  • 3

    您可以将stderr重定向到stdout:

    command_name 2>&1

    我记得,在使用管道的C中这是可能的 .

    更新:哦,对不起 - 错过了能够区分两者的部分 . 我知道TextMate使用有点用户可见的代码以某种方式做到了... Haven 't looked for a while, but I'将给它一个偷看 . 但经过深思熟虑之后,你能在Ruby中使用像_567735这样的东西吗?你必须同时观察 STDOUTSTDERR ,但实际上没有人应该期待关于这两者的某种输出顺序 .

    更新2:我在Ruby中的含义示例:

    require 'open3'
    
    Open3.popen3('ruby print3.rb') do |stdin, stdout, stderr|
      loop do
        puts stdout.gets
        puts stderr.gets
      end
    end
    

    ... print3.rb 只是:

    loop do
      $stdout.puts 'hello from stdout'
      $stderr.puts 'hello from stderr'
    end
    

    您可以将消息直接发送到 puts ,而不是将消息发送给观察者,该观察者会在您的程序中将其打印出来 . 对不起,我在这台机器上没有Windows(或任何立即可用的),但我希望这说明了这个概念 .

  • 2

    我很确定,即使你将它们分开,你也会以正确的顺序互相交换 .

  • 0

    由于意图是对现有程序的输出进行注释,因此两个流的任何可能的交错必须是正确的 . 原始开发人员将进行适当的flush()调用,以确保遵守任何强制性排序 .

    如前所述,记录用时间戳写入的每个片段,并使用它来恢复输出设备实际看到的序列 .

相关问题