【问题标题】:run external program in Ruby IO.popen : rescue not working在 Ruby IO.popen 中运行外部程序:救援不起作用
【发布时间】:2015-05-04 09:28:57
【问题描述】:

我正在使用Tika jar 从 Microsoft Word doc 文件中提取元数据,但如果 Tika 遇到问题,我的救援没有发现错误,而是退出了脚本。我在装有 MRI Ruby 1.9.3 的 Windows 7 上 我可以调整 doc 文件,但我想避免以后的文件出现这个问题。 如何捕获此错误?

JARPATH = "jar/tika-app-1.6.jar"

def metadata
    return @metadata if defined? @metadata
    switch = '-m -j'
    begin
      command = %Q{java -Djava.awt.headless=true -jar #{JARPATH} #{switch} "#{@path}"}
      output = IO.popen(command+" 2>&1") do |io|
        io.read
      end
      if output.respond_to?(:to_str)
        @metadata = JSON.parse(output)
      else
        @metadata = nil
      end
    rescue => e
      puts e
      puts e.backtrace
    end
  end

这是我得到的输出

c:/Ruby193/lib/ruby/gems/1.9.1/gems/json-1.8.2/lib/json/common.rb:155:in `parse': 757: unexpected token at 'Exception in thread "main" org.apache.tika.exception.TikaException: TIKA-198: Illegal IOExce
ption from org.apache.tika.parser.microsoft.OfficeParser@1006d75 (JSON::ParserError)
        at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:250)
        at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:244)
        at org.apache.tika.parser.AutoDetectParser.parse(AutoDetectParser.java:121)
        at org.apache.tika.cli.TikaCLI$OutputType.process(TikaCLI.java:143)
        at org.apache.tika.cli.TikaCLI.process(TikaCLI.java:422)
        at org.apache.tika.cli.TikaCLI.main(TikaCLI.java:113)
Caused by: java.io.IOException: Invalid header signature; read 0x04090000002DA5DB, expected 0xE11AB1A1E011CFD0 - Your file appears not to be a valid OLE2 document
        at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:140)
        at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:115)
        at org.apache.poi.poifs.filesystem.NPOIFSFileSystem.<init>(NPOIFSFileSystem.java:204)
        at org.apache.poi.poifs.filesystem.NPOIFSFileSystem.<init>(NPOIFSFileSystem.java:163)
        at org.apache.tika.parser.microsoft.OfficeParser.parse(OfficeParser.java:162)
        at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:244)
        ... 5 more
'
        from c:/Ruby193/lib/ruby/gems/1.9.1/gems/json-1.8.2/lib/json/common.rb:155:in `parse'
        from C:/Users/.../tika.rb:37:in `metadata'
        from C:/Users/.../index_helpers.rb:55:in `index_doc'
        from index.rb:39:in `block in <main>'
        from index.rb:20:in `each'
        from index.rb:20:in `each_with_index'
        from index.rb:20:in `<main>'

【问题讨论】:

  • 为什么不使用Tika network server 而不是每次调用应用程序时都生成一个新的JVM?您将通过网络发布您的内容,并取回元数据或错误,与您的 ruby​​ 很好地隔离
  • 另外,您的堆栈跟踪中的特定错误已在最新版本的 Apache Tika 中修复,您使用旧版本是否有原因?
  • @Gagravarr,这里的小企业,需要尽量减少正在运行的服务器进程的数量,只有运行的网络服务器是我宁愿不使用的 IIS 和 Tomcat。 Tika 与 Yomi Gem 一起安装,我决定不使用它,而是酿造我自己的课程来与 Tika 交互。 Tika 从命令行运行时出现同样的错误,我将看看那个新版本。
  • 那个代码无效,你有IO.popen(...) do |io| ... rescue ...rescue 不允许在那里,应该有一个end
  • @peter 我只是说要注意这一点。您今天编写的代码“工作正常”,后来当有人上传“Untitled Document.docx”时它在生产中爆炸。

标签: ruby popen apache-tika


【解决方案1】:

调用IO.popen 后,您将子程序的输出传递给JSON.parse,无论它是否有效。您看到的异常是 json 解析器试图解析 Java 异常方法,因为您使用 2&gt;&amp;1 重定向 stderr 而被捕获。

在继续之前,您需要检查子进程是否成功完成。最简单的方法大概是在调用popen之后,使用$?这个特殊变量,它表示最后执行的子进程的状态。如果Process::Status,此变量是一个实例。你可以这样做:

output = IO.popen(command+" 2>&1") do |io|
  io.read
end

unless $?.success?
  # Handle the error however you feel is best, e.g.
  puts "Tika had an error, the message was:\n#{output}"
  raise "Tika error"
end

要获得更多控制,您可以查看标准库中的Open3 module。由于 Tika 是一个 Java 程序,另一种可能是研究使用 JRuby 并直接调用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-31
    • 2017-09-05
    • 2021-10-24
    • 2012-02-26
    • 1970-01-01
    • 1970-01-01
    • 2023-01-13
    相关资源
    最近更新 更多