I'd like to spawn a process mycmd from Ruby:
I have Ruby blocking until mycmd writes BOOTED, but I can't get mycmd to hang around as a daemon.
stdin, stdout, stderr, process_status = Open3.popen3("mycmd --whatever")
puts "Starting mycmd, pid=#{process_status.pid}"
# Block until mycmd prints "BOOTED":
stdout.each_line do |line|
break if line.include?("BOOTED")
end
Process.detatch(process_status.pid)
# And now our ruby process exits, killing mycmd as it dies
# How can I keep mycmd running even when Ruby exits?
Things I've tried:
Open3.popen3("nohup mycmd")
# mycmd exits with rubyOpen3.popen3("mycmd &")
# mycmd exits with rubyOpen3.popen3("mycmd > /dev/null 2>&1")
# mycmd does NOT exit when ruby exits (yay), but I can't read from stdout to wait for BOOTEDThe likely problem here is that the standard output streamsof your child process are owned by the parent process. Once the parent process is killed, the stdout
and stderr
descriptors in the child process are invalid, and any attempt to use them will fail with an error such as:
Broken pipe @ rb_io_flush_raw - <STDOUT>
Since it sounds like you're attempting to launch the child as a daemon, it would be best to avoid trying to directly capture the stdout
or stderr
of the child. As mentioned in the comments by Casper, setting the child stdout
and stderr
to a file is reasonable, and this could also be done in the child process via STDOUT.reopen(...)