I'm continuing the revival of one of my previous projects and in the process noticed some provisioning shell scripts were getting a bit unwieldy so I decided to rewrite them in Ruby. The choice wasn't an accident. Most people reach for Python to rewrite shell scripts but Ruby in my opinion is a much better choice. It has better process and thread management support out of the box and it is much easier to execute and capture process output with Ruby than Python.
But anyway, my main issue wasn't with the process output but with random failures during the provisioning process. Instead of figuring out what the issue was I decided to write a very basic supervisor loop to make sure the processes I wanted to stay up after provisioning actually stayed up. So in my provisioning script I used the double fork and exec pattern
# Provisioning logic # ... Process.fork do Process.setsid p = Process.fork do STDIN.reopen '/dev/null' STDOUT.reopen '/dev/null', 'a' STDERR.reopen '/dev/null', 'a' loop do # Monitoring logic end end Process.detach(p) end
Most of this is Unix arcana. I actually don't really know why we need to fork twice and why we need to call
Process.setsid but I know that's what Unix wants so that's what Unix gets.