我正在开发Ruby on Rails应用程序。部分功能是通过串口启动和关闭与Modbus从站的连接,获取数据并将其存储到数据库中。我也在python中创建了一个完全符合我需要的脚本,所以我不想重新发明轮子并将其重写为Ruby。
我的想法是启动一个执行python脚本的进程,并在不再需要时终止进程。
我按照以下步骤开始,所以我可以访问它的pid:
def start
...
@@pids[ object.id ] = IO.popen("python ./python_script_name.py").pid
...
@@ pids是一个哈希,它存储所有已启动的进程'密钥为object.id的pids(假设每个对象只能启动一个进程)
当我想要关闭连接时,我会杀死这个过程:
def stop
...
pid = @@pids[ object.id ]
system("kill #{pid}")
这导致僵尸进程(在ps aux | grep python
之后可见):
[python] <defunct>
我尝试将SIGCHLD
信号发送到rails应用程序(因为它是之前调用的python脚本的父代),但它不起作用。
我想补充一点,我可能需要经常调用/终止这个过程,这样会导致大量的僵尸进程。
如何在不离开僵尸进程的情况下杀死进程?
答案 0 :(得分:1)
python脚本中没有问题 - 默认情况下信号处理正确(实现signal
模块后没有变化)。
问题出在ruby脚本中。杀死一个进程后,它的父进程(在这种情况下为rails服务器)需要知道它被杀死了。为此,有一个wait
函数。来自ruby文档:
父进程应使用Process.wait来收集其子进程的终止状态
因此要正确处理杀死子进程,需要遵循:
def stop
...
pid = @@pids[ object.id ]
Process.kill( 15, pid )
Process.wait( pid )
...