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

mir*_*cop 3 ruby linux kill process pty

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

@shell = PTY.spawn 'env PS1="\w>" TERM=dumb COLUMNS=63 LINES=21 sh -i'
Run Code Online (Sandbox Code Playgroud)

在以后的某个时间点,我想销毁该实例并杀死相关的shell进程。可悲的是,我什么也无法正常工作。这是我尝试过的方法,按照工作的可能性排序:

  • 没什么,就是说当管理对象被销毁时,shell proc不会关闭。
  • 使用kill命令杀死外壳程序上运行的所有进程(此方法有效),然后使用杀死外壳程序本身system("kill #{@shell[2]")。这没有作用。
  • 在上面使用-9。这使Shell进程失效。

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

Dig*_*oss 5

问题是僵尸。对真的。

所有Unix风格的内核都将其保留下来,直到有人等待。(这是为了跟踪PID,退出状态和其他一些东西。)它们被称为僵尸,在ps(1)列表中具有Z状态。您无法杀死它们,因为它们已经死了。他们在您等待时消失。

因此,这是清理@shell对象的方法:

@shell[0].close
@shell[1].close
begin
  Process.wait @shell[2]
rescue PTY::ChildExited
end
Run Code Online (Sandbox Code Playgroud)

您可能不需要急救块,具体取决于您是否具有较高的层来广泛捕获异常。(叹气,像我的irb。)

顺便说一句,当Ruby程序退出时,您的进程最终消失的原因是,然后僵尸也变成了一个孤儿(无父进程),而shell或init(8)最终将等待所有孤儿。

  • 至少,Unix开发人员将以他们的经验为所有死去的孤立的僵尸外壳消失的经验作好准备。 (2认同)