如何在 Puma 上使用 Sinatra 清理 defunct/zombie 进程或关闭长 运行 popen

How to cleanup defunct/zombie processes or close long running popen with Sinatra on Puma

我的 ruby sinatra 应用程序中有以下内容可以即时传输大型 tar 文件,效果很好,但每个请求都会留下一个 defunct/zombie 子进程。一旦浏览器弹出保存文件对话框,进程就会失效。

我在 Puma 2.12.2

运行

我尝试了系统调用并在块中使用 popen,但它会在 tar 命令完成之前关闭进程和 returns,因此客户端收到一个空文件。

有什么想法可以自动清理已失效的子进程或保留 io 对象的句柄但仍然 return 它以便它 tar 流式传输到客户端?

get '/:dir_name' do
    headers['Content-Type']="application/octet-stream"
    headers["Content-Disposition"]="attachment;filename=#{params[:dir_name]}.tar"
    IO.popen("tar -C /home/my/files -cf - #{params[:dir_name]}")
end

上面的代码似乎产生了两个子进程:一个用于正确关闭的 tar 命令;另一个用于还有一个已经不存在了。

当 popen 在下面的代码中分离时,不存在的进程不会出现,并且 tar 命令仍然作为服务器的子进程正确附加。

get '/:dir_name' do
    headers['Content-Type']="application/octet-stream"
    headers["Content-Disposition"]="attachment;filename=#{params[:dir_name]}.tar"
    io = IO.popen("tar -C /home/my/files -cf - #{params[:dir_name]}")
    Process.detach(io.pid)
    return io
end