7

我正在使用命令行程序,它的工作方式如下所述:

$ ROUTE_TO_FOLDER/app < "long text"

如果“长文本”是使用“app”需要的参数写入的,那么它将用结果填充一个文本文件。如果没有,它将连续用点填充文本文件(为了避免这种情况,我无法处理或修改“app”的代码)。

在 ruby​​ 脚本中有这样一行:

text = "long text that will be used by app"
output = system("ROUTE_TO_FOLDER/app < #{text}")

现在,如果文本写得好,就不会有问题,我会得到一个前面提到的输出文件。当文本写得不好时,问题就来了。接下来发生的是我的 ruby​​ 脚本挂起,我不知道如何杀死它。

我找到了 Open3并且我使用了这样的方法:

irb> cmd = "ROUTE_TO_FOLDER/app < #{text}"
irb> stdin, stdout, stderr, wait_thr = Open3.popen3(cmd)
=> [#<IO:fd 10>, #<IO:fd 11>, #<IO:fd 13>, #<Thread:0x007f3a1a6f8820 run>]

当我做:

irb> wait_thr.value

它也挂起,并且:

irb> wait_thr.status
=> "sleep"

我怎样才能避免这些问题?是不是没有认识到“应用程序”失败了?

4

1 回答 1

10

wait_thr.pid为您提供已启动进程的 pid。做就是了

Process.kill("KILL",wait_thr.pid)

当你需要杀死它时。

您可以将其与以两种方式之一检测进程是否挂起(连续输出点)结合使用。

1)设置等待进程的超时时间:

get '/process' do
  text = "long text that will be used by app"
  cmd = "ROUTE_TO_FOLDER/app < #{text}"
  Open3.popen3(cmd) do |i,o,e,w|
    begin
      Timeout.timeout(10) do # timeout set to 10 sec, change if needed
        # process output of the process. it will produce EOF when done.
        until o.eof? do
          # o.read_nonblock(N) ...
        end
      end
    rescue Timeout::Error
      # here you know that the process took longer than 10 seconds
      Process.kill("KILL", w.pid)
      # do whatever other error processing you need
    end
  end
end

2) 检查过程输出。(下面的代码已简化 - 您可能不想先将进程的输出读入单个 String buf 然后再进行处理,但我想您明白了)。

get '/process' do
  text = "long text that will be used by app"
  cmd = "ROUTE_TO_FOLDER/app < #{text}"
  Open3.popen3(cmd) do |i,o,e,w|
    # process output of the process. it will produce EOF when done. 
    # If you get 16 dots in a row - the process is in the continuous loop
    # (you may want to deal with stderr instead - depending on where these dots are sent to)
    buf = ""
    error = false
    until o.eof? do
      buf << o.read_nonblock(16)
      if buf.size>=16 && buf[-16..-1] == '.'*16
        # ok, the process is hung
        Process.kill("KILL", w.pid)
        error = true
        # you should also get o.eof? the next time you check (or after flushing the pipe buffer),
        # so you will get out of the until o.eof? loop
      end
    end
    if error
      # do whatever error processing you need
    else
      # process buf, it contains all the output
    end
  end
end
于 2014-10-09T01:43:23.757 回答