在 Rails 应用程序上从 Ruby 启动一个进程并在不离开僵尸进程的情况下将其杀死
Starting a process and killing it from Ruby on Rails app without leaving zombie process
我正在 Rails 应用程序上开发 Ruby。部分功能是通过串行端口启动和关闭与 Modbus 从站的连接,获取数据并将其存储到数据库中。此外,我在 python 中制作了一个脚本,它完全满足我的需要,因此我不想重新发明轮子并将其重写为 Ruby。
我的想法是启动一个将执行 python 脚本的进程,并在不再需要时终止该进程。
我启动进程如下,所以我可以访问它的pid:
def start
...
@@pids[ object.id ] = IO.popen("python ./python_script_name.py").pid
...
@@pids 是一个散列,它存储所有启动进程的 pids,键为 object.id(假设每个对象只能启动一个进程)
当我想关闭连接时,我会像这样终止进程:
def stop
...
pid = @@pids[ object.id ]
system("kill #{pid}")
这导致僵尸进程(在ps aux | grep python
之后可见):
[python] <defunct>
我试图将 SIGCHLD
信号发送到 rails 应用程序(因为它是之前调用的 python 脚本的父级)但它不起作用。
我想补充一点,我可能需要经常 call/kill 这个过程,所以它会导致大量的僵尸进程。
如何在不留下僵尸进程的情况下终止进程?
问题不在 python 脚本中 - 默认情况下可以正确处理信号(实施 signal
模块后没有变化)。
问题出在 ruby 脚本中。终止进程后,其父进程(在本例中为 rails 服务器)需要以某种方式知道它已被终止。为此,有一个 wait
函数。来自 ruby 文档:
The parent process should use Process.wait to collect the termination status of its child
因此,要正确处理杀死子进程,需要遵循:
def stop
...
pid = @@pids[ object.id ]
Process.kill( 15, pid )
Process.wait( pid )
...
我正在 Rails 应用程序上开发 Ruby。部分功能是通过串行端口启动和关闭与 Modbus 从站的连接,获取数据并将其存储到数据库中。此外,我在 python 中制作了一个脚本,它完全满足我的需要,因此我不想重新发明轮子并将其重写为 Ruby。
我的想法是启动一个将执行 python 脚本的进程,并在不再需要时终止该进程。
我启动进程如下,所以我可以访问它的pid:
def start
...
@@pids[ object.id ] = IO.popen("python ./python_script_name.py").pid
...
@@pids 是一个散列,它存储所有启动进程的 pids,键为 object.id(假设每个对象只能启动一个进程)
当我想关闭连接时,我会像这样终止进程:
def stop
...
pid = @@pids[ object.id ]
system("kill #{pid}")
这导致僵尸进程(在ps aux | grep python
之后可见):
[python] <defunct>
我试图将 SIGCHLD
信号发送到 rails 应用程序(因为它是之前调用的 python 脚本的父级)但它不起作用。
我想补充一点,我可能需要经常 call/kill 这个过程,所以它会导致大量的僵尸进程。
如何在不留下僵尸进程的情况下终止进程?
问题不在 python 脚本中 - 默认情况下可以正确处理信号(实施 signal
模块后没有变化)。
问题出在 ruby 脚本中。终止进程后,其父进程(在本例中为 rails 服务器)需要以某种方式知道它已被终止。为此,有一个 wait
函数。来自 ruby 文档:
The parent process should use Process.wait to collect the termination status of its child
因此,要正确处理杀死子进程,需要遵循:
def stop
...
pid = @@pids[ object.id ]
Process.kill( 15, pid )
Process.wait( pid )
...