문제

I'm trying to programmatically spawn a Puma process then kill it via sending it TERM.

To do this I'm using Process.spawn which returns a pid. This PID is not the PID of the puma process but rather the PID of a shell command that spawns puma

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

Now I can run ps aux | grep puma and I can see it is running

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

However you'll notice as I mentioned before the PID returned 10711 is not listed. It is actually a (sh) process

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

Now back to Ruby land. When I try to terminate puma via Process.kill('TERM', pid) the shell process is terminated but puma continues to run in the background. Puma never receives SIGTERM.

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

Is there another way to consistently spawn and kill puma from inside Ruby? Any clues why the spawned process isn't sending signals to it's child (puma). Is this a bug in my OS, Ruby, or Puma? Perhaps this is expected behavior?

This is my app.ru https://gist.github.com/schneems/18c216cc159772c80361

올바른 솔루션이 없습니다

다른 팁

The quickest hack is to use 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"

This replaces the shell with the invoked process.

However, you should never use Process.spawn with a shell command. When combined with variables, it leads to surprising, insecure and unpredictable behavior. Instead, you should separate the arguments and set up the redirection yourself:

# 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")

This avoids the shell in the first place.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top