Double fork and stdin

I wrote this code to run my process in a daemon. The goal is to start this process, even if I close its parent. Now I would like to write something in my stdin. What should I do? Here is the code.

def daemonize(cmd, options = {}) rd, wr = IO.pipe p1 = Process.fork { Process.setsid p2 = Process.fork { $0 = cmd #Name of the command pidfile = File.new(options[:pid_file], 'w') pidfile.chmod( 0644 ) pidfile.puts "#{Process.pid}" pidfile.close Dir.chdir(ENV["PWD"] = options[:working_dir].to_s) if options[:working_dir] File.umask 0000 STDIN.reopen '/dev/null' STDOUT.reopen '/dev/null', 'a' STDERR.reopen STDOUT Signal.trap("USR1") do Console.show 'I just received a USR1', 'warning' end ::Kernel.exec(*Shellwords.shellwords(cmd)) #Executing the command in the parent process exit } raise 'Fork failed!' if p2 == -1 Process.detach(p2) # divorce p2 from parent process (p1) rd.close wr.write p2 wr.close exit } raise 'Fork failed!' if p1 == -1 Process.detach(p1) # divorce p1 from parent process (shell) wr.close daemon_id = rd.read.to_i rd.close daemon_id end 

Is there a way to re-open stdin in something like pipe instead of / dev / null in which I could write?

+4
source share
1 answer

How about fifteen? On linux, you can use the mkfifo command:

 $ mkfifo /tmp/mypipe 

Then you can re-open STDIN on this channel:

 STDIN.reopen '/tmp/mypipe' # Do read-y things 

All that can be written to this channel:

 $ echo "roflcopter" > /tmp/mypipe 

allows you to read data by the ruby โ€‹โ€‹process.

(Update) Caution with Lock

Since fifos locks until it is read and written (for example, reading is blocked if there is no write, and vice versa), it is best to handle multiple threads. One thread must do the reading, passing data to the queue, and the other should handle this input. Here is an example of this situation:

 require 'thread' input = Queue.new threads = [] # Read from the fifo and add to an input queue (glorified array) threads << Thread.new(input) do |ip| STDIN.reopen 'mypipe' loop do if line = STDIN.gets puts "Read: #{line}" ip.push line end end end # Handle the input passed by the reader thread threads << Thread.new(input) do |ip| loop do puts "Ouput: #{ip.pop}" end end threads.map(&:join) 
+2
source

Source: https://habr.com/ru/post/1496557/


All Articles