2014-10-27 90 views
0

我使用:红宝石 - Open3没有完成子

- 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/process时,Open3的工作原理是这样(我不是100%肯定,但尝试了几次后,我认为是唯一的选择)

  • 读取命令并执行它们(这是确定)

  • 试图通过ODBC方法(在这里从DB读的是我的PROBL EM。 I 需要从Open3接收一些输出,以便我可以在浏览器中显示它,但我猜测它什么时候尝试读取它会启动Open3不知道的另一个进程,因此Open3继续并完成而不等待它)

  • 退出

退出

我发现有关以下内容:

  • 使用的Thread.join(在这种情况下,w.join),以等待进程结束,但它不起作用
  • OPEN4似乎处理子进程,但在Windows不起作用
  • Process.wait(PID),在这种情况下PID = w.pid,但也不起作用
  • Timeout.timeout(N) ,这里的问题是我不知道它需要多长时间。

有没有办法处理这个问题?提前(等待Open3子,所以我得到正确的输出)

感谢

+0

URL“http:// localhost/process”的意义是什么? – hagello 2014-11-30 06:56:20

回答

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 
+0

我试过这个,问题是当我打印“w.value.exited?它返回true ...所以Open3.popen3(program_path,file_name)实际完成,似乎没有完成它的子进程(我只是猜测) – JavierQQ23 2014-10-29 16:01:03

+0

更新我的答案与我们使用的完整代码 – bridiver 2014-10-29 19:30:31

+0

备忘录被定义作为“备忘录= []”还是其他东西?我得到了未定义的变量错误 – JavierQQ23 2014-10-30 01:47:46

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*。他们做所有困难的事情,如同时等待stdout和stderr