Ruby 2.4

Open3

module Open3

Open3授予您在运行其他程序时访问stdin,stdout,stderr和一个线程以等待子进程。您可以像Process.spawn一样指定程序的各种属性,重定向,当前目录等。

  • #popen3:stdin,stdout,stderr的管道

  • #popen2:stdin,stdout的管道

  • #popen2e:用于标准输入的管道,合并的标准输出和标准错误

  • #capture3:为stdin提供一个字符串; 为stdout,stderr获取字符串

  • #capture2:为stdin提供一个字符串; 获取stdout的字符串

  • #capture2e:为stdin提供一个字符串; 为合并的stdout和stderr获取一个字符串

  • #pipeline_rw:管道的第一个stdin和管道的最后stdout

  • #pipeline_r:管道的最后stdout的管道

  • #pipeline_w:管道的第一个stdin

  • #pipeline_start:无需等待就可以运行管道

  • #pipeline:运行管道并等待其完成

公共类方法

capture2(*cmd, stdin_data: nil, binmode: false, **opts) Show source

#capture2捕获命令的标准输出。

stdout_str, status = Open3.capture2([env,] cmd... [, opts])

参数env,cmd和opts被传递给#popen3,除了opts[:stdin_data]opts[:binmode]。请参阅Process.spawn。

如果opts[:stdin_data]指定,则发送到命令的标准输入。

如果opts[:binmode]为真,则内部管道设置为二进制模式。

例:

# factor is a command for integer factorization. o, s = Open3.capture2("factor", :stdin_data=>"42") p o #=> "42: 2 3 7\n" # generate x**2 graph in png using gnuplot. gnuplot_commands = <<"End" set terminal png plot x**2, "-" with lines 1 14 2 1 3 8 4 5 e End image, s = Open3.capture2("gnuplot", :stdin_data=>gnuplot_commands, :binmode=>true)

# File lib/open3.rb, line 304 def capture2(*cmd, stdin_data: nil, binmode: false, **opts) popen2(*cmd, opts) {|i, o, t| if binmode i.binmode o.binmode end out_reader = Thread.new { o.read } if stdin_data begin i.write stdin_data rescue Errno::EPIPE end end i.close [out_reader.value, t.value] } end

capture2e(*cmd, stdin_data: nil, binmode: false, **opts) Show source

#capture2e捕获命令的标准输出和标准错误。

stdout_and_stderr_str, status = Open3.capture2e([env,] cmd... [, opts])

参数env,cmd和opts被传递给#popen3,除了opts[:stdin_data]opts[:binmode]。请参阅Process.spawn。

如果opts[:stdin_data]指定,则发送到命令的标准输入。

如果opts[:binmode]为真,则内部管道设置为二进制模式。

例:

# capture make log make_log, s = Open3.capture2e("make")

# File lib/open3.rb, line 339 def capture2e(*cmd, stdin_data: nil, binmode: false, **opts) popen2e(*cmd, opts) {|i, oe, t| if binmode i.binmode oe.binmode end outerr_reader = Thread.new { oe.read } if stdin_data begin i.write stdin_data rescue Errno::EPIPE end end i.close [outerr_reader.value, t.value] } end

capture3(*cmd, stdin_data: '', binmode: false, **opts) Show source

#capture3捕获命令的标准输出和标准错误。

stdout_str, stderr_str, status = Open3.capture3([env,] cmd... [, opts])

参数env,cmd和opts被传递给#popen3,除了opts[:stdin_data]opts[:binmode]。请参阅Process.spawn。

如果opts[:stdin_data]指定,则发送到命令的标准输入。

如果opts[:binmode]为真,则内部管道设置为二进制模式。

例子:

# dot is a command of graphviz. graph = <<'End' digraph g { a -> b } End drawn_graph, dot_log = Open3.capture3("dot -v", :stdin_data=>graph) o, e, s = Open3.capture3("echo abc; sort >&2", :stdin_data=>"foo\nbar\nbaz\n") p o #=> "abc\n" p e #=> "bar\nbaz\nfoo\n" p s #=> #<Process::Status: pid 32682 exit 0> # generate a thumbnail image using the convert command of ImageMagick. # However, if the image is really stored in a file, # system("convert", "-thumbnail", "80", "png:#{filename}", "png:-") is better # because of reduced memory consumption. # But if the image is stored in a DB or generated by the gnuplot Open3.capture2 example, # Open3.capture3 should be considered. # image = File.read("/usr/share/openclipart/png/animals/mammals/sheep-md-v0.1.png", :binmode=>true) thumbnail, err, s = Open3.capture3("convert -thumbnail 80 png:- png:-", :stdin_data=>image, :binmode=>true) if s.success? STDOUT.binmode; print thumbnail end

# File lib/open3.rb, line 256 def capture3(*cmd, stdin_data: '', binmode: false, **opts) popen3(*cmd, opts) {|i, o, e, t| if binmode i.binmode o.binmode e.binmode end out_reader = Thread.new { o.read } err_reader = Thread.new { e.read } begin i.write stdin_data rescue Errno::EPIPE end i.close [out_reader.value, err_reader.value, t.value] } end

pipeline(*cmds, **opts) Show source

#pipeline以管道形式启动命令列表。它等待命令的完成。第一个命令的stdin和最后一个命令的stdout都没有创建管道。

status_list = Open3.pipeline(cmd1, cmd2, ... [, opts])

每个cmd是一个字符串或一个数组。如果它是一个数组,则元素将传递给Process.spawn。

cmd: commandline command line string which is passed to a shell [env, commandline, opts] command line string which is passed to a shell [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) Note that env and opts are optional, as Process.spawn.

例:

fname = "/usr/share/man/man1/ruby.1.gz" p Open3.pipeline(["zcat", fname], "nroff -man", "less") #=> [#<Process::Status: pid 11817 exit 0>, # #<Process::Status: pid 11820 exit 0>, # #<Process::Status: pid 11828 exit 0>] fname = "/usr/share/man/man1/ls.1.gz" Open3.pipeline(["zcat", fname], "nroff -man", "colcrt") # convert PDF to PS and send to a printer by lpr pdf_file = "paper.pdf" printer = "printer-name" Open3.pipeline(["pdftops", pdf_file, "-"], ["lpr", "-P#{printer}"]) # count lines Open3.pipeline("sort", "uniq -c", :in=>"names.txt", :out=>"count") # cyclic pipeline r,w = IO.pipe w.print "ibase=14\n10\n" Open3.pipeline("bc", "tee /dev/tty", :in=>r, :out=>w) #=> 14 # 18 # 22 # 30 # 42 # 58 # 78 # 106 # 202

# File lib/open3.rb, line 601 def pipeline(*cmds, **opts) pipeline_run(cmds, opts, [], []) {|ts| ts.map(&:value) } end

pipeline_r(*cmds, **opts, &block) Show source

#pipeline_r starts a list of commands as a pipeline with a pipe which connects to stdout of the last command.

Open3.pipeline_r(cmd1, cmd2, ... [, opts]) {|last_stdout, wait_threads| ... } last_stdout, wait_threads = Open3.pipeline_r(cmd1, cmd2, ... [, opts]) ... last_stdout.close

每个cmd是一个字符串或一个数组。如果它是一个数组,则元素将传递给Process.spawn。

cmd: commandline command line string which is passed to a shell [env, commandline, opts] command line string which is passed to a shell [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) Note that env and opts are optional, as for Process.spawn.

例:

Open3.pipeline_r("zcat /var/log/apache2/access.log.*.gz", [{"LANG"=>"C"}, "grep", "GET /favicon.ico"], "logresolve") {|o, ts| o.each_line {|line| ... } } Open3.pipeline_r("yes", "head -10") {|o, ts| p o.read #=> "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\n" p ts[0].value #=> #<Process::Status: pid 24910 SIGPIPE (signal 13)> p ts[1].value #=> #<Process::Status: pid 24913 exit 0> }

# File lib/open3.rb, line 450 def pipeline_r(*cmds, **opts, &block) out_r, out_w = IO.pipe opts[:out] = out_w pipeline_run(cmds, opts, [out_w], [out_r], &block) end

pipeline_rw(*cmds, **opts, &block) Show source

#pipeline_rw使用连接到第一个命令的stdin和最后一个命令的stdout的管道作为管道启动命令列表。

Open3.pipeline_rw(cmd1, cmd2, ... [, opts]) {|first_stdin, last_stdout, wait_threads| ... } first_stdin, last_stdout, wait_threads = Open3.pipeline_rw(cmd1, cmd2, ... [, opts]) ... first_stdin.close last_stdout.close

每个cmd是一个字符串或一个数组。如果它是一个数组,则元素将传递给Process.spawn。

cmd: commandline command line string which is passed to a shell [env, commandline, opts] command line string which is passed to a shell [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) Note that env and opts are optional, as for Process.spawn.

传递给Process.spawn的选项通过合并opts,数组的最后一个哈希元素以及每个命令之间的管道规范来构造。

例:

Open3.pipeline_rw("tr -dc A-Za-z", "wc -c") {|i, o, ts| i.puts "All persons more than a mile high to leave the court." i.close p o.gets #=> "42\n" } Open3.pipeline_rw("sort", "cat -n") {|stdin, stdout, wait_thrs| stdin.puts "foo" stdin.puts "bar" stdin.puts "baz" stdin.close # send EOF to sort. p stdout.read #=> " 1\tbar\n 2\tbaz\n 3\tfoo\n" }

# File lib/open3.rb, line 400 def pipeline_rw(*cmds, **opts, &block) in_r, in_w = IO.pipe opts[:in] = in_r in_w.sync = true out_r, out_w = IO.pipe opts[:out] = out_w pipeline_run(cmds, opts, [in_r, out_w], [in_w, out_r], &block) end

pipeline_start(*cmds, **opts, &block) Show source

#pipeline_start作为管道启动一个命令列表。第一个命令的stdin和最后一个命令的stdout都没有创建管道。

Open3.pipeline_start(cmd1, cmd2, ... [, opts]) {|wait_threads| ... } wait_threads = Open3.pipeline_start(cmd1, cmd2, ... [, opts]) ...

每个cmd是一个字符串或一个数组。如果它是一个数组,则元素将传递给Process.spawn。

cmd: commandline command line string which is passed to a shell [env, commandline, opts] command line string which is passed to a shell [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) Note that env and opts are optional, as for Process.spawn.

例:

# Run xeyes in 10 seconds. Open3.pipeline_start("xeyes") {|ts| sleep 10 t = ts[0] Process.kill("TERM", t.pid) p t.value #=> #<Process::Status: pid 911 SIGTERM (signal 15)> } # Convert pdf to ps and send it to a printer. # Collect error message of pdftops and lpr. pdf_file = "paper.pdf" printer = "printer-name" err_r, err_w = IO.pipe Open3.pipeline_start(["pdftops", pdf_file, "-"], ["lpr", "-P#{printer}"], :err=>err_w) {|ts| err_w.close p err_r.read # error messages of pdftops and lpr. }

# File lib/open3.rb, line 539 def pipeline_start(*cmds, **opts, &block) if block pipeline_run(cmds, opts, [], [], &block) else ts, = pipeline_run(cmds, opts, [], []) ts end end

pipeline_w(*cmds, **opts, &block) Show source

#pipeline_w使用连接到第一个命令的stdin的管道将一系列命令作为管道启动。

Open3.pipeline_w(cmd1, cmd2, ... [, opts]) {|first_stdin, wait_threads| ... } first_stdin, wait_threads = Open3.pipeline_w(cmd1, cmd2, ... [, opts]) ... first_stdin.close

每个cmd是一个字符串或一个数组。如果它是一个数组,则元素将传递给Process.spawn。

cmd: commandline command line string which is passed to a shell [env, commandline, opts] command line string which is passed to a shell [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) Note that env and opts are optional, as for Process.spawn.

例:

Open3.pipeline_w("bzip2 -c", :out=>"/tmp/hello.bz2") {|i, ts| i.puts "hello" }

# File lib/open3.rb, line 486 def pipeline_w(*cmds, **opts, &block) in_r, in_w = IO.pipe opts[:in] = in_r in_w.sync = true pipeline_run(cmds, opts, [in_r], [in_w], &block) end

popen2(*cmd, **opts, &block) Show source

#popen2与#popen3类似,不同之处在于它不会为标准错误流创建管道。

块形式:

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

非块形式:

stdin, stdout, wait_thr = Open3.popen2([env,] cmd... [, opts]) ... stdin.close # stdin and stdout should be closed explicitly in this form. stdout.close

有关可选散列参数envopts,请参阅Process.spawn 。

例:

Open3.popen2("wc -c") {|i,o,t| i.print "answer to life the universe and everything" i.close p o.gets #=> "42\n" } Open3.popen2("bc -q") {|i,o,t| i.puts "obase=13" i.puts "6 * 9" p o.gets #=> "42\n" } Open3.popen2("dc") {|i,o,t| i.print "42P" i.close p o.read #=> "*" }

# File lib/open3.rb, line 138 def popen2(*cmd, **opts, &block) in_r, in_w = IO.pipe opts[:in] = in_r in_w.sync = true out_r, out_w = IO.pipe opts[:out] = out_w popen_run(cmd, opts, [in_r, out_w], [in_w, out_r], &block) end

popen2e(*cmd, **opts, &block) Show source

#popen2e类似于#popen3,只是它将标准输出流和标准错误流合并。

块形式:

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

非块形式:

stdin, stdout_and_stderr, wait_thr = Open3.popen2e([env,] cmd... [, opts]) ... stdin.close # stdin and stdout_and_stderr should be closed explicitly in this form. stdout_and_stderr.close

有关可选散列参数envopts,请参阅Process.spawn 。

例:

# check gcc warnings source = "foo.c" Open3.popen2e("gcc", "-Wall", source) {|i,oe,t| oe.each {|line| if /warning/ =~ line ... end } }

# File lib/open3.rb, line 181 def popen2e(*cmd, **opts, &block) in_r, in_w = IO.pipe opts[:in] = in_r in_w.sync = true out_r, out_w = IO.pipe opts[[:out, :err]] = out_w popen_run(cmd, opts, [in_r, out_w], [in_w, out_r], &block) end

popen3(*cmd, **opts, &block) Show source

打开stdin,stdout和stderr流并启动外部可执行文件。另外,创建一个等待启动的进程的线程。线程有一个pid方法和一个线程变量:pid,它是启动进程的pid。

块形式:

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. }

非块形式:

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.

参数env,cmd和opts传递给Process.spawn。一个命令行字符串和一个参数字符串列表可以被接受,如下所示:

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| ... }

如果最后一个参数opts是散列,则它将被识别为Process.spawn的选项。

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

wait_thr.value等待进程的终止。块表单也会在返回时等待进程。

关闭标准输入,标准输出和标准错误不会等待进程完成。

你应该小心避免死锁。由于管道是固定长度的缓冲区,#popen3(“prog”){| i,o,e,t | 如果程序在stderr上产生太多输出,则会导致死锁。您应该同时读取stdout和stderr(使用线程或IO.select)。但是,如果您不需要标准输出,则可以使用#popen2。如果合并stdout和stderr输出不成问题,则可以使用#popen2e。如果你真的需要stdout和stderr输出作为单独的字符串,你可以考虑#capture3。

# File lib/open3.rb, line 83 def popen3(*cmd, **opts, &block) in_r, in_w = IO.pipe opts[:in] = in_r in_w.sync = true out_r, out_w = IO.pipe opts[:out] = out_w err_r, err_w = IO.pipe opts[:err] = err_w popen_run(cmd, opts, [in_r, out_w, err_w], [in_w, out_r, err_r], &block) end

私有实例方法

capture2(*cmd, stdin_data: nil, binmode: false, **opts) Show source

#capture2捕获命令的标准输出。

stdout_str, status = Open3.capture2([env,] cmd... [, opts])

参数env,cmd和opts被传递给#popen3,除了opts[:stdin_data]opts[:binmode]。请参阅Process.spawn。

如果opts[:stdin_data]指定,则发送到命令的标准输入。

如果opts[:binmode]为真,则内部管道设置为二进制模式。

例:

# factor is a command for integer factorization. o, s = Open3.capture2("factor", :stdin_data=>"42") p o #=> "42: 2 3 7\n" # generate x**2 graph in png using gnuplot. gnuplot_commands = <<"End" set terminal png plot x**2, "-" with lines 1 14 2 1 3 8 4 5 e End image, s = Open3.capture2("gnuplot", :stdin_data=>gnuplot_commands, :binmode=>true)

# File lib/open3.rb, line 304 def capture2(*cmd, stdin_data: nil, binmode: false, **opts) popen2(*cmd, opts) {|i, o, t| if binmode i.binmode o.binmode end out_reader = Thread.new { o.read } if stdin_data begin i.write stdin_data rescue Errno::EPIPE end end i.close [out_reader.value, t.value] } end

capture2e(* cmd,stdin_data:nil,binmode:false,** opts)显示源代码

#capture2e捕获命令的标准输出和标准错误。

stdout_and_stderr_str, status = Open3.capture2e([env,] cmd... [, opts])

参数env,cmd和opts被传递给#popen3,除了opts[:stdin_data]opts[:binmode]。请参阅Process.spawn。

如果opts[:stdin_data]指定,则发送到命令的标准输入。

如果opts[:binmode]为真,则内部管道设置为二进制模式。

例:

# capture make log make_log, s = Open3.capture2e("make")

# File lib/open3.rb, line 339 def capture2e(*cmd, stdin_data: nil, binmode: false, **opts) popen2e(*cmd, opts) {|i, oe, t| if binmode i.binmode oe.binmode end outerr_reader = Thread.new { oe.read } if stdin_data begin i.write stdin_data rescue Errno::EPIPE end end i.close [outerr_reader.value, t.value] } end

capture3(*cmd, stdin_data: '', binmode: false, **opts) Show source

#capture3捕获命令的标准输出和标准错误。

stdout_str, stderr_str, status = Open3.capture3([env,] cmd... [, opts])

参数env,cmd和opts被传递给#popen3,除了opts[:stdin_data]opts[:binmode]。请参阅Process.spawn。

如果opts[:stdin_data]指定,则发送到命令的标准输入。

如果opts[:binmode]为真,则内部管道设置为二进制模式。

例子:

# dot is a command of graphviz. graph = <<'End' digraph g { a -> b } End drawn_graph, dot_log = Open3.capture3("dot -v", :stdin_data=>graph) o, e, s = Open3.capture3("echo abc; sort >&2", :stdin_data=>"foo\nbar\nbaz\n") p o #=> "abc\n" p e #=> "bar\nbaz\nfoo\n" p s #=> #<Process::Status: pid 32682 exit 0> # generate a thumbnail image using the convert command of ImageMagick. # However, if the image is really stored in a file, # system("convert", "-thumbnail", "80", "png:#{filename}", "png:-") is better # because of reduced memory consumption. # But if the image is stored in a DB or generated by the gnuplot Open3.capture2 example, # Open3.capture3 should be considered. # image = File.read("/usr/share/openclipart/png/animals/mammals/sheep-md-v0.1.png", :binmode=>true) thumbnail, err, s = Open3.capture3("convert -thumbnail 80 png:- png:-", :stdin_data=>image, :binmode=>true) if s.success? STDOUT.binmode; print thumbnail end

# File lib/open3.rb, line 256 def capture3(*cmd, stdin_data: '', binmode: false, **opts) popen3(*cmd, opts) {|i, o, e, t| if binmode i.binmode o.binmode e.binmode end out_reader = Thread.new { o.read } err_reader = Thread.new { e.read } begin i.write stdin_data rescue Errno::EPIPE end i.close [out_reader.value, err_reader.value, t.value] } end

pipeline(*cmds, **opts) Show source

#pipeline以管道形式启动命令列表。它等待命令的完成。第一个命令的stdin和最后一个命令的stdout都没有创建管道。

status_list = Open3.pipeline(cmd1, cmd2, ... [, opts])

每个cmd是一个字符串或一个数组。如果它是一个数组,则元素将传递给Process.spawn。

cmd: commandline command line string which is passed to a shell [env, commandline, opts] command line string which is passed to a shell [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) Note that env and opts are optional, as Process.spawn.

例:

fname = "/usr/share/man/man1/ruby.1.gz" p Open3.pipeline(["zcat", fname], "nroff -man", "less") #=> [#<Process::Status: pid 11817 exit 0>, # #<Process::Status: pid 11820 exit 0>, # #<Process::Status: pid 11828 exit 0>] fname = "/usr/share/man/man1/ls.1.gz" Open3.pipeline(["zcat", fname], "nroff -man", "colcrt") # convert PDF to PS and send to a printer by lpr pdf_file = "paper.pdf" printer = "printer-name" Open3.pipeline(["pdftops", pdf_file, "-"], ["lpr", "-P#{printer}"]) # count lines Open3.pipeline("sort", "uniq -c", :in=>"names.txt", :out=>"count") # cyclic pipeline r,w = IO.pipe w.print "ibase=14\n10\n" Open3.pipeline("bc", "tee /dev/tty", :in=>r, :out=>w) #=> 14 # 18 # 22 # 30 # 42 # 58 # 78 # 106 # 202

# File lib/open3.rb, line 601 def pipeline(*cmds, **opts) pipeline_run(cmds, opts, [], []) {|ts| ts.map(&:value) } end

pipeline_r(*cmds, **opts, &block) Show source

#pipeline_r使用连接到最后一个命令的标准输出的管道将一系列命令作为管道启动。

Open3.pipeline_r(cmd1, cmd2, ... [, opts]) {|last_stdout, wait_threads| ... } last_stdout, wait_threads = Open3.pipeline_r(cmd1, cmd2, ... [, opts]) ... last_stdout.close

每个cmd是一个字符串或一个数组。如果它是一个数组,则元素将传递给Process.spawn。

cmd: commandline command line string which is passed to a shell [env, commandline, opts] command line string which is passed to a shell [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) Note that env and opts are optional, as for Process.spawn.

例:

Open3.pipeline_r("zcat /var/log/apache2/access.log.*.gz", [{"LANG"=>"C"}, "grep", "GET /favicon.ico"], "logresolve") {|o, ts| o.each_line {|line| ... } } Open3.pipeline_r("yes", "head -10") {|o, ts| p o.read #=> "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\n" p ts[0].value #=> #<Process::Status: pid 24910 SIGPIPE (signal 13)> p ts[1].value #=> #<Process::Status: pid 24913 exit 0> }

# File lib/open3.rb, line 450 def pipeline_r(*cmds, **opts, &block) out_r, out_w = IO.pipe opts[:out] = out_w pipeline_run(cmds, opts, [out_w], [out_r], &block) end

pipeline_rw(*cmds, **opts, &block) Show source

#pipeline_rw使用连接到第一个命令的stdin和最后一个命令的stdout的管道作为管道启动命令列表。

Open3.pipeline_rw(cmd1, cmd2, ... [, opts]) {|first_stdin, last_stdout, wait_threads| ... } first_stdin, last_stdout, wait_threads = Open3.pipeline_rw(cmd1, cmd2, ... [, opts]) ... first_stdin.close last_stdout.close

每个cmd是一个字符串或一个数组。如果它是一个数组,则元素将传递给Process.spawn。

cmd: commandline command line string which is passed to a shell [env, commandline, opts] command line string which is passed to a shell [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) Note that env and opts are optional, as for Process.spawn.

传递给Process.spawn的选项通过合并opts,数组的最后一个哈希元素以及每个命令之间的管道规范来构造。

例:

Open3.pipeline_rw("tr -dc A-Za-z", "wc -c") {|i, o, ts| i.puts "All persons more than a mile high to leave the court." i.close p o.gets #=> "42\n" } Open3.pipeline_rw("sort", "cat -n") {|stdin, stdout, wait_thrs| stdin.puts "foo" stdin.puts "bar" stdin.puts "baz" stdin.close # send EOF to sort. p stdout.read #=> " 1\tbar\n 2\tbaz\n 3\tfoo\n" }

# File lib/open3.rb, line 400 def pipeline_rw(*cmds, **opts, &block) in_r, in_w = IO.pipe opts[:in] = in_r in_w.sync = true out_r, out_w = IO.pipe opts[:out] = out_w pipeline_run(cmds, opts, [in_r, out_w], [in_w, out_r], &block) end

pipeline_start(*cmds, **opts, &block) Show source

#pipeline_start作为管道启动一个命令列表。第一个命令的stdin和最后一个命令的stdout都没有创建管道。

Open3.pipeline_start(cmd1, cmd2, ... [, opts]) {|wait_threads| ... } wait_threads = Open3.pipeline_start(cmd1, cmd2, ... [, opts]) ...

每个cmd是一个字符串或一个数组。如果它是一个数组,则元素将传递给Process.spawn。

cmd: commandline command line string which is passed to a shell [env, commandline, opts] command line string which is passed to a shell [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) Note that env and opts are optional, as for Process.spawn.

例:

# Run xeyes in 10 seconds. Open3.pipeline_start("xeyes") {|ts| sleep 10 t = ts[0] Process.kill("TERM", t.pid) p t.value #=> #<Process::Status: pid 911 SIGTERM (signal 15)> } # Convert pdf to ps and send it to a printer. # Collect error message of pdftops and lpr. pdf_file = "paper.pdf" printer = "printer-name" err_r, err_w = IO.pipe Open3.pipeline_start(["pdftops", pdf_file, "-"], ["lpr", "-P#{printer}"], :err=>err_w) {|ts| err_w.close p err_r.read # error messages of pdftops and lpr. }

# File lib/open3.rb, line 539 def pipeline_start(*cmds, **opts, &block) if block pipeline_run(cmds, opts, [], [], &block) else ts, = pipeline_run(cmds, opts, [], []) ts end end

pipeline_w(*cmds, **opts, &block) Show source

#pipeline_w使用连接到第一个命令的stdin的管道将一系列命令作为管道启动。

Open3.pipeline_w(cmd1, cmd2, ... [, opts]) {|first_stdin, wait_threads| ... } first_stdin, wait_threads = Open3.pipeline_w(cmd1, cmd2, ... [, opts]) ... first_stdin.close

每个cmd是一个字符串或一个数组。如果它是一个数组,则元素将传递给Process.spawn。

cmd: commandline command line string which is passed to a shell [env, commandline, opts] command line string which is passed to a shell [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) Note that env and opts are optional, as for Process.spawn.

例:

Open3.pipeline_w("bzip2 -c", :out=>"/tmp/hello.bz2") {|i, ts| i.puts "hello" }

# File lib/open3.rb, line 486 def pipeline_w(*cmds, **opts, &block) in_r, in_w = IO.pipe opts[:in] = in_r in_w.sync = true pipeline_run(cmds, opts, [in_r], [in_w], &block) end

popen2(*cmd, **opts, &block) Show source

#popen2与#popen3类似,不同之处在于它不会为标准错误流创建管道。

块形式:

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

非块形式:

stdin, stdout, wait_thr = Open3.popen2([env,] cmd... [, opts]) ... stdin.close # stdin and stdout should be closed explicitly in this form. stdout.close

有关可选散列参数envopts,请参阅Process.spawn 。

例:

Open3.popen2("wc -c") {|i,o,t| i.print "answer to life the universe and everything" i.close p o.gets #=> "42\n" } Open3.popen2("bc -q") {|i,o,t| i.puts "obase=13" i.puts "6 * 9" p o.gets #=> "42\n" } Open3.popen2("dc") {|i,o,t| i.print "42P" i.close p o.read #=> "*" }

# File lib/open3.rb, line 138 def popen2(*cmd, **opts, &block) in_r, in_w = IO.pipe opts[:in] = in_r in_w.sync = true out_r, out_w = IO.pipe opts[:out] = out_w popen_run(cmd, opts, [in_r, out_w], [in_w, out_r], &block) end

popen2e(*cmd, **opts, &block) Show source

#popen2e类似于#popen3,只是它将标准输出流和标准错误流合并。

块形式:

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

非块形式:

stdin, stdout_and_stderr, wait_thr = Open3.popen2e([env,] cmd... [, opts]) ... stdin.close # stdin and stdout_and_stderr should be closed explicitly in this form. stdout_and_stderr.close

有关可选散列参数envopts,请参阅Process.spawn 。

例:

# check gcc warnings source = "foo.c" Open3.popen2e("gcc", "-Wall", source) {|i,oe,t| oe.each {|line| if /warning/ =~ line ... end } }

# File lib/open3.rb, line 181 def popen2e(*cmd, **opts, &block) in_r, in_w = IO.pipe opts[:in] = in_r in_w.sync = true out_r, out_w = IO.pipe opts[[:out, :err]] = out_w popen_run(cmd, opts, [in_r, out_w], [in_w, out_r], &block) end

popen3(*cmd, **opts, &block) Show source

打开stdin,stdout和stderr流并启动外部可执行文件。另外,创建一个等待启动的进程的线程。线程有一个pid方法和一个线程变量:pid,它是启动进程的pid。

块形式:

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. }

非块形式:

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.

参数env,cmd和opts传递给Process.spawn。一个命令行字符串和一个参数字符串列表可以被接受,如下所示:

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| ... }

如果最后一个参数opts是散列,则它将被识别为Process.spawn的选项。

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

wait_thr.value等待进程的终止。块表单也会在返回时等待进程。

关闭标准输入,标准输出和标准错误不会等待进程完成。

你应该小心避免死锁。由于管道是固定长度的缓冲区,#popen3(“prog”){| i,o,e,t | 如果程序在stderr上产生太多输出,则会导致死锁。您应该同时读取stdout和stderr(使用线程或IO.select)。但是,如果您不需要标准输出,则可以使用#popen2。如果合并stdout和stderr输出不成问题,则可以使用#popen2e。如果你真的需要stdout和stderr输出作为单独的字符串,你可以考虑#capture3。

# File lib/open3.rb, line 83 def popen3(*cmd, **opts, &block) in_r, in_w = IO.pipe opts[:in] = in_r in_w.sync = true out_r, out_w = IO.pipe opts[:out] = out_w err_r, err_w = IO.pipe opts[:err] = err_w popen_run(cmd, opts, [in_r, out_w, err_w], [in_w, out_r, err_r], &block) end