开发者

Ruby run two processes, output results to terminal, and end safely

In Ruby, I'm running a system("command here") that is constantly watching changes for files, similar to tail. I'd like my program to continue to run and not halt at the system() call. Is there a way in Ruby to create another proces开发者_开发技巧s so both can run independently, output results to the terminal, and then when you exit the program all processes the application created are removed?


Just combine spawn and waitall:

spawn 'sleep 6'
spawn 'sleep 8'
Process.waitall


You don't want to use system as that waits for the process to complete. You could use spawn instead and then wait for the processes (to avoid zombies). Then, when you want to exit, send a SIGTERM to your spawned processes. You could also use fork to launch your child processes but spawn is probably easier if you're using external programs.

You could also use process groups instead of tracking all the process IDs, then a single Process.kill('TERM', -process_group_id) call would take care of things. Your child processes should end up in the same process group but there is Process.setpgid if you need it.

Here's an example that uses fork (easier to get it all wrapped in one package that way).

def launch(id, sleep_for)
    pid = Process.fork do
        while(true)
            puts "#{id}, pgid = #{Process.getpgid(Process.pid())}, pid = #{Process.pid()}"
            sleep(sleep_for)
        end
    end
    # No zombie processes please.
    Process.wait(pid, Process::WNOHANG)
    pid
end

# These just forward the signals to the whole process group and
# then immediately exit.
pgid = Process.getpgid(Process.pid())
Signal.trap('TERM') { Process.kill('TERM', -pgid); exit }
Signal.trap('INT' ) { Process.kill('INT',  -pgid); exit }

launch('a', 5)
launch('b', 3)
while(true)
    puts "p, pgid = #{Process.getpgid(Process.pid())}, pid = #{Process.pid()}"
    sleep 2
end

If you run that in one terminal and then kill it from another (using the shell's kill command)you'll see that the children are also killed. If you remove the "forward this signal to the whole process group" Signal.trap stuff, then a simple SIGTERM will leave the children still running.

All of this assumes that you're working on some sort of Unixy system (such as Linux or OSX), YMMV anywhere else.


One more vote for using Spawn. We use it in Production a lot and it's very stable.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜