0

我在用着:

- Ruby 1.9.3-p448
- Windows Server 2008

我有一个包含程序使用的命令的文件,我正在以这种方式使用它

C:\> PATH_TO_FOLDER/program.exe file.txt

File.txt有一些命令,所以program.exe将执行以下操作:

- Execute commands 
- Reads from a DB using an ODBC method used by program
- Outputs result in a txt file

使用 powershell 此命令可以正常工作并且符合预期。

现在我在一个文件(app.rb)中有这个:

require 'sinatra'
require 'open3'

get '/process' do
  program_path = "path to program.exe"
  file_name = "file.txt"
  Open3.popen3(program_path, file_name) do |i, o, e, w|
    # I have some commands here to execute but just as an example I'm using o.read
    puts o.read
  end
end

现在,当通过访问来使用它时http://localhost/processOpen3可以通过这样做来工作(我不是 100% 确定,但在尝试了几次之后,我认为这是唯一的选择)

  • 读取命令并执行它们(这没关系)

  • 尝试使用 ODBC 方法从 DB 读取(这是我的问题。我需要从其中接收一些输出,Open3以便可以在浏览器中显示它,但我猜当它尝试读取它时会启动另一个Open3不知道的进程,所以Open3 继续并完成而不等待它)

  • 出口

出口

我发现了以下内容:

  • 使用Thread.join(在这种情况下,w.join)为了等待进程完成,但它不起作用
  • Open4似乎可以处理子进程,但在 Windows 上不起作用
  • Process.wait(pid),在这种情况下pid = w.pid,但也不起作用
  • Timeout.timeout(n),这里的问题是我不确定需要多长时间。

有没有办法处理这个?(等待Open3子进程,所以我得到正确的输出)。

4

2 回答 2

0

Open3.popen3仅在琐碎的情况下使用很容易。我不知道处理子进程的输入、输出和错误通道的真实代码。我也不知道你的子进程的确切行为:它写在标准输出上吗?它写在stderr上吗?它是否尝试从标准输入读取?

这就是为什么我认为您替换为puts o.read. 关于您可能遇到的问题的一个很好的总结是http://coldattic.info/shvedsky/pro/blogs/a-foo-walks-into-a-bar/posts/63

尽管我不同意这篇文章的作者 Pavel Shved 在寻找解决方案方面的看法。他推荐了自己的解决方案。我只是popen3在我的项目中使用了其中一个包装函数:Open3.capture*. 他们做所有困难的事情,比如同时等待标准输出和标准错误。

于 2014-11-30T07:15:05.763 回答
0

我们在获取退出状态时遇到了类似的问题,这就是我们所做的

Open3.popen3(*cmd) do |stdin, stdout, stderr, wait_thr|

  # print stdout and stderr as it comes in
  threads = [stdout, stderr].collect do |output|
    Thread.new do
      while ((line = output.gets rescue '') != nil) do
        unless line.blank?
          puts line
        end
      end
    end
  end

  # get exit code as a Process::Status object
  process_status = wait_thr.value #.exitstatus

  # wait for logging threads to finish before continuing
  # so we don't lose any logging output
  threads.each(&:join)

  # wait up to 5 minutes to make sure the process has really exited
  Timeout::timeout(300) do
    while !process_status.exited?
      sleep(1)
    end
  end rescue nil

  process_status.exitstatus.to_i
end
于 2014-10-28T22:25:59.287 回答