处理ruby中的子进程

时间:2014-10-04 10:29:50

标签: ruby

我需要运行一个子进程,执行一些代码,然后终止已启动的进程;我不需要这个子流程的输出。我试过这样的事情:

def start
  @@rtorrentIO ||= IO.popen("rtorrent")
  sleep 0.5
end
def stop
  Process.kill(9, @@rtorrentIO.pid) if defined? @@rtorrentIO
  @@rtorrentIO = nil
end

start
sleep 0.5
#some code there
stop

但是终端对我所做的任何动作都没有反应(甚至 Ctrl + C 转义)。我做错了什么?

更新 我在初始条件下犯了一个小错误。实际上终端会对我的所有操作做出反应,但在命令执行之前我没有看到任何符号。在下图中,我始终执行以下命令:mangaParser.rb;我是谁; PS; 这就是我得出的结果: enter image description here

但是,如果我尝试用 Ctrl + C 转义来破坏运行命令,那就失败了(例如,如果没有,我就不能打破以下命令序列其他终端:mangaParser.rb; ping google.com;)

1 个答案:

答案 0 :(得分:1)

如果我将其更改为

#!/usr/bin/env ruby

def start
  @rtorrentIO ||= IO.popen("rtorrent",'w') #default mode is 'r'
  sleep 0.5
end
def stop
  Process.kill(9, @rtorrentIO.pid) if defined? @rtorrentIO
  @rtorrentIO = nil
end

start


sleep 0.5
#some code there
stop

使它成为一个独立的例子,它对我来说很好。您应该打开用于撰写(..,"w")的管道,因为您对输出不感兴趣(如果您对编写它不感兴趣,那么打开它是没有意义的使用popen进行处理,并且您最好使用pid = Process.spawn('rtorrent')之类的内容。

<强>更新 您遇到的问题是rtorrent通过在输出中写入特殊的终端控制序列(有意或无意)来弄乱您的终端。这种情况会不时发生(cat随机二进制文件很可能会弄乱您的终端,因为您可能会遇到一个对终端有点特殊的字节序列) 。解决方案是在终端中运行reset(有关详情,请参阅man reset) - 您必须盲目输入。

如果您不希望rtorrent这样做,重定向其 stdout stderr (这些通常绑定到您的终端)将是最重要的可能会阻止它写入您的终端。除此之外,您可以使用system reset方法stop来修复rtorrent所做的事情。

以下是上述内容的组合:

#!/usr/bin/env ruby

def start
  @pid ||= Process.spawn "rtorrent" #, err: '/dev/null', out: '/dev/null'
  sleep 0.5
end
def stop
  Process.kill(9, @pid) if @pid
  @pid = nil
  system 'reset'
end

start


sleep 0.5
#some code there
stop