@@ -899,48 +899,84 @@ def capture2e(*cmd)
899899 end
900900 module_function :capture2e
901901
902- # Open3.pipeline_rw starts a list of commands as a pipeline with pipes
903- # which connect to stdin of the first command and stdout of the last command.
904- #
905- # Open3.pipeline_rw(cmd1, cmd2, ... [, opts]) {|first_stdin, last_stdout, wait_threads|
906- # ...
907- # }
902+ # :call-seq:
903+ # Open3.pipeline_rw([env, ] *cmds, options = {}) -> [first_stdin, last_stdout, wait_threads]
908904 #
909- # first_stdin, last_stdout, wait_threads = Open3.pipeline_rw(cmd1, cmd2, ... [, opts])
910- # ...
911- # first_stdin.close
912- # last_stdout.close
905+ # Basically a wrapper for
906+ # {Process.spawn}[https://docs.ruby-lang.org/en/master/Process.html#method-c-spawn]
907+ # that:
913908 #
914- # Each cmd is a string or an array.
915- # If it is an array, the elements are passed to Process.spawn.
909+ # - Creates a child process for each of the given +cmds+
910+ # by calling Process.spawn.
911+ # - Pipes the +stdout+ from each child to the +stdin+ of the next child,
912+ # or, for the first child, from the caller's +stdin+,
913+ # or, for the last child, to the caller's +stdout+.
916914 #
917- # cmd:
918- # commandline command line string which is passed to a shell
919- # [env, commandline, opts] command line string which is passed to a shell
920- # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell)
921- # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell)
915+ # The method does not wait for child processes to exit,
916+ # so the caller must do so.
922917 #
923- # Note that env and opts are optional, as for Process.spawn.
918+ # With no block given, returns a 3-element array containing:
924919 #
925- # The options to pass to Process.spawn are constructed by merging
926- # +opts+, the last hash element of the array, and
927- # specifications for the pipes between each of the commands .
920+ # - The +stdin+ stream of the first child process.
921+ # - The +stdout+ stream of the last child process.
922+ # - An array of the wait threads for all of the child processes .
928923 #
929924 # Example:
930925 #
931- # Open3.pipeline_rw("tr -dc A-Za-z", "wc -c") {|i, o, ts|
932- # i.puts "All persons more than a mile high to leave the court."
933- # i.close
934- # p o.gets #=> "42\n"
935- # }
936- #
937- # Open3.pipeline_rw("sort", "cat -n") {|stdin, stdout, wait_thrs|
938- # stdin.puts "foo"
939- # stdin.puts "bar"
940- # stdin.puts "baz"
941- # stdin.close # send EOF to sort.
942- # p stdout.read #=> " 1\tbar\n 2\tbaz\n 3\tfoo\n"
943- # }
926+ # first_stdin, last_stdout, wait_threads = Open3.pipeline_rw('sort', 'cat -n')
927+ # # => [#<IO:fd 20>, #<IO:fd 21>, [#<Process::Waiter:0x000055e8de29ab40 sleep>, #<Process::Waiter:0x000055e8de29a690 sleep>]]
928+ # first_stdin.puts("foo\nbar\nbaz")
929+ # first_stdin.close # Send EOF to sort.
930+ # puts last_stdout.read
931+ # wait_threads.each do |wait_thread|
932+ # wait_thread.join
933+ # end
934+ #
935+ # Output:
936+ #
937+ # 1 bar
938+ # 2 baz
939+ # 3 foo
940+ #
941+ # With a block given, calls the block with the +stdin+ stream of the first child,
942+ # the +stdout+ stream of the last child,
943+ # and an array of the wait processes:
944+ #
945+ # Open3.pipeline_rw('sort', 'cat -n') do |first_stdin, last_stdout, wait_threads|
946+ # first_stdin.puts "foo\nbar\nbaz"
947+ # first_stdin.close # send EOF to sort.
948+ # puts last_stdout.read
949+ # wait_threads.each do |wait_thread|
950+ # wait_thread.join
951+ # end
952+ # end
953+ #
954+ # Output:
955+ #
956+ # 1 bar
957+ # 2 baz
958+ # 3 foo
959+ #
960+ # Like Process.spawn, this method has potential security vulnerabilities
961+ # if called with untrusted input;
962+ # see {Command Injection}[rdoc-ref:command_injection.rdoc].
963+ #
964+ # If the first argument is a hash, it becomes leading argument +env+
965+ # in each call to Process.spawn;
966+ # see {Execution Environment}[https://docs.ruby-lang.org/en/master/Process.html#module-Process-label-Execution+Environment].
967+ #
968+ # If the last argument is a hash, it becomes trailing argument +options+
969+ # in each call to Process.spawn;
970+ # see {Execution Options}[https://docs.ruby-lang.org/en/master/Process.html#module-Process-label-Execution+Options].
971+ #
972+ # Each remaining argument in +cmds+ is one of:
973+ #
974+ # - A +command_line+: a string that begins with a shell reserved word
975+ # or special built-in, or contains one or more metacharacters.
976+ # - An +exe_path+: the string path to an executable to be called.
977+ # - An array containing a +command_line+ or an +exe_path+,
978+ # along with zero or more string arguments for the command.
979+ #
944980 def pipeline_rw ( *cmds , &block )
945981 if Hash === cmds . last
946982 opts = cmds . pop . dup
@@ -970,7 +1006,9 @@ def pipeline_rw(*cmds, &block)
9701006 # by calling Process.spawn.
9711007 # - Pipes the +stdout+ from each child to the +stdin+ of the next child,
9721008 # or, for the last child, to the caller's +stdout+.
973- # - Waits for all child processes to exit.
1009+ #
1010+ # The method does not wait for child processes to exit,
1011+ # so the caller must do so.
9741012 #
9751013 # With no block given, returns a 2-element array containing:
9761014 #
@@ -979,31 +1017,38 @@ def pipeline_rw(*cmds, &block)
9791017 #
9801018 # Example:
9811019 #
982- # Open3.pipeline_r('ls', 'grep R')
983- # # => [#<IO:fd 5>, [#<Process::Waiter:0x00005638280167b8 sleep>, #<Process::Waiter:0x0000563828015480 dead>]]
1020+ # last_stdout, wait_threads = Open3.pipeline_r('ls', 'grep R')
1021+ # # => [#<IO:fd 5>, [#<Process::Waiter:0x000055e8de2f9898 dead>, #<Process::Waiter:0x000055e8de2f94b0 sleep>]]
1022+ # puts last_stdout.read
1023+ # wait_threads.each do |wait_thread|
1024+ # wait_thread.join
1025+ # end
1026+ #
1027+ # Output:
1028+ #
1029+ # Rakefile
1030+ # README.md
9841031 #
9851032 # With a block given, calls the block with the +stdout+ stream
9861033 # of the last child process,
9871034 # and an array of the wait processes:
9881035 #
989- # Open3.pipeline_r('ls', 'grep R') do |x, ts|
990- # puts x.read
991- # p ts
1036+ # Open3.pipeline_r('ls', 'grep R') do |last_stdout, wait_threads|
1037+ # puts last_stdout.read
1038+ # wait_threads.each do |wait_thread|
1039+ # wait_thread.join
1040+ # end
9921041 # end
9931042 #
9941043 # Output:
9951044 #
9961045 # Rakefile
9971046 # README.md
998- # [#<Process::Waiter:0x000055f1d78d76f0 sleep>, #<Process::Waiter:0x000055f1d78d7358 dead>]
9991047 #
10001048 # Like Process.spawn, this method has potential security vulnerabilities
10011049 # if called with untrusted input;
10021050 # see {Command Injection}[rdoc-ref:command_injection.rdoc].
10031051 #
1004- # Unlike Process.spawn, this method waits for the child processes to exit
1005- # before returning, so the caller need not do so.
1006- #
10071052 # If the first argument is a hash, it becomes leading argument +env+
10081053 # in each call to Process.spawn;
10091054 # see {Execution Environment}[https://docs.ruby-lang.org/en/master/Process.html#module-Process-label-Execution+Environment].
@@ -1046,7 +1091,9 @@ def pipeline_r(*cmds, &block)
10461091 # by calling Process.spawn.
10471092 # - Pipes the +stdout+ from each child to the +stdin+ of the next child,
10481093 # or, for the first child, pipes the caller's +stdout+ to the child's +stdin+.
1049- # - Waits for all child processes to exit.
1094+ #
1095+ # The method does not wait for child processes to exit,
1096+ # so the caller must do so.
10501097 #
10511098 # With no block given, returns a 2-element array containing:
10521099 #
@@ -1055,36 +1102,42 @@ def pipeline_r(*cmds, &block)
10551102 #
10561103 # Example:
10571104 #
1058- # p Open3.pipeline_r(
1059- # ['ruby', '-e', 'print "Foo"'],
1060- # ['ruby', '-e', 'print STDIN.read + "Bar"']
1061- # )
1062- # [#<IO:fd 5>, [#<Process::Waiter:0x00005568cad44a08 sleep>, #<Process::Waiter:0x00005568cad44508 run>]]
1105+ # first_stdin, wait_threads = Open3.pipeline_w('sort', 'cat -n')
1106+ # # => [#<IO:fd 7>, [#<Process::Waiter:0x000055e8de928278 run>, #<Process::Waiter:0x000055e8de923e80 run>]]
1107+ # first_stdin.puts("foo\nbar\nbaz")
1108+ # first_stdin.close # Send EOF to sort.
1109+ # wait_threads.each do |wait_thread|
1110+ # wait_thread.join
1111+ # end
1112+ #
1113+ # Output:
1114+ #
1115+ # 1 bar
1116+ # 2 baz
1117+ # 3 foo
10631118 #
10641119 # With a block given, calls the block with the +stdin+ stream
10651120 # of the first child process,
10661121 # and an array of the wait processes:
10671122 #
1068- # Open3.pipeline_r(
1069- # ['ruby', '-e', 'print "Foo"'],
1070- # ['ruby', '-e', 'print STDIN.read + "Bar"']
1071- # ) do |x, ts |
1072- # puts x.read
1073- # p ts
1123+ # Open3.pipeline_w('sort', 'cat -n') do |first_stdin, wait_threads|
1124+ # first_stdin.puts("foo\nbar\nbaz")
1125+ # first_stdin.close # Send EOF to sort.
1126+ # wait_threads.each do |wait_thread |
1127+ # wait_thread.join
1128+ # end
10741129 # end
10751130 #
10761131 # Output:
10771132 #
1078- # FooBar
1079- # [#<Process::Waiter:0x000055628e2ebbc0 dead>, #<Process::Waiter:0x000055628e2eb7b0 sleep>]
1133+ # 1 bar
1134+ # 2 baz
1135+ # 3 foo
10801136 #
10811137 # Like Process.spawn, this method has potential security vulnerabilities
10821138 # if called with untrusted input;
10831139 # see {Command Injection}[rdoc-ref:command_injection.rdoc].
10841140 #
1085- # Unlike Process.spawn, this method waits for the child processes to exit
1086- # before returning, so the caller need not do so.
1087- #
10881141 # If the first argument is a hash, it becomes leading argument +env+
10891142 # in each call to Process.spawn;
10901143 # see {Execution Environment}[https://docs.ruby-lang.org/en/master/Process.html#module-Process-label-Execution+Environment].
@@ -1116,49 +1169,65 @@ def pipeline_w(*cmds, &block)
11161169 end
11171170 module_function :pipeline_w
11181171
1119- # Open3.pipeline_start starts a list of commands as a pipeline.
1120- # No pipes are created for stdin of the first command and
1121- # stdout of the last command.
1172+ # :call-seq:
1173+ # Open3.pipeline_start([env, ] *cmds, options = {}) -> [wait_threads]
1174+ #
1175+ # Basically a wrapper for
1176+ # {Process.spawn}[https://docs.ruby-lang.org/en/master/Process.html#method-c-spawn]
1177+ # that:
11221178 #
1123- # Open3.pipeline_start(cmd1, cmd2, ... [, opts]) {|wait_threads|
1124- # .. .
1125- # }
1179+ # - Creates a child process for each of the given +cmds+
1180+ # by calling Process.spawn .
1181+ # - Does not wait for child processes to exit.
11261182 #
1127- # wait_threads = Open3.pipeline_start(cmd1, cmd2, ... [, opts])
1128- # .. .
1183+ # With no block given, returns an array of the wait threads
1184+ # for all of the child processes .
11291185 #
1130- # Each cmd is a string or an array.
1131- # If it is an array, the elements are passed to Process.spawn.
1186+ # Example:
11321187 #
1133- # cmd:
1134- # commandline command line string which is passed to a shell
1135- # [env, commandline, opts] command line string which is passed to a shell
1136- # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell)
1137- # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell)
1188+ # wait_threads = Open3.pipeline_start('ls', 'grep R')
1189+ # # => [#<Process::Waiter:0x000055e8de9d2bb0 run>, #<Process::Waiter:0x000055e8de9d2890 run>]
1190+ # wait_threads.each do |wait_thread|
1191+ # wait_thread.join
1192+ # end
11381193 #
1139- # Note that env and opts are optional, as for Process.spawn.
1194+ # Output:
11401195 #
1141- # Example:
1196+ # Rakefile
1197+ # README.md
1198+ #
1199+ # With a block given, calls the block with an array of the wait processes:
1200+ #
1201+ # Open3.pipeline_start('ls', 'grep R') do |wait_threads|
1202+ # wait_threads.each do |wait_thread|
1203+ # wait_thread.join
1204+ # end
1205+ # end
1206+ #
1207+ # Output:
11421208 #
1143- # # Run xeyes in 10 seconds.
1144- # Open3.pipeline_start("xeyes") {|ts|
1145- # sleep 10
1146- # t = ts[0]
1147- # Process.kill("TERM", t.pid)
1148- # p t.value #=> #<Process::Status: pid 911 SIGTERM (signal 15)>
1149- # }
1150- #
1151- # # Convert pdf to ps and send it to a printer.
1152- # # Collect error message of pdftops and lpr.
1153- # pdf_file = "paper.pdf"
1154- # printer = "printer-name"
1155- # err_r, err_w = IO.pipe
1156- # Open3.pipeline_start(["pdftops", pdf_file, "-"],
1157- # ["lpr", "-P#{printer}"],
1158- # :err=>err_w) {|ts|
1159- # err_w.close
1160- # p err_r.read # error messages of pdftops and lpr.
1161- # }
1209+ # Rakefile
1210+ # README.md
1211+ #
1212+ # Like Process.spawn, this method has potential security vulnerabilities
1213+ # if called with untrusted input;
1214+ # see {Command Injection}[rdoc-ref:command_injection.rdoc].
1215+ #
1216+ # If the first argument is a hash, it becomes leading argument +env+
1217+ # in each call to Process.spawn;
1218+ # see {Execution Environment}[https://docs.ruby-lang.org/en/master/Process.html#module-Process-label-Execution+Environment].
1219+ #
1220+ # If the last argument is a hash, it becomes trailing argument +options+
1221+ # in each call to Process.spawn;
1222+ # see {Execution Options}[https://docs.ruby-lang.org/en/master/Process.html#module-Process-label-Execution+Options].
1223+ #
1224+ # Each remaining argument in +cmds+ is one of:
1225+ #
1226+ # - A +command_line+: a string that begins with a shell reserved word
1227+ # or special built-in, or contains one or more metacharacters.
1228+ # - An +exe_path+: the string path to an executable to be called.
1229+ # - An array containing a +command_line+ or an +exe_path+,
1230+ # along with zero or more string arguments for the command.
11621231 #
11631232 def pipeline_start ( *cmds , &block )
11641233 if Hash === cmds . last
@@ -1187,28 +1256,23 @@ def pipeline_start(*cmds, &block)
11871256 # by calling Process.spawn.
11881257 # - Pipes the +stdout+ from each child to the +stdin+ of the next child,
11891258 # or, for the last child, to the caller's +stdout+.
1190- # - Waits for all child processes to exit.
1259+ # - Waits for the child processes to exit.
11911260 # - Returns an array of Process::Status objects (one for each child).
11921261 #
1193- # A simple example :
1262+ # Example :
11941263 #
1195- # Open3.pipeline('ls', 'grep [A-Z] ')
1196- # # => [#<Process::Status: pid 1343895 exit 0>, #<Process::Status: pid 1343897 exit 0>]
1264+ # wait_threads = Open3.pipeline('ls', 'grep R ')
1265+ # # => [#<Process::Status: pid 2139200 exit 0>, #<Process::Status: pid 2139202 exit 0>]
11971266 #
11981267 # Output:
11991268 #
1200- # Gemfile
1201- # LICENSE.txt
12021269 # Rakefile
12031270 # README.md
12041271 #
12051272 # Like Process.spawn, this method has potential security vulnerabilities
12061273 # if called with untrusted input;
12071274 # see {Command Injection}[rdoc-ref:command_injection.rdoc].
12081275 #
1209- # Unlike Process.spawn, this method waits for the child process to exit
1210- # before returning, so the caller need not do so.
1211- #
12121276 # If the first argument is a hash, it becomes leading argument +env+
12131277 # in each call to Process.spawn;
12141278 # see {Execution Environment}[https://docs.ruby-lang.org/en/master/Process.html#module-Process-label-Execution+Environment].
0 commit comments