3

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

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

在稍后的某个时间点,我想销毁这个实例并杀死相关的 shell 进程。可悲的是,我无法让任何东西正常工作。这是我尝试过的,按概率工作:

  • 没有什么,也就是说,当管理对象被破坏时,期望 shell proc 被关闭。
  • 使用 kill 命令杀死在 shell 上运行的所有进程(这有效),然后使用system("kill #{@shell[2]"). 这没有效果。
  • 在上面使用 -9。这使 shell 进程失效。

当 ruby​​ 程序退出时,所有的 shell 都会关闭,但我想在保持程序运行的同时杀死它们。有人遇到过这样的事情吗?

4

1 回答 1

5

问题是僵尸。对真的。

所有 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) 最终将等待所有孤儿。

于 2011-06-10T19:57:30.050 回答