popen3

popen3(*cmd, &block)
Class Public methods

Open stdin, stdout, and stderr streams and start external executable. In addition, a thread for waiting the started process is noticed. The thread has a pid method and thread variable :pid which is the pid of the started process.

Block form:

Open3.popen3([env,] cmd... [, opts]) {|stdin, stdout, stderr, wait_thr|
  pid = wait_thr.pid # pid of the started process.
  ...
  exit_status = wait_thr.value # Process::Status object returned.
}

Non-block form:

stdin, stdout, stderr, wait_thr = Open3.popen3([env,] cmd... [, opts])
pid = wait_thr[:pid]  # pid of the started process.
...
stdin.close  # stdin, stdout and stderr should be closed explicitly in this form.
stdout.close
stderr.close
exit_status = wait_thr.value  # Process::Status object returned.

The parameters cmd... is passed to Process.spawn. So a commandline string and list of argument strings can be accepted as follows.

Open3.popen3("echo abc") {|i, o, e, t| ... }
Open3.popen3("echo", "abc") {|i, o, e, t| ... }
Open3.popen3(["echo", "argv0"], "abc") {|i, o, e, t| ... }

If the last parameter, opts, is a Hash, it is recognized as an option for Process.spawn.

Open3.popen3("pwd", :chdir=>"/") {|i,o,e,t|
  p o.read.chomp #=> "/"
}

wait_thr.value waits the termination of the process. The block form also waits the process when it returns.

Closing stdin, stdout and stderr does not wait the process.

You should be careful to avoid deadlocks. Since pipes are fixed length buffer, ::popen3(âprogâ) {|i, o, e, t| o.read } deadlocks if the program generates many output on stderr. You should be read stdout and stderr simultaneously (using thread or IO.select). However if you don't need stderr output, ::popen2 can be used. If merged stdout and stderr output is not a problem, you can use ::popen2e. If you really needs stdout and stderr output as separate strings, you can consider ::capture3.

doc_ruby_on_rails
2015-04-24 15:19:16
Comments
Leave a Comment

Please login to continue.