Ruby杀死使用PTY.spawn打开的虚拟shell

在ruby脚本中,我启动了更多的虚拟shell,每个都由shellpipe理器对象pipe理,如下所示:

@shell = PTY.spawn 'env PS1="\w>" TERM=dumb COLUMNS=63 LINES=21 sh -i' 

在稍后的某个时间点,我想销毁这个实例,并杀死关联的shell进程。 可悲的是,我无法正常工作。 这是我尝试的,按照工作的概率顺序:

  • 没有任何东西,也就是说,当pipe理对象被销毁时,期望shell proc会被closures。
  • 使用kill命令杀死在shell上运行的所有进程(这是可行的),然后用system("kill #{@shell[2]")杀死shell本身。 这没有效果。
  • 在上面使用-9。 这使得shell进程不存在。

当ruby程序退出时,所有的shell都会closures,但是我想在程序运行的时候杀掉它们。 任何人都遇到过这样的事情?

问题是僵尸。 对真的。

所有Unix风格的内核都会一直等到有人等待。 (这是为了跟踪PID,退出状态,以及其他一些东西)。它们被称为僵尸并在ps(1)列表中具有Z状态。 你不能杀他们,因为他们已经死了。 当你等待他们时,他们就会消失。

所以这里是如何清理你的@shell对象:

 @shell[0].close @shell[1].close begin Process.wait @shell[2] rescue PTY::ChildExited end 

您可能不需要救援块,具体取决于您是否有更高级别的图层捕捉异常过于广泛。 (叹气,像我的irb。)

顺便说一句,当Ruby程序退出时,你的进程终于消失的原因是因为那么僵尸也变成了一个孤儿(没有父进程),shell或者init(8)最终会等待所有的孤儿。