Process.spawn子级没有收到TERM

时间:2014-03-03 20:04:42

标签: ruby bash shell process

我正在尝试以编程方式生成Puma进程,然后通过发送它来终止它。

要做到这一点,我正在使用Process.spawn返回一个pid。这个PID不是美洲狮过程的PID,而是产生美洲狮的shell命令的PID

pid = Process.spawn "bundle exec puma test/fixtures/app.ru -w 3 -t 1:1 -p 0 -e development > test/logs/puma_1961_1393875906.917352.log"
=> 10711

现在我可以运行ps aux | grep puma,我可以看到它正在运行

schneems        10719   0.0  0.1  2488912   7564 s000  S+    1:57PM   0:00.02 puma: cluster worker: 10712
schneems        10718   0.0  0.1  2488912   7524 s000  S+    1:57PM   0:00.02 puma: cluster worker: 10712
schneems        10717   0.0  0.1  2489936   7652 s000  S+    1:57PM   0:00.02 puma: cluster worker: 10712
schneems        10712   0.0  0.3  2478612  24596 s000  S+    1:57PM   0:00.47 ruby /Users/schneems/.gem/ruby/2.1.1/bin/puma test/fixtures/app.ru -w 3 -t 1:1 -p 0 -e development

但是你会注意到我之前提到的PID 10711没有列出。它实际上是一个(sh)过程

$ ps -p 10711
  PID TTY           TIME CMD
10711 ttys000    0:00.00 (sh)

现在回到Ruby的土地上。当我尝试通过Process.kill('TERM', pid)终止puma时,shell进程终止,但是puma继续在后台运行。 Puma永远不会收到SIGTERM

puts pid
10711
Process.kill("TERM", pid)
=> 1
Process.wait(pid)

还有另一种方法可以从Ruby内部生成并杀死puma吗?任何线索为什么产生的过程不向它的孩子发送信号(美洲狮)。这是我的操作系统,Ruby或Puma中的错误吗?也许这是预期的行为?

这是我的app.ru https://gist.github.com/schneems/18c216cc159772c80361

1 个答案:

答案 0 :(得分:1)

最快的黑客是使用exec

# Bad quick fix
pid = Process.spawn "exec bundle exec puma test/fixtures/app.ru -w 3 -t 1:1 -p 0 -e development > test/logs/puma_1961_1393875906.917352.log"

这将使用调用的进程替换shell。

但是,永远不要将Process.spawn与shell命令一起使用。当与变量结合时,会导致令人惊讶,不安全和不可预测的行为。相反,您应该分离参数并自己设置重定向:

# Good solution
pid = Process.spawn("bundle", "exec", "puma", "test/fixtures/app.ru", "-w", "3", "-t", "1:1", "-p", "0", "-e", "development", :out=>"test/logs/puma_1961_1393875906.917352.log")

这首先避免了shell。